diff --git a/.circleci/config.yml b/.circleci/config.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml old mode 100644 new mode 100755 index e783cb0a8..b0816f403 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,8 +8,8 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s, r7800, l1000, zbt4019] - OMR_KERNEL: [5.4, 5.14] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, cm520-79f, x86_64, ubnt-erx, r4s, r7800, l1000, zbt4019] + OMR_KERNEL: [5.4, 5.15] runs-on: ubuntu-latest continue-on-error: true @@ -73,6 +73,8 @@ jobs: env: OMR_TARGET: ${{ matrix.OMR_TARGET }} run: | + cat "feeds/openmptcprouter/openmptcprouter/files/etc/init.d/getserveratboot" + sudo rm -rf "feeds/openmptcprouter/openmptcprouter/files/etc/init.d/getserveratboot" >/dev/null 2>&1 || true make IGNORE_ERRORS=m -C $OMR_TARGET/source package/{compile,install,index} -j$(nproc) || make IGNORE_ERRORS=m -C $OMR_TARGET/source package/{compile,install,index} -j1 V=s - name: Build image working-directory: ../../omr diff --git a/.github/workflows/workspace.code-workspace b/.github/workflows/workspace.code-workspace old mode 100644 new mode 100755 diff --git a/README.md b/README.md index e9edfcd2c..e92835abd 100755 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is the OpenWrt OpenMPTCProuter feed containing all modified and necessary packages to build the OpenMPTCProuter image. -For More information, see [https://github.com/suyuan168/3grouter](https://github.com/suyuan168/3grouter) and [https://www.openmptcprouter.com](https://www.openmptcprouter.com/). +For More information, see [https://github.com/ysurac/openmptcprouter](https://github.com/ysurac/openmptcprouter) and [https://www.openmptcprouter.com](https://www.openmptcprouter.com/). ## Glorytun @@ -66,7 +66,7 @@ Added support to gateway set by user for 6in4. Used for IPv6 over the glorytun I ## luci-omr-bypass -*Source:* [https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-omr-bypass](https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-omr-bypass) +*Source:* [https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-omr-bypass](https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-omr-bypass) *Description:* Luci interface to bypass domains, IPs and networks with shadowsocks @@ -74,7 +74,7 @@ Domains, IPs, networks and protocol (using DPI) added are bypassed when shadowso ## omr-tracker -*Source:* [https://github.com/suyuan168/3grouter-feeds/tree/master/omr-tracker](https://github.com/suyuan168/3grouter-feeds/tree/master/omr-tracker) +*Source:* [https://github.com/Ysurac/openmptcprouter-feeds/tree/master/omr-tracker](https://github.com/Ysurac/openmptcprouter-feeds/tree/master/omr-tracker) *Description:* Track connection status. This check if gateway is up then check if the connection work. If it's not working this execute scripts. This also detect if ShadowSocks is up or not. @@ -82,7 +82,7 @@ This is used for OpenMPTCProuter failover. ## luci-omr-tracker -*Source:* [https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-omr-tracker](https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-omr-tracker) +*Source:* [https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-omr-tracker](https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-omr-tracker) *Description:* Luci interface to omr-tracker @@ -90,37 +90,37 @@ Interface to omr-tracker. ## luci-app-iperf -*Source:* [https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-iperf](https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-iperf) +*Source:* [https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-iperf](https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-iperf) *Description:* Luci interface to iPerf ## omr-6in4 -*Source:* [https://github.com/suyuan168/3grouter-feeds/tree/master/omr-6in4](https://github.com/suyuan168/3grouter-feeds/tree/master/omr-6in4) +*Source:* [https://github.com/Ysurac/openmptcprouter-feeds/tree/master/omr-6in4](https://github.com/Ysurac/openmptcprouter-feeds/tree/master/omr-6in4) *Description:* Set tunnel configuration by tracking tunnel configuration. ## omr-update -*Source:* [https://github.com/suyuan168/3grouter-feeds/tree/master/omr-update](https://github.com/suyuan168/3grouter-feeds/tree/master/omr-update) +*Source:* [https://github.com/Ysurac/openmptcprouter-feeds/tree/master/omr-update](https://github.com/Ysurac/openmptcprouter-feeds/tree/master/omr-update) *Description:* Update old config with new settings. ## luci-app-mptcp -*Source:* [https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-mptcp](https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-mptcp) +*Source:* [https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-mptcp](https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-mptcp) *Description:* Luci interface for all MPTCP settings ## luci-app-openmptcprouter -*Source:* [https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-openmptcprouter](https://github.com/suyuan168/3grouter-feeds/tree/master/luci-app-openmptcprouter) +*Source:* [https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-openmptcprouter](https://github.com/Ysurac/openmptcprouter-feeds/tree/master/luci-app-openmptcprouter) *Description:* Wizard for OpenMPTCProuter settings and status page ## mptcp -*Source:* [https://github.com/suyuan168/3grouter-feeds/tree/master/mptcp](https://github.com/suyuan168/3grouter-feeds/tree/master/mptcp) +*Source:* [https://github.com/Ysurac/openmptcprouter-feeds/tree/master/mptcp](https://github.com/Ysurac/openmptcprouter-feeds/tree/master/mptcp) *Description:* This package set all MPTCP settings diff --git a/aquantia/Makefile b/aquantia/Makefile old mode 100644 new mode 100755 diff --git a/cryptodev-linux/Makefile b/cryptodev-linux/Makefile old mode 100644 new mode 100755 diff --git a/fast-classifier/Makefile b/fast-classifier/Makefile old mode 100644 new mode 100755 diff --git a/fast-classifier/src/Makefile b/fast-classifier/src/Makefile old mode 100644 new mode 100755 diff --git a/fast-classifier/src/fast-classifier.c b/fast-classifier/src/fast-classifier.c old mode 100644 new mode 100755 diff --git a/fast-classifier/src/fast-classifier.h b/fast-classifier/src/fast-classifier.h old mode 100644 new mode 100755 diff --git a/fast-classifier/src/nl_classifier_test.c b/fast-classifier/src/nl_classifier_test.c old mode 100644 new mode 100755 diff --git a/fast-classifier/src/sfe.h b/fast-classifier/src/sfe.h old mode 100644 new mode 100755 diff --git a/fast-classifier/src/sfe_backport.h b/fast-classifier/src/sfe_backport.h old mode 100644 new mode 100755 diff --git a/fast-classifier/src/sfe_cm.h b/fast-classifier/src/sfe_cm.h old mode 100644 new mode 100755 diff --git a/fast-classifier/src/userspace_example.c b/fast-classifier/src/userspace_example.c old mode 100644 new mode 100755 diff --git a/glorytun/init b/glorytun/init index 3d549f0aa..1384a0315 100755 --- a/glorytun/init +++ b/glorytun/init @@ -62,6 +62,7 @@ start_instance() { uci -q set network.omrvpn.device=${dev} uci -q commit network fi + _log "starting ${PROG_NAME} ${1} instance $*" procd_open_instance diff --git a/golang/golang-values.mk b/golang/golang-values.mk index 69126a1ed..34c9c1c65 100755 --- a/golang/golang-values.mk +++ b/golang/golang-values.mk @@ -13,10 +13,11 @@ endif # Unset environment variables # There are more magic variables to track down, but ain't nobody got time for that -# From https://golang.org/cmd/go/#hdr-Environment_variables +# From https://pkg.go.dev/cmd/go#hdr-Environment_variables # General-purpose environment variables: unexport \ + GO111MODULE \ GCCGO \ GOARCH \ GOBIN \ @@ -36,6 +37,7 @@ unexport \ # GONOPROXY # GOSUMDB # GONOSUMDB +# GOVCS # Environment variables for use with cgo: unexport \ @@ -63,23 +65,20 @@ unexport \ # Special-purpose environment variables: unexport \ GCCGOTOOLDIR \ + GOEXPERIMENT \ GOROOT_FINAL \ GO_EXTLINK_ENABLED # Unmodified: # GIT_ALLOW_PROTOCOL -# From https://golang.org/cmd/go/#hdr-Module_support -unexport \ - GO111MODULE - -# From https://golang.org/pkg/runtime/#hdr-Environment_Variables +# From https://pkg.go.dev/runtime#hdr-Environment_Variables unexport \ GOGC \ GOMAXPROCS \ GORACE \ GOTRACEBACK -# From https://golang.org/cmd/cgo/#hdr-Using_cgo_with_the_go_command +# From https://pkg.go.dev/cmd/cgo#hdr-Using_cgo_with_the_go_command unexport \ CC_FOR_TARGET \ CXX_FOR_TARGET @@ -111,10 +110,6 @@ unexport \ BOOT_GO_GCFLAGS \ BOOT_GO_LDFLAGS -# From https://golang.org/src/cmd/dist/buildruntime.go -unexport \ - GOEXPERIMENT - # From https://golang.org/src/cmd/dist/buildtool.go unexport \ GOBOOTSTRAP_TOOLEXEC @@ -148,8 +143,11 @@ else endif ifeq ($(GO_ARCH),386) - # ensure binaries can run on older CPUs - GO_386:=387 + ifeq ($(CONFIG_TARGET_x86_geode)$(CONFIG_TARGET_x86_legacy),y) + GO_386:=softfloat + else + GO_386:=sse2 + endif # -fno-plt: causes "unexpected GOT reloc for non-dynamic symbol" errors GO_CFLAGS_TO_REMOVE:=-fno-plt @@ -195,19 +193,23 @@ GO_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mips64||mips64el||mipsel||pow # ASLR/PIE +# From https://golang.org/src/cmd/internal/sys/supported.go GO_PIE_SUPPORTED_OS_ARCH:= \ - android_386 android_amd64 android_arm android_arm64 \ - linux_386 linux_amd64 linux_arm linux_arm64 \ + android_386 android_amd64 android_arm android_arm64 \ + linux_386 linux_amd64 linux_arm linux_arm64 \ \ - windows_386 windows_amd64 windows_arm \ + windows_386 windows_amd64 windows_arm \ + \ + darwin_amd64 darwin_arm64 \ + ios_amd64 ios_arm64 \ \ - darwin_amd64 \ freebsd_amd64 \ \ aix_ppc64 \ \ - linux_ppc64le linux_s390x + linux_ppc64le linux_riscv64 linux_s390x +# From https://golang.org/src/cmd/go/internal/work/init.go go_pie_install_suffix=$(if $(filter $(1),aix_ppc64 windows_386 windows_amd64 windows_arm),,shared) ifneq ($(filter $(GO_HOST_OS_ARCH),$(GO_PIE_SUPPORTED_OS_ARCH)),) @@ -236,7 +238,7 @@ endif # General build info -GO_BUILD_CACHE_DIR:=$(or $(call qstrip,$(CONFIG_GOLANG_BUILD_CACHE_DIR)),$(TOPDIR)/.go-build) +GO_BUILD_CACHE_DIR:=$(or $(call qstrip,$(CONFIG_GOLANG_BUILD_CACHE_DIR)),$(TMP_DIR)/go-build) GO_MOD_CACHE_DIR:=$(DL_DIR)/go-mod-cache GO_MOD_ARGS= \ @@ -249,6 +251,6 @@ GO_GENERAL_BUILD_CONFIG_VARS= \ GO_MOD_ARGS="$(GO_MOD_ARGS)" define Go/CacheCleanup - $(GENERAL_BUILD_CONFIG_VARS) \ + $(GO_GENERAL_BUILD_CONFIG_VARS) \ $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh cache_cleanup endef diff --git a/golang/golang/Makefile b/golang/golang/Makefile index 1c311d571..30979fe7c 100755 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk GO_VERSION_MAJOR_MINOR:=1.17 -GO_VERSION_PATCH:=2 +GO_VERSION_PATCH:=3 PKG_NAME:=golang PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH)) @@ -20,7 +20,7 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \ PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz PKG_SOURCE_URL:=$(GO_SOURCE_URLS) -PKG_HASH:=2255eb3e4e824dd7d5fcdc2e7f84534371c186312e546fb1086a34c17752f431 +PKG_HASH:=705c64251e5b25d5d55ede1039c6aa22bea40a7a931d14c370339853643c3df0 PKG_MAINTAINER:=Jeffery To PKG_LICENSE:=BSD-3-Clause @@ -48,12 +48,13 @@ HOST_GO_VALID_OS_ARCH:= \ freebsd_386 freebsd_amd64 freebsd_arm freebsd_arm64 \ linux_386 linux_amd64 linux_arm linux_arm64 \ openbsd_386 openbsd_amd64 openbsd_arm openbsd_arm64 \ + netbsd_386 netbsd_amd64 netbsd_arm netbsd_arm64 \ + windows_386 windows_amd64 windows_arm windows_arm64 \ \ - netbsd_386 netbsd_amd64 netbsd_arm \ plan9_386 plan9_amd64 plan9_arm \ - windows_386 windows_amd64 windows_arm \ \ darwin_amd64 darwin_arm64 \ + ios_amd64 ios_arm64 \ \ dragonfly_amd64 \ illumos_amd64 \ @@ -64,7 +65,9 @@ HOST_GO_VALID_OS_ARCH:= \ \ linux_ppc64 linux_ppc64le \ linux_mips linux_mipsle linux_mips64 linux_mips64le \ - linux_riscv64 linux_s390x + linux_riscv64 linux_s390x \ + \ + openbsd_mips64 BOOTSTRAP_SOURCE:=go1.4-bootstrap-20171003.tar.gz BOOTSTRAP_SOURCE_URL:=$(GO_SOURCE_URLS) @@ -258,12 +261,14 @@ endif $(eval $(call GoCompiler/AddProfile,Package,$(PKG_BUILD_DIR),$(PKG_GO_PREFIX),$(PKG_GO_VERSION_ID),$(GO_OS_ARCH),$(PKG_GO_INSTALL_SUFFIX))) PKG_GO_ZBOOTSTRAP_MODS:= \ - s/defaultGO386 = `[^`]*`/defaultGO386 = `$(or $(GO_386),387)`/; \ + s/defaultGO386 = `[^`]*`/defaultGO386 = `$(or $(GO_386),sse2)`/; \ s/defaultGOARM = `[^`]*`/defaultGOARM = `$(or $(GO_ARM),5)`/; \ s/defaultGOMIPS = `[^`]*`/defaultGOMIPS = `$(or $(GO_MIPS),hardfloat)`/; \ s/defaultGOMIPS64 = `[^`]*`/defaultGOMIPS64 = `$(or $(GO_MIPS64),hardfloat)`/; \ s/defaultGOPPC64 = `[^`]*`/defaultGOPPC64 = `power8`/; +PKG_GO_ZBOOTSTRAP_PATH:=$(PKG_BUILD_DIR)/src/internal/buildcfg/zbootstrap.go + PKG_GO_VARS= \ GOCACHE="$(GO_BUILD_CACHE_DIR)" \ GOENV=off \ @@ -306,8 +311,17 @@ define Build/Compile $(PKG_GO_VARS) \ ) - $(SED) '$(PKG_GO_ZBOOTSTRAP_MODS)' \ - "$(PKG_BUILD_DIR)/src/cmd/internal/objabi/zbootstrap.go" + $(SED) '$(PKG_GO_ZBOOTSTRAP_MODS)' "$(PKG_GO_ZBOOTSTRAP_PATH)" + + ( \ + if echo 'int main() { return 0; }' | $(TARGET_CC) -o $(PKG_BUILD_DIR)/test-ldso -x c - > /dev/null 2>&1; then \ + LDSO=$$$$( \ + readelf -l $(PKG_BUILD_DIR)/test-ldso | \ + sed -n -e 's/^.*interpreter: \(.*\)[]]/\1/p' \ + ) ; \ + fi ; \ + $(SED) "s,defaultGO_LDSO = \`[^\`]*\`,defaultGO_LDSO = \`$$$$LDSO\`," "$(PKG_GO_ZBOOTSTRAP_PATH)" ; \ + ) @echo "Building target Go second stage" diff --git a/https-dns-proxy/test.sh b/https-dns-proxy/test.sh old mode 100644 new mode 100755 diff --git a/iperf3/Makefile b/iperf3/Makefile old mode 100644 new mode 100755 diff --git a/iperf3/patches/remove-in6_flowlabel_req.patch b/iperf3/patches/remove-in6_flowlabel_req.patch old mode 100644 new mode 100755 diff --git a/iptables-mod-fullconenat/Makefile b/iptables-mod-fullconenat/Makefile deleted file mode 100755 index 279c1eb9a..000000000 --- a/iptables-mod-fullconenat/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright (C) 2018 Chion Tang -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=fullconenat -PKG_RELEASE:=1 - -PKG_SOURCE_DATE:=2019-10-21 -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/Chion82/netfilter-full-cone-nat.git -PKG_SOURCE_VERSION:=0cf3b48fd7d2fa81d0297d1fff12bbd0580fc435 - -PKG_LICENSE:=GPL-2.0 -PKG_LICENSE_FILES:=LICENSE - -include $(INCLUDE_DIR)/package.mk - -define Package/iptables-mod-fullconenat - SUBMENU:=Firewall - SECTION:=net - CATEGORY:=Network - TITLE:=FULLCONENAT iptables extension - DEPENDS:=+iptables +kmod-ipt-fullconenat - MAINTAINER:=Chion Tang -endef - -define Package/iptables-mod-fullconenat/install - $(INSTALL_DIR) $(1)/usr/lib/iptables - $(INSTALL_BIN) $(PKG_BUILD_DIR)/libipt_FULLCONENAT.so $(1)/usr/lib/iptables -endef - -define KernelPackage/ipt-fullconenat - SUBMENU:=Netfilter Extensions - TITLE:=FULLCONENAT netfilter module - DEPENDS:=+kmod-nf-ipt +kmod-nf-nat - MAINTAINER:=Chion Tang - KCONFIG:=CONFIG_NF_CONNTRACK_EVENTS=y CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y - FILES:=$(PKG_BUILD_DIR)/xt_FULLCONENAT.ko -endef - -include $(INCLUDE_DIR)/kernel-defaults.mk - -define Build/Prepare - $(call Build/Prepare/Default) - $(CP) ./files/Makefile $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(BUILDFLAGS)" \ - modules - $(call Build/Compile/Default) -endef - -$(eval $(call BuildPackage,iptables-mod-fullconenat)) -$(eval $(call KernelPackage,ipt-fullconenat)) diff --git a/iptables-mod-fullconenat/README.md b/iptables-mod-fullconenat/README.md deleted file mode 100755 index 4d4909802..000000000 --- a/iptables-mod-fullconenat/README.md +++ /dev/null @@ -1,27 +0,0 @@ -## Netfilter and iptables extension for [FULLCONENAT](https://github.com/Chion82/netfilter-full-cone-nat) target ported to OpenWrt. - -Compile ---- -``` -# cd to OpenWrt source path -# Clone this repo -git clone -b master --single-branch https://github.com/LGA1150/openwrt-fullconenat package/fullconenat -# Select Network -> Firewall -> iptables-mod-fullconenat -make menuconfig -# Compile -make V=s -``` - -Usage ---- -You can apply [this patch](https://github.com/LGA1150/fullconenat-fw3-patch) to OpenWrt's Firewall3 (Recommended). - -Or manually add the following rules to `/etc/firewall.user` -``` -iptables -t nat -A zone_wan_prerouting -j FULLCONENAT -iptables -t nat -A zone_wan_postrouting -j FULLCONENAT -``` - -Workaround for conflicting with module `nf_conntrack_netlink` ---- -This module uses conntrack events to register a callback function. In the same netns, only one callback method can be registered, that causes conflicts with `nf_conntrack_netlink`, which also uses conntrack events. Qualcomm Shortcut FE has introduced a patch to allow multiple callbacks to be registered. To apply, put [this patch](https://github.com/coolsnowwolf/lede/blob/master/target/linux/generic/hack-4.14/952-net-conntrack-events-support-multiple-registrant.patch) into `target/linux/generic/hack-4.14`. diff --git a/iptables-mod-fullconenat/files/Makefile b/iptables-mod-fullconenat/files/Makefile deleted file mode 100755 index da52a2a4e..000000000 --- a/iptables-mod-fullconenat/files/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -libipt_FULLCONENAT.so: libipt_FULLCONENAT.o - $(CC) -shared -lxtables -o $@ $^; -libipt_FULLCONENAT.o: libipt_FULLCONENAT.c - $(CC) ${CFLAGS} -fPIC -D_INIT=$*_init -c -o $@ $<; - -obj-m += xt_FULLCONENAT.o - diff --git a/iptables-mod-fullconenat/patches/000-printk.patch b/iptables-mod-fullconenat/patches/000-printk.patch deleted file mode 100755 index 4e764c5d6..000000000 --- a/iptables-mod-fullconenat/patches/000-printk.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/xt_FULLCONENAT.c b/xt_FULLCONENAT.c -index 9e52eba..8658c5f 100644 ---- a/xt_FULLCONENAT.c -+++ b/xt_FULLCONENAT.c -@@ -702,9 +702,11 @@ static struct xt_target tg_reg[] __read_mostly = { - - static int __init fullconenat_tg_init(void) - { -+ printk(KERN_INFO "xt_FULLCONENAT: RFC3489 Full Cone NAT module\n" -+ "xt_FULLCONENAT: Copyright (C) 2018 Chion Tang \n"); - wq = create_singlethread_workqueue("xt_FULLCONENAT"); - if (wq == NULL) { -- printk("xt_FULLCONENAT: warning: failed to create workqueue\n"); -+ printk(KERN_WARNING "xt_FULLCONENAT: warning: failed to create workqueue\n"); - } - - return xt_register_targets(tg_reg, ARRAY_SIZE(tg_reg)); diff --git a/libmbim/Makefile b/libmbim/Makefile index 505ae7bc6..32c8ef493 100644 --- a/libmbim/Makefile +++ b/libmbim/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libmbim -PKG_VERSION:=1.26.2 +PKG_VERSION:=1.26.0 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.freedesktop.org/software/libmbim -PKG_HASH:=10c77bf5b5eb8c92ba80e9b519923ad9b898362bc8e1928e2bc9a17eeba649af +PKG_HASH:=1e1f0926b22c77210442129eca689722ecf324ab9c9abf421a5c989f46e813cf PKG_MAINTAINER:=Nicholas Smith diff --git a/libqmi/Config.in b/libqmi/Config.in new file mode 100644 index 000000000..6f35b7453 --- /dev/null +++ b/libqmi/Config.in @@ -0,0 +1,16 @@ +menu "Configuration" + depends on PACKAGE_libqmi + +config LIBQMI_WITH_MBIM_QMUX + bool "Include MBIM QMUX service support" + default y + help + Compile libqmi with QMI-over-MBIM support + +config LIBQMI_WITH_QRTR_GLIB + bool "Include QRTR support" + default y + help + Compile libqmi with QRTR support + +endmenu diff --git a/libqmi/Makefile b/libqmi/Makefile new file mode 100644 index 000000000..ee5b69749 --- /dev/null +++ b/libqmi/Makefile @@ -0,0 +1,119 @@ +# +# Copyright (C) 2016 Velocloud Inc. +# Copyright (C) 2016 Aleksander Morgado +# +# This is free software, licensed under the GNU General Public License v2. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=libqmi +PKG_VERSION:=1.30.2 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://www.freedesktop.org/software/libqmi +PKG_HASH:=be01ece0ea2c2194cbea5744bf5aaf06c04ba5fb7ec7887a13116c76d114fedd + +PKG_MAINTAINER:=Nicholas Smith + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/libqmi/config + source "$(SOURCE)/Config.in" +endef + +define Package/libqmi + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:= \ + +glib2 \ + +LIBQMI_WITH_MBIM_QMUX:libmbim \ + +LIBQMI_WITH_QRTR_GLIB:libqrtr-glib + TITLE:=Helper library to talk to QMI enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libqmi + LICENSE:=LGPL-2.0-or-later + LICENSE_FILES:=COPYING.LIB +endef + +define Package/libqmi/description + Helper library talk to QMI enabled modems. + Add qmi-utils for extra utilities. +endef + +define Package/qmi-utils + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+libqmi + TITLE:=Utilities to talk to QMI enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libqmi + LICENSE:=GPL-2.0-or-later + LICENSE_FILES:=COPYING +endef + +define Package/libqmi-utils/description + Utils to talk to QMI enabled modems +endef + +CONFIGURE_ARGS += \ + --disable-static \ + --disable-gtk-doc \ + --disable-gtk-doc-html \ + --disable-gtk-doc-pdf \ + --disable-silent-rules \ + --enable-firmware-update \ + --enable-more-warnings=yes \ + --without-udev \ + --without-udev-base-dir + +ifeq ($(CONFIG_LIBQMI_WITH_MBIM_QMUX),y) + CONFIGURE_ARGS += --enable-mbim-qmux +else + CONFIGURE_ARGS += --disable-mbim-qmux +endif + +ifeq ($(CONFIG_LIBQMI_WITH_QRTR_GLIB),y) + CONFIGURE_ARGS += --enable-qrtr +else + CONFIGURE_ARGS += --disable-qrtr +endif + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) \ + $(PKG_INSTALL_DIR)/usr/include/libqmi-glib \ + $(1)/usr/include/ + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so* \ + $(1)/usr/lib/ + + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/qmi-glib.pc \ + $(1)/usr/lib/pkgconfig +endef + +define Package/libqmi/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so.* \ + $(1)/usr/lib/ + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/qmi-proxy $(1)/usr/lib/ +endef + +define Package/qmi-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmicli $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-network $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-firmware-update $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,libqmi)) +$(eval $(call BuildPackage,qmi-utils)) diff --git a/luci-app-dsvpn/po/fr/dsvpn.po~ b/luci-app-dsvpn/po/fr/dsvpn.po~ old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/po/ru/dsvpn.po b/luci-app-dsvpn/po/ru/dsvpn.po old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/po/zh_Hans/dsvpn.po~ b/luci-app-dsvpn/po/zh_Hans/dsvpn.po~ old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po~ b/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/po/ru/glorytun-tcp.po b/luci-app-glorytun-tcp/po/ru/glorytun-tcp.po old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po~ b/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/po/fr/glorytun-udp.po~ b/luci-app-glorytun-udp/po/fr/glorytun-udp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/po/ru/glorytun-udp.po b/luci-app-glorytun-udp/po/ru/glorytun-udp.po old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po~ b/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/de/iperf.po~ b/luci-app-iperf/po/de/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/fr/iperf.po~ b/luci-app-iperf/po/fr/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/it/iperf.po~ b/luci-app-iperf/po/it/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/oc/iperf.po~ b/luci-app-iperf/po/oc/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/ru/iperf.po b/luci-app-iperf/po/ru/iperf.po old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/zh_Hans/iperf.po~ b/luci-app-iperf/po/zh_Hans/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/de/mail.po~ b/luci-app-mail/po/de/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/fr/mail.po~ b/luci-app-mail/po/fr/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/it/mail.po~ b/luci-app-mail/po/it/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/oc/mail.po~ b/luci-app-mail/po/oc/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/ru/mail.po b/luci-app-mail/po/ru/mail.po old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/zh_Hans/mail.po~ b/luci-app-mail/po/zh_Hans/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/po/fr/mlvpn.po~ b/luci-app-mlvpn/po/fr/mlvpn.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/po/ru/mlvpn.po b/luci-app-mlvpn/po/ru/mlvpn.po old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/po/zh_Hans/mlvpn.po~ b/luci-app-mlvpn/po/zh_Hans/mlvpn.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/de/mptcp.po~ b/luci-app-mptcp/po/de/mptcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/it/mptcp.po~ b/luci-app-mptcp/po/it/mptcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/oc/mptcp.po~ b/luci-app-mptcp/po/oc/mptcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/ru/mptcp.po b/luci-app-mptcp/po/ru/mptcp.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/de/omr-bypass.po~ b/luci-app-omr-bypass/po/de/omr-bypass.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/it/omr-bypass.po~ b/luci-app-omr-bypass/po/it/omr-bypass.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/oc/omr-bypass.po~ b/luci-app-omr-bypass/po/oc/omr-bypass.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/ru/omr-bypass.po b/luci-app-omr-bypass/po/ru/omr-bypass.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 1aa237f91..0aed12deb 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -539,7 +539,7 @@ _intf_rule() { EOF else ip rule add prio 1 fwmark 0x539$count lookup $count pref 1 > /dev/null 2>&1 - ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count > /dev/null 2>&1 + ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count pref 1 > /dev/null 2>&1 fi } if [ "$(iptables-save | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then diff --git a/luci-app-omr-dscp/po/de/omr-dscp.po~ b/luci-app-omr-dscp/po/de/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/fr/omr-dscp.po~ b/luci-app-omr-dscp/po/fr/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/it/omr-dscp.po~ b/luci-app-omr-dscp/po/it/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/oc/omr-dscp.po~ b/luci-app-omr-dscp/po/oc/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po~ b/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/root/etc/init.d/omr-dscp b/luci-app-omr-dscp/root/etc/init.d/omr-dscp index 9ea0d661f..4997e1cbc 100755 --- a/luci-app-omr-dscp/root/etc/init.d/omr-dscp +++ b/luci-app-omr-dscp/root/etc/init.d/omr-dscp @@ -19,10 +19,10 @@ config_get lan_device lan ifname config_load dscp _ipt4() { - iptables -w -t mangle "$@" + iptables -w -t mangle "$@" 2>&1 >/dev/null } _ipt6() { - ip6tables -w -t mangle "$@" + ip6tables -w -t mangle "$@" >/dev/null } _add_dscp_rule() { diff --git a/luci-app-omr-quota/po/de/omr-quota.po~ b/luci-app-omr-quota/po/de/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/fr/omr-quota.po~ b/luci-app-omr-quota/po/fr/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/it/omr-quota.po~ b/luci-app-omr-quota/po/it/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/oc/omr-quota.po~ b/luci-app-omr-quota/po/oc/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/ru/omr-quota.po b/luci-app-omr-quota/po/ru/omr-quota.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/zh_Hans/omr-quota.po~ b/luci-app-omr-quota/po/zh_Hans/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/de/omr-tracker.po~ b/luci-app-omr-tracker/po/de/omr-tracker.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/fr/omr-tracker.po~ b/luci-app-omr-tracker/po/fr/omr-tracker.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/it/omr-tracker.po~ b/luci-app-omr-tracker/po/it/omr-tracker.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/oc/omr-tracker.po~ b/luci-app-omr-tracker/po/oc/omr-tracker.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 27bae5b7f..58d354013 100755 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -201,7 +201,7 @@ function wizard_add() ucic:set("sqm","wan" .. i,"script","simple.qos") ucic:set("sqm","wan" .. i,"qdisc_advanced","0") ucic:set("sqm","wan" .. i,"linklayer","none") - ucic:set("sqm","wan" .. i,"enabled","0") + ucic:set("sqm","wan" .. i,"enabled","1") ucic:set("sqm","wan" .. i,"debug_logging","0") ucic:set("sqm","wan" .. i,"verbosity","5") ucic:set("sqm","wan" .. i,"download","0") diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index d3610bd36..f2c85d3e9 100755 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -682,7 +682,7 @@
- +
<%:Set an IP in the same network as the modem%> @@ -696,7 +696,7 @@
- " data-type="ip6addr"> + " data-type="ip6addr" data-optional="true">
<%:Set here IP of the modem%> @@ -896,7 +896,7 @@
- +
<%:You can force a TTL. Some LTE provider detect tethering by inpecting packet TTL value, setting it to 65 often solve the issue.%> diff --git a/luci-app-openmptcprouter/po/de/openmptcprouter.po~ b/luci-app-openmptcprouter/po/de/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/fr/openmptcprouter.po~ b/luci-app-openmptcprouter/po/fr/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/it/openmptcprouter.po~ b/luci-app-openmptcprouter/po/it/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/oc/openmptcprouter.po~ b/luci-app-openmptcprouter/po/oc/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po~ b/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter index b4ded81ab..79dbead91 100755 --- a/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter +++ b/luci-app-openmptcprouter/root/etc/init.d/openmptcprouter @@ -150,15 +150,15 @@ start_service() { if [ "$(uci -q get openmptcprouter.settings.country)" = "china" ] && [ -n "$(uci -q get dhcp.@dnsmasq[0].server | grep '127.0.0.1#5353')" ]; then uci -q batch <<-EOF > /dev/null del_list dhcp.@dnsmasq[0].server='127.0.0.1#5353' - add_list dhcp.@dnsmasq[0].server='223.5.5.5' + add_list dhcp.@dnsmasq[0].server='114.114.114.114' set dhcp.@dnsmasq[0].dnsseccheckunsigned='0' delete dhcp.@dnsmasq[0].dnssec commit dhcp EOF - elif [ "$(uci -q get openmptcprouter.settings.country)" = "world" ] && [ -n "$(uci -q get dhcp.@dnsmasq[0].server | grep '223.5.5.5')" ]; then + elif [ "$(uci -q get openmptcprouter.settings.country)" = "world" ] && [ -n "$(uci -q get dhcp.@dnsmasq[0].server | grep '114.114.114.114')" ]; then uci -q batch <<-EOF > /dev/null add_list dhcp.@dnsmasq[0].server='127.0.0.1#5353' - del_list dhcp.@dnsmasq[0].server='223.5.5.5' + del_list dhcp.@dnsmasq[0].server='114.114.114.114' commit dhcp EOF fi diff --git a/luci-app-packet-capture/po/zh_Hans/packet-capture.po b/luci-app-packet-capture/po/zh_Hans/packet-capture.po old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/fr/shutdown.po b/luci-app-shutdown/po/fr/shutdown.po old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/ru/shutdown.po b/luci-app-shutdown/po/ru/shutdown.po old mode 100644 new mode 100755 diff --git a/luci-app-status/Makefile b/luci-app-status/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-status/htdocs/luci-static/resources/status/css/wanstatus.css b/luci-app-status/htdocs/luci-static/resources/status/css/wanstatus.css old mode 100644 new mode 100755 diff --git a/luci-app-status/htdocs/luci-static/resources/status/images/status-doing.png b/luci-app-status/htdocs/luci-static/resources/status/images/status-doing.png old mode 100644 new mode 100755 diff --git a/luci-app-status/htdocs/luci-static/resources/status/images/status-done.png b/luci-app-status/htdocs/luci-static/resources/status/images/status-done.png old mode 100644 new mode 100755 diff --git a/luci-app-status/htdocs/luci-static/resources/status/images/status-error.png b/luci-app-status/htdocs/luci-static/resources/status/images/status-error.png old mode 100644 new mode 100755 diff --git a/luci-app-status/htdocs/luci-static/resources/status/images/status-todo.png b/luci-app-status/htdocs/luci-static/resources/status/images/status-todo.png old mode 100644 new mode 100755 diff --git a/luci-app-status/htdocs/luci-static/resources/status/images/status-warn.png b/luci-app-status/htdocs/luci-static/resources/status/images/status-warn.png old mode 100644 new mode 100755 diff --git a/luci-app-status/htdocs/luci-static/resources/status/images/statusError.png b/luci-app-status/htdocs/luci-static/resources/status/images/statusError.png old mode 100644 new mode 100755 diff --git a/luci-app-status/htdocs/luci-static/resources/status/images/statusOK.png b/luci-app-status/htdocs/luci-static/resources/status/images/statusOK.png old mode 100644 new mode 100755 diff --git a/luci-app-status/htdocs/luci-static/resources/status/images/statusWarning.png b/luci-app-status/htdocs/luci-static/resources/status/images/statusWarning.png old mode 100644 new mode 100755 diff --git a/luci-app-status/luasrc/controller/status.lua b/luci-app-status/luasrc/controller/status.lua old mode 100644 new mode 100755 diff --git a/luci-app-status/luasrc/view/status/server.htm b/luci-app-status/luasrc/view/status/server.htm old mode 100644 new mode 100755 diff --git a/luci-app-status/luasrc/view/status/wanstatus.htm b/luci-app-status/luasrc/view/status/wanstatus.htm old mode 100644 new mode 100755 diff --git a/luci-app-status/po/templates/status.pot b/luci-app-status/po/templates/status.pot old mode 100644 new mode 100755 diff --git a/luci-app-status/po/zh_Hans/status.po b/luci-app-status/po/zh_Hans/status.po old mode 100644 new mode 100755 diff --git a/luci-app-status/root/usr/share/luci/menu.d/luci-app-status.json b/luci-app-status/root/usr/share/luci/menu.d/luci-app-status.json old mode 100644 new mode 100755 diff --git a/luci-app-status/root/usr/share/rpcd/acl.d/luci-app-status.json b/luci-app-status/root/usr/share/rpcd/acl.d/luci-app-status.json old mode 100644 new mode 100755 diff --git a/luci-app-sysupgrade/po/fr/sysupgrade.po~ b/luci-app-sysupgrade/po/fr/sysupgrade.po~ old mode 100644 new mode 100755 diff --git a/luci-app-sysupgrade/po/ru/sysupgrade.po b/luci-app-sysupgrade/po/ru/sysupgrade.po old mode 100644 new mode 100755 diff --git a/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po b/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po old mode 100644 new mode 100755 diff --git a/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po~ b/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po~ old mode 100644 new mode 100755 diff --git a/luci-app-zerotier/Makefile b/luci-app-zerotier/Makefile new file mode 100644 index 000000000..80fa08c2a --- /dev/null +++ b/luci-app-zerotier/Makefile @@ -0,0 +1,17 @@ +# +# Copyright (C) 2008-2014 The LuCI Team +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI for Zerotier +LUCI_DEPENDS:=+zerotier +LUCI_PKGARCH:=all +PKG_VERSION:=1.0 +PKG_RELEASE:=20 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-zerotier/luasrc/controller/zerotier.lua b/luci-app-zerotier/luasrc/controller/zerotier.lua new file mode 100644 index 000000000..9c69c063e --- /dev/null +++ b/luci-app-zerotier/luasrc/controller/zerotier.lua @@ -0,0 +1,23 @@ +module("luci.controller.zerotier",package.seeall) + +function index() + if not nixio.fs.access("/etc/config/zerotier") then + return + end + + entry({"admin","vpn"}, firstchild(), "VPN", 45).dependent = false + + entry({"admin", "vpn", "zerotier"},firstchild(), _("ZeroTier")).dependent = false + + entry({"admin", "vpn", "zerotier", "general"}, cbi("zerotier/settings"), _("Base Setting"), 1) + entry({"admin", "vpn", "zerotier", "log"}, form("zerotier/info"), _("Interface Info"), 2) + + entry({"admin", "vpn", "zerotier", "status"}, call("act_status")) +end + +function act_status() + local e = {} + e.running = luci.sys.call("pgrep /usr/bin/zerotier-one >/dev/null") == 0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end diff --git a/luci-app-zerotier/luasrc/model/cbi/zerotier/info.lua b/luci-app-zerotier/luasrc/model/cbi/zerotier/info.lua new file mode 100644 index 000000000..199c468dd --- /dev/null +++ b/luci-app-zerotier/luasrc/model/cbi/zerotier/info.lua @@ -0,0 +1,15 @@ +local fs = require "nixio.fs" +local conffile = "/tmp/zero.info" + +f = SimpleForm("logview") + +t = f:field(TextValue, "conf") +t.rmempty = true +t.rows = 19 +function t.cfgvalue() + luci.sys.exec("for i in $(ifconfig | grep 'zt' | awk '{print $1}'); do ifconfig $i; done > /tmp/zero.info") + return fs.readfile(conffile) or "" +end +t.readonly="readonly" + +return f diff --git a/luci-app-zerotier/luasrc/model/cbi/zerotier/settings.lua b/luci-app-zerotier/luasrc/model/cbi/zerotier/settings.lua new file mode 100644 index 000000000..32ef1bbfc --- /dev/null +++ b/luci-app-zerotier/luasrc/model/cbi/zerotier/settings.lua @@ -0,0 +1,27 @@ +a = Map("zerotier") +a.title = translate("ZeroTier") +a.description = translate("Zerotier is an open source, cross-platform and easy to use virtual LAN") + +a:section(SimpleSection).template = "zerotier/zerotier_status" + +t = a:section(NamedSection, "sample_config", "zerotier") +t.anonymous = true +t.addremove = false + +e = t:option(Flag, "enabled", translate("Enable")) +e.default = 0 +e.rmempty=false + +e = t:option(DynamicList, "join", translate('ZeroTier Network ID')) +e.password = true +e.rmempty = false + +e = t:option(Flag, "nat", translate("Auto NAT Clients")) +e.description = translate("Allow zerotier clients access your LAN network") +e.default = 0 +e.rmempty = false + +e = t:option(DummyValue, "opennewwindow", translate("")) +e.description = translate("Create or manage your zerotier network, and auth clients who could access") + +return a diff --git a/luci-app-zerotier/luasrc/view/zerotier/zerotier_status.htm b/luci-app-zerotier/luasrc/view/zerotier/zerotier_status.htm new file mode 100644 index 000000000..9d216c5d9 --- /dev/null +++ b/luci-app-zerotier/luasrc/view/zerotier/zerotier_status.htm @@ -0,0 +1,22 @@ + + +
+

+ <%:Collecting data...%> +

+
diff --git a/luci-app-zerotier/po/zh-cn/zerotier.po b/luci-app-zerotier/po/zh-cn/zerotier.po new file mode 100644 index 000000000..9ed1270b3 --- /dev/null +++ b/luci-app-zerotier/po/zh-cn/zerotier.po @@ -0,0 +1,25 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Gtranslator 2.91.7\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Zerotier is an open source, cross-platform and easy to use virtual LAN" +msgstr "Zerotier 是一个开源,跨平台,而且适合内网穿透互联的傻瓜配置虚拟 VPN LAN" + +msgid "Auto NAT Clients" +msgstr "自动允许客户端 NAT" + +msgid "Allow zerotier clients access your LAN network" +msgstr "允许 Zerotier 的拨入客户端访问路由器 LAN 资源(需要在 Zerotier 管理页面设定到 LAN 网段的路由表)" + +msgid "Create or manage your zerotier network, and auth clients who could access" +msgstr "点击跳转到 Zerotier 官网管理平台,新建或者管理网络,并允许客户端接入访问你私人网路(新接入的节点默认不允许访问)" + +msgid "Base Setting" +msgstr "基本设置" + +msgid "Interface Info" +msgstr "接口信息" diff --git a/luci-app-zerotier/root/etc/init.d/zerotier b/luci-app-zerotier/root/etc/init.d/zerotier new file mode 100755 index 000000000..0403e5d17 --- /dev/null +++ b/luci-app-zerotier/root/etc/init.d/zerotier @@ -0,0 +1,113 @@ +#!/bin/sh /etc/rc.common + +START=99 + +USE_PROCD=1 + +PROG=/usr/bin/zerotier-one +CONFIG_PATH=/var/lib/zerotier-one + +service_triggers() { + procd_add_reload_trigger "zerotier" + procd_add_interface_trigger "interface.*.up" wan /etc/init.d/zerotier restart +} + +section_enabled() { + config_get_bool enabled "$1" 'enabled' 0 + [ $enabled -gt 0 ] +} + +start_instance() { + local cfg="$1" + local port secret config_path + local ARGS="" + + if ! section_enabled "$cfg"; then + echo "disabled in config" + return 1 + fi + + [ -d /etc/config/zero ] || mkdir -p /etc/config/zero + config_path=/etc/config/zero + + config_get_bool port $cfg 'port' + config_get secret $cfg 'secret' + + # Remove existing link or folder + rm -rf $CONFIG_PATH + + # Create link from CONFIG_PATH to config_path + if [ -n "$config_path" -a "$config_path" != $CONFIG_PATH ]; then + if [ ! -d "$config_path" ]; then + echo "ZeroTier config_path does not exist: $config_path" + return + fi + + ln -s $config_path $CONFIG_PATH + fi + + mkdir -p $CONFIG_PATH/networks.d + + if [ -n "$port" ]; then + ARGS="$ARGS -p$port" + fi + + if [ "$secret" = "generate" ]; then + echo "Generate secret - please wait..." + local sf="/tmp/zt.$cfg.secret" + + zerotier-idtool generate "$sf" > /dev/null + [ $? -ne 0 ] && return 1 + + secret="$(cat $sf)" + rm "$sf" + + uci set zerotier.$cfg.secret="$secret" + uci commit zerotier + fi + + if [ -n "$secret" ]; then + echo "$secret" > $CONFIG_PATH/identity.secret + # make sure there is not previous identity.public + rm -f $CONFIG_PATH/identity.public + fi + + add_join() { + # an (empty) config file will cause ZT to join a network + touch $CONFIG_PATH/networks.d/$1.conf + } + + config_list_foreach $cfg 'join' add_join + + procd_open_instance + procd_set_param command $PROG $ARGS $CONFIG_PATH + procd_set_param stderr 1 + procd_close_instance +} + +start_service() { + config_load 'zerotier' + config_foreach start_instance 'zerotier' + touch /tmp/zero.log && /etc/zerotier.start > /tmp/zero.log 2>&1 & +} + +stop_instance() { + rm -f /tmp/zero.log + local cfg="$1" + + /etc/zerotier.stop > /tmp/zero.log 2>&1 & + + # Remove existing link or folder + rm -f $CONFIG_PATH/networks.d/*.conf + rm -rf $CONFIG_PATH +} + +stop_service() { + config_load 'zerotier' + config_foreach stop_instance 'zerotier' +} + +reload_service() { + stop + start +} \ No newline at end of file diff --git a/luci-app-zerotier/root/etc/uci-defaults/40_luci-zerotier b/luci-app-zerotier/root/etc/uci-defaults/40_luci-zerotier new file mode 100755 index 000000000..95f0ccfc9 --- /dev/null +++ b/luci-app-zerotier/root/etc/uci-defaults/40_luci-zerotier @@ -0,0 +1,17 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@zerotier[-1] + add ucitrack zerotier + set ucitrack.@zerotier[-1].init=zerotier + commit ucitrack + delete firewall.zerotier + set firewall.zerotier=include + set firewall.zerotier.type=script + set firewall.zerotier.path=/etc/zerotier.start + set firewall.zerotier.reload=1 + commit firewall +EOF + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/luci-app-zerotier/root/etc/zerotier.start b/luci-app-zerotier/root/etc/zerotier.start new file mode 100755 index 000000000..b43e5f974 --- /dev/null +++ b/luci-app-zerotier/root/etc/zerotier.start @@ -0,0 +1,28 @@ +#!/bin/sh + +zero_enable="$(uci get zerotier.sample_config.enabled)" + +[ "${zero_enable}" -ne "1" ] && exit 0 + +[ -f "/tmp/zero.log" ] && { + while [ "$(ifconfig | grep 'zt' | awk '{print $1}')" = "" ] + do + sleep 1 + done +} + +nat_enable="$(uci get zerotier.sample_config.nat)" +zt0="$(ifconfig | grep 'zt' | awk '{print $1}')" +echo "${zt0}" > "/tmp/zt.nif" + +[ "${nat_enable}" -eq "1" ] && { + for i in ${zt0} + do + ip_segment="" + iptables -I FORWARD -i "$i" -j ACCEPT + iptables -I FORWARD -o "$i" -j ACCEPT + iptables -t nat -I POSTROUTING -o "$i" -j MASQUERADE + ip_segment="$(ip route | grep "dev $i proto kernel" | awk '{print $1}')" + iptables -t nat -I POSTROUTING -s "${ip_segment}" -j MASQUERADE + done +} diff --git a/luci-app-zerotier/root/etc/zerotier.stop b/luci-app-zerotier/root/etc/zerotier.stop new file mode 100755 index 000000000..07450183e --- /dev/null +++ b/luci-app-zerotier/root/etc/zerotier.stop @@ -0,0 +1,15 @@ +#!/bin/sh + +zt0="$(ifconfig | grep 'zt' | awk '{print $1}')" +[ -z "${zt0}" ] && zt0="$(cat "/tmp/zt.nif")" + +for i in ${zt0} +do + ip_segment="" + iptables -D FORWARD -i "$i" -j ACCEPT 2>/dev/null + iptables -D FORWARD -o "$i" -j ACCEPT 2>/dev/null + iptables -t nat -D POSTROUTING -o "$i" -j MASQUERADE 2>/dev/null + ip_segment="$(ip route | grep "dev $i proto" | awk '{print $1}')" + iptables -t nat -D POSTROUTING -s "${ip_segment}" -j MASQUERADE 2>/dev/null + echo "zt interface $i is stopped!" +done \ No newline at end of file diff --git a/luci-app-zerotier/root/etc/zerotier/zerotier.log b/luci-app-zerotier/root/etc/zerotier/zerotier.log new file mode 100644 index 000000000..e69de29bb diff --git a/luci-app-zerotier/root/usr/share/rpcd/acl.d/luci-app-zerotier.json b/luci-app-zerotier/root/usr/share/rpcd/acl.d/luci-app-zerotier.json new file mode 100644 index 000000000..2724e99bf --- /dev/null +++ b/luci-app-zerotier/root/usr/share/rpcd/acl.d/luci-app-zerotier.json @@ -0,0 +1,11 @@ +{ + "luci-app-zerotier": { + "description": "Grant UCI access for luci-app-zerotier", + "read": { + "uci": [ "zerotier" ] + }, + "write": { + "uci": [ "zerotier" ] + } + } +} diff --git a/luci-mod-dashboard/po/fr/dashboard.po b/luci-mod-dashboard/po/fr/dashboard.po old mode 100644 new mode 100755 diff --git a/luci-mod-dashboard/po/ru/dashboard.po b/luci-mod-dashboard/po/ru/dashboard.po old mode 100644 new mode 100755 diff --git a/luci-mod-dashboard/po/templates/dashboard.pot b/luci-mod-dashboard/po/templates/dashboard.pot old mode 100644 new mode 100755 diff --git a/luci-mod-dashboard/po/zh_Hans/dashboard.po b/luci-mod-dashboard/po/zh_Hans/dashboard.po old mode 100644 new mode 100755 diff --git a/luci-mod-network/htdocs/luci-static/resources/tools/network.js b/luci-mod-network/htdocs/luci-static/resources/tools/network.js old mode 100644 new mode 100755 diff --git a/luci-theme-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/omr-logo.png b/luci-theme-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/omr-logo.png old mode 100644 new mode 100755 diff --git a/luci-theme-openmptcprouter/luasrc/view/themes/openmptcprouter/footer.htm b/luci-theme-openmptcprouter/luasrc/view/themes/openmptcprouter/footer.htm index f78b911a5..0fdd0e4d3 100755 --- a/luci-theme-openmptcprouter/luasrc/view/themes/openmptcprouter/footer.htm +++ b/luci-theme-openmptcprouter/luasrc/view/themes/openmptcprouter/footer.htm @@ -8,7 +8,7 @@ <% local ver = require "luci.version" %> diff --git a/mlvpn/patches/020-remove-cdefs.patch b/mlvpn/patches/020-remove-cdefs.patch old mode 100644 new mode 100755 diff --git a/modemmanager/Config.in b/modemmanager/Config.in new file mode 100644 index 000000000..283a9e10a --- /dev/null +++ b/modemmanager/Config.in @@ -0,0 +1,21 @@ +menu "Configuration" +depends on PACKAGE_modemmanager + + config MODEMMANAGER_WITH_MBIM + bool "Include MBIM support" + default y + help + Compile ModemManager with MBIM support + + config MODEMMANAGER_WITH_QMI + bool "Include QMI support" + default y + help + Compile ModemManager with QMI support + + config MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS + bool "Allow AT commands via DBus" + default n + help + Compile ModemManager allowing AT commands without debug flag +endmenu diff --git a/modemmanager/Makefile b/modemmanager/Makefile new file mode 100644 index 000000000..570bc9293 --- /dev/null +++ b/modemmanager/Makefile @@ -0,0 +1,142 @@ +# +# Copyright (C) 2016 Velocloud Inc. +# Copyright (C) 2016 Aleksander Morgado +# +# This is free software, licensed under the GNU General Public License v2. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=modemmanager +PKG_VERSION:=1.18.2 +PKG_RELEASE:=1 + +PKG_SOURCE:=ModemManager-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://www.freedesktop.org/software/ModemManager +PKG_HASH:=374be158ae1c1fb38a29eef1cc3cdf89ff3536b48ff1320d208ab204ea6c5f8a +PKG_BUILD_DIR:=$(BUILD_DIR)/ModemManager-$(PKG_VERSION) + +PKG_MAINTAINER:=Nicholas Smith +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/modemmanager/config + source "$(SOURCE)/Config.in" +endef + +define Package/modemmanager + SECTION:=net + CATEGORY:=Network + TITLE:=Control utility for any kind of mobile broadband modem + URL:=https://www.freedesktop.org/wiki/Software/ModemManager + DEPENDS:= \ + $(INTL_DEPENDS) \ + +glib2 \ + +dbus \ + +ppp \ + +MODEMMANAGER_WITH_MBIM:libmbim \ + +MODEMMANAGER_WITH_QMI:libqmi +endef + +define Package/modemmanager/description + ModemManager is a D-Bus-activated service which allows controlling mobile + broadband modems. Add kernel modules for your modems as needed. + Select Utilities/usb-modeswitch if needed. +endef + +CONFIGURE_ARGS += \ + --without-polkit \ + --without-udev \ + --without-systemdsystemunitdir \ + --disable-rpath \ + --disable-gtk-doc + +ifeq ($(CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS),y) + CONFIGURE_ARGS += --with-at-command-via-dbus +endif + +ifdef CONFIG_MODEMMANAGER_WITH_MBIM + CONFIGURE_ARGS += --with-mbim +else + CONFIGURE_ARGS += --without-mbim +endif + +ifdef CONFIG_MODEMMANAGER_WITH_QMI + CONFIGURE_ARGS += --with-qmi +else + CONFIGURE_ARGS += --without-qmi +endif + +define Build/Prepare + $(call Build/Prepare/Default) + ( cd "$(PKG_BUILD_DIR)"; \ + printf "all:\ninstall:\n" >po/Makefile.in.in; \ + ) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/include/ModemManager/*.h $(1)/usr/include/ModemManager + $(INSTALL_DIR) $(1)/usr/include/libmm-glib + $(CP) $(PKG_INSTALL_DIR)/usr/include/libmm-glib/*.h $(1)/usr/include/libmm-glib + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so* $(1)/usr/lib + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/ModemManager.pc $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mm-glib.pc $(1)/usr/lib/pkgconfig +endef + +define Package/modemmanager/install + $(INSTALL_DIR) $(1)/lib/udev/rules.d + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/lib/udev/rules.d/*.rules $(1)/lib/udev/rules.d + + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ModemManager $(1)/usr/sbin + $(INSTALL_BIN) ./files/usr/sbin/ModemManager-wrapper $(1)/usr/sbin + + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mmcli $(1)/usr/bin + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so.* $(1)/usr/lib + + $(INSTALL_DIR) $(1)/usr/lib/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-shared-*.so* $(1)/usr/lib/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-plugin-*.so* $(1)/usr/lib/ModemManager + + $(INSTALL_DIR) $(1)/etc/dbus-1/system.d + $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/dbus-1/system.d/org.freedesktop.ModemManager1.conf $(1)/etc/dbus-1/system.d + + $(INSTALL_DIR) $(1)/usr/share/dbus-1/system-services + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/dbus-1/system-services/org.freedesktop.ModemManager1.service $(1)/usr/share/dbus-1/system-services + + $(INSTALL_DIR) $(1)/usr/share/ModemManager + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf $(1)/usr/share/ModemManager + $(INSTALL_DATA) ./files/modemmanager.common $(1)/usr/share/ModemManager + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/modemmanager.init $(1)/etc/init.d/modemmanager + + $(INSTALL_DIR) $(1)/etc/hotplug.d/usb + $(INSTALL_DATA) ./files/25-modemmanager-usb $(1)/etc/hotplug.d/usb + + $(INSTALL_DIR) $(1)/etc/hotplug.d/net + $(INSTALL_DATA) ./files/25-modemmanager-net $(1)/etc/hotplug.d/net + + $(INSTALL_DIR) $(1)/etc/hotplug.d/tty + $(INSTALL_DATA) ./files/25-modemmanager-tty $(1)/etc/hotplug.d/tty + + $(INSTALL_DIR) $(1)/etc/hotplug.d/wwan + $(INSTALL_DATA) ./files/25-modemmanager-wwan $(1)/etc/hotplug.d/wwan + + $(INSTALL_DIR) $(1)/lib/netifd/proto + $(INSTALL_BIN) ./files/modemmanager.proto $(1)/lib/netifd/proto/modemmanager.sh +endef + +$(eval $(call BuildPackage,modemmanager)) diff --git a/modemmanager/README.md b/modemmanager/README.md new file mode 100644 index 000000000..c9d880ea4 --- /dev/null +++ b/modemmanager/README.md @@ -0,0 +1,40 @@ +# OpenWrt ModemManager + +## Description + +Cellular modem control and connectivity + +Optional libraries libmbim and libqmi are available. +Your modem may require additional kernel modules and/or the usb-modeswitch +package. + +## Usage + +Once installed, you can configure the 2G/3G/4G modem connections directly in +/etc/config/network as in the following example: + + config interface 'broadband' + option device '/sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.2/1-1.2.1' + option proto 'modemmanager' + option apn 'ac.vodafone.es' + option allowedauth 'pap chap' + option username 'vodafone' + option password 'vodafone' + option pincode '7423' + option iptype 'ipv4' + option lowpower '1' + option signalrate '30' + +Only 'device' and 'proto' are mandatory options, the remaining ones are all +optional. + +The 'allowedauth' option allows limiting the list of authentication protocols. +It is given as a space-separated list of values, including any of the +following: 'pap', 'chap', 'mschap', 'mschapv2' or 'eap'. It will default to +allowing all protocols. + +The 'iptype' option supports any of these values: 'ipv4', 'ipv6' or 'ipv4v6'. +It will default to 'ipv4' if not given. + +The 'signalrate' option set's the signal refresh rate (in seconds) for the device. +You can call signal info with command: mmcli -m 0 --signal-get diff --git a/modemmanager/files/25-modemmanager-net b/modemmanager/files/25-modemmanager-net new file mode 100644 index 000000000..e87231e31 --- /dev/null +++ b/modemmanager/files/25-modemmanager-net @@ -0,0 +1,31 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +# Load common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a interface name +[ -n "${INTERFACE}" ] || exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report network interface +mm_log "${ACTION} network interface ${INTERFACE}: event processed" +mm_report_event "${ACTION}" "${INTERFACE}" "net" "/sys${DEVPATH}" + +# Look for an associated cdc-wdm interface + +cdcwdm="" + +case "${ACTION}" in + "add") cdcwdm=$(mm_track_cdcwdm "${INTERFACE}") ;; + "remove") cdcwdm=$(mm_untrack_cdcwdm "${INTERFACE}") ;; +esac + +# Report cdc-wdm device, if any +[ -n "${cdcwdm}" ] && { + mm_log "${ACTION} cdc interface ${cdcwdm}: custom event processed" + mm_report_event "${ACTION}" "${cdcwdm}" "usbmisc" "/sys${DEVPATH}" +} diff --git a/modemmanager/files/25-modemmanager-tty b/modemmanager/files/25-modemmanager-tty new file mode 100644 index 000000000..c13148a33 --- /dev/null +++ b/modemmanager/files/25-modemmanager-tty @@ -0,0 +1,16 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +# Load hotplug common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a device name +[ -n "$DEVNAME" ] || exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report TTY +mm_log "${ACTION} serial interface ${DEVNAME}: event processed" +mm_report_event "${ACTION}" "${DEVNAME}" "tty" "/sys${DEVPATH}" diff --git a/modemmanager/files/25-modemmanager-usb b/modemmanager/files/25-modemmanager-usb new file mode 100644 index 000000000..93d0bf70a --- /dev/null +++ b/modemmanager/files/25-modemmanager-usb @@ -0,0 +1,13 @@ +#!/bin/sh +# Copyright (C) 2019 Aleksander Morgado + +# We need to process only full USB device removal events, we don't +# want to process specific interface removal events. +[ "$ACTION" = remove ] || exit +[ -z "${INTERFACE}" ] || exit + +# Load common utilities +. /usr/share/ModemManager/modemmanager.common + +mm_clear_modem_wait_status "/sys${DEVPATH}" +mm_cleanup_interface_by_sysfspath "/sys${DEVPATH}" diff --git a/modemmanager/files/25-modemmanager-wwan b/modemmanager/files/25-modemmanager-wwan new file mode 100644 index 000000000..c4dc6b897 --- /dev/null +++ b/modemmanager/files/25-modemmanager-wwan @@ -0,0 +1,15 @@ +#!/bin/sh +# Copyright (C) 2021 Aleksander Morgado + +# Load hotplug common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a device name +[ -n "$DEVNAME" ] || exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report wwan +mm_log "${ACTION} wwan control port ${DEVNAME}: event processed" +mm_report_event "${ACTION}" "${DEVNAME}" "wwan" "/sys${DEVPATH}" diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common new file mode 100644 index 000000000..a439179de --- /dev/null +++ b/modemmanager/files/modemmanager.common @@ -0,0 +1,341 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +################################################################################ + +. /lib/functions.sh +. /lib/netifd/netifd-proto.sh + +################################################################################ +# Runtime state + +MODEMMANAGER_RUNDIR="/var/run/modemmanager" +MODEMMANAGER_PID_FILE="${MODEMMANAGER_RUNDIR}/modemmanager.pid" +MODEMMANAGER_CDCWDM_CACHE="${MODEMMANAGER_RUNDIR}/cdcwdm.cache" +MODEMMANAGER_SYSFS_CACHE="${MODEMMANAGER_RUNDIR}/sysfs.cache" +MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" + +################################################################################ +# Common logging + +mm_log() { + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && logger -t "ModemManager" "hotplug: $*" +} + +################################################################################ +# Receives as input argument the full sysfs path of the device +# Returns the physical device sysfs path +# +# NOTE: this method only works when the device exists, i.e. it cannot be used +# on removal hotplug events + +mm_find_physdev_sysfs_path() { + local tmp_path="$1" + + while true; do + tmp_path=$(dirname "${tmp_path}") + + # avoid infinite loops iterating + [ -z "${tmp_path}" ] || [ "${tmp_path}" = "/" ] && return + + # for USB devices, the physical device will be that with a idVendor + # and idProduct pair of files + [ -f "${tmp_path}"/idVendor ] && [ -f "${tmp_path}"/idProduct ] && { + tmp_path=$(readlink -f "$tmp_path") + echo "${tmp_path}" + return + } + + # For PCI devices, the physical device will be that with a vendor + # and device pair of files + [ -f "${tmp_path}"/vendor ] && [ -f "${tmp_path}"/device ] && { + tmp_path=$(readlink -f "$tmp_path") + echo "${tmp_path}" + return + } + done +} + +################################################################################ + +# Returns the cdc-wdm name retrieved from sysfs +mm_track_cdcwdm() { + local wwan="$1" + local cdcwdm + + cdcwdm=$(ls "/sys/class/net/${wwan}/device/usbmisc/") + [ -n "${cdcwdm}" ] || return + + # We have to cache it for later, as we won't be able to get the + # associated cdc-wdm device on a remove event + echo "${wwan} ${cdcwdm}" >> "${MODEMMANAGER_CDCWDM_CACHE}" + + echo "${cdcwdm}" +} + +# Returns the cdc-wdm name retrieved from the cache +mm_untrack_cdcwdm() { + local wwan="$1" + local cdcwdm + + # Look for the cached associated cdc-wdm device + [ -f "${MODEMMANAGER_CDCWDM_CACHE}" ] || return + + cdcwdm=$(awk -v wwan="${wwan}" '!/^#/ && $0 ~ wwan { print $2 }' "${MODEMMANAGER_CDCWDM_CACHE}") + [ -n "${cdcwdm}" ] || return + + # Remove from cache + sed -i "/${wwan} ${cdcwdm}/d" "${MODEMMANAGER_CDCWDM_CACHE}" + + echo "${cdcwdm}" +} + +################################################################################ +# ModemManager needs some time from the ports being added until a modem object +# is exposed in DBus. With the logic here we do an explicit wait of N seconds +# for ModemManager to expose the new modem object, making sure that the wait is +# unique per device (i.e. per physical device sysfs path). + +# Gets the modem wait status as retrieved from the cache +mm_get_modem_wait_status() { + local sysfspath="$1" + + # If no sysfs cache file, we're done + [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] || return + + # Get status of the sysfs path + awk -v sysfspath="${sysfspath}" '!/^#/ && $0 ~ sysfspath { print $2 }' "${MODEMMANAGER_SYSFS_CACHE}" +} + +# Clear the modem wait status from the cache, if any +mm_clear_modem_wait_status() { + local sysfspath="$1" + + local escaped_sysfspath + + [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] && { + # escape '/', '\' and '&' for sed... + escaped_sysfspath=$(echo "$sysfspath" | sed -e 's/[\/&]/\\&/g') + sed -i "/${escaped_sysfspath}/d" "${MODEMMANAGER_SYSFS_CACHE}" + } +} + +# Sets the modem wait status in the cache +mm_set_modem_wait_status() { + local sysfspath="$1" + local status="$2" + + # Remove sysfs line before adding the new one with the new state + mm_clear_modem_wait_status "${sysfspath}" + + # Add the new status + echo "${sysfspath} ${status}" >> "${MODEMMANAGER_SYSFS_CACHE}" +} + +# Callback for config_foreach() +mm_get_modem_config_foreach_cb() { + local cfg="$1" + local sysfspath="$2" + + local proto + config_get proto "${cfg}" proto + [ "${proto}" = modemmanager ] || return 0 + + local dev + dev=$(uci_get network "${cfg}" device) + [ "${dev}" = "${sysfspath}" ] || return 0 + + echo "${cfg}" +} + +# Returns the name of the interface configured for this device +mm_get_modem_config() { + local sysfspath="$1" + + # Look for configuration for the given sysfs path + config_load network + config_foreach mm_get_modem_config_foreach_cb interface "${sysfspath}" +} + +# Wait for a modem in the specified sysfspath +mm_wait_for_modem() { + local cfg="$1" + local sysfspath="$2" + + # TODO: config max wait + local n=45 + local step=5 + + while [ $n -ge 0 ]; do + [ -d "${sysfspath}" ] || { + mm_log "error: ignoring modem detection request: no device at ${sysfspath}" + proto_set_available "${cfg}" 0 + return 1 + } + + # Check if the modem exists at the given sysfs path + if ! mmcli -m "${sysfspath}" > /dev/null 2>&1 + then + mm_log "error: modem not detected at sysfs path" + else + mm_log "modem exported successfully at ${sysfspath}" + mm_log "setting interface '${cfg}' as available" + proto_set_available "${cfg}" 1 + return 0 + fi + + sleep $step + n=$((n-step)) + done + + mm_log "error: timed out waiting for the modem to get exported at ${sysfspath}" + proto_set_available "${cfg}" 0 + return 2 +} + +mm_report_modem_wait() { + local sysfspath=$1 + + local parent_sysfspath status + + parent_sysfspath=$(mm_find_physdev_sysfs_path "$sysfspath") + [ -n "${parent_sysfspath}" ] || { + mm_log "error: parent device sysfspath not found" + return + } + + status=$(mm_get_modem_wait_status "${parent_sysfspath}") + case "${status}" in + "") + local cfg + + cfg=$(mm_get_modem_config "${parent_sysfspath}") + if [ -n "${cfg}" ]; then + mm_log "interface '${cfg}' is set to configure device '${parent_sysfspath}'" + mm_log "now waiting for modem at sysfs path ${parent_sysfspath}" + mm_set_modem_wait_status "${parent_sysfspath}" "processed" + # Launch subshell for the explicit wait + ( mm_wait_for_modem "${cfg}" "${parent_sysfspath}" ) > /dev/null 2>&1 & + else + mm_log "no need to wait for modem at sysfs path ${parent_sysfspath}" + mm_set_modem_wait_status "${parent_sysfspath}" "ignored" + fi + ;; + "processed") + mm_log "already waiting for modem at sysfs path ${parent_sysfspath}" + ;; + "ignored") + ;; + *) + mm_log "error: unknown status read for device at sysfs path ${parent_sysfspath}" + ;; + esac +} + +################################################################################ +# Cleanup interfaces + +mm_cleanup_interface_cb() { + local cfg="$1" + + local proto + config_get proto "${cfg}" proto + [ "${proto}" = modemmanager ] || return 0 + + proto_set_available "${cfg}" 0 +} + +mm_cleanup_interfaces() { + config_load network + config_foreach mm_cleanup_interface_cb interface +} + +mm_cleanup_interface_by_sysfspath() { + local dev="$1" + + local cfg + cfg=$(mm_get_modem_config "$dev") + [ -n "${cfg}" ] || return + + mm_log "setting interface '$cfg' as unavailable" + proto_set_available "${cfg}" 0 +} + +################################################################################ +# Event reporting + +# Receives as input the action, the device name and the subsystem +mm_report_event() { + local action="$1" + local name="$2" + local subsystem="$3" + local sysfspath="$4" + + # Track/untrack events in cache + case "${action}" in + "add") + # On add events, store event details in cache (if not exists yet) + grep -qs "${name},${subsystem}" "${MODEMMANAGER_EVENTS_CACHE}" || \ + echo "${action},${name},${subsystem},${sysfspath}" >> "${MODEMMANAGER_EVENTS_CACHE}" + ;; + "remove") + # On remove events, remove old events from cache (match by subsystem+name) + sed -i "/${name},${subsystem}/d" "${MODEMMANAGER_EVENTS_CACHE}" + ;; + esac + + # Report the event + mm_log "event reported: action=${action}, name=${name}, subsystem=${subsystem}" + mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 1>/dev/null 2>&1 & + + # Wait for added modem if a sysfspath is given + [ -n "${sysfspath}" ] && [ "$action" = "add" ] && mm_report_modem_wait "${sysfspath}" +} + +mm_report_event_from_cache_line() { + local event_line="$1" + + local action name subsystem sysfspath + action=$(echo "${event_line}" | awk -F ',' '{ print $1 }') + name=$(echo "${event_line}" | awk -F ',' '{ print $2 }') + subsystem=$(echo "${event_line}" | awk -F ',' '{ print $3 }') + sysfspath=$(echo "${event_line}" | awk -F ',' '{ print $4 }') + + mm_log "cached event found: action=${action}, name=${name}, subsystem=${subsystem}, sysfspath=${sysfspath}" + mm_report_event "${action}" "${name}" "${subsystem}" "${sysfspath}" +} + +mm_report_events_from_cache() { + # Remove the sysfs cache + rm -f "${MODEMMANAGER_SYSFS_CACHE}" + + local n=60 + local step=1 + local mmrunning=0 + + # Wait for ModemManager to be available in the bus + while [ $n -ge 0 ]; do + sleep $step + mm_log "checking if ModemManager is available..." + + if ! mmcli -L >/dev/null 2>&1 + then + mm_log "ModemManager not yet available" + else + mmrunning=1 + break + fi + n=$((n-step)) + done + + [ ${mmrunning} -eq 1 ] || { + mm_log "error: couldn't report initial kernel events: ModemManager not running" + return + } + + # Report cached kernel events + while IFS= read -r event_line; do + mm_report_event_from_cache_line "${event_line}" + done < ${MODEMMANAGER_EVENTS_CACHE} +} diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/modemmanager.init new file mode 100644 index 000000000..a3f6c1b12 --- /dev/null +++ b/modemmanager/files/modemmanager.init @@ -0,0 +1,34 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2016 Aleksander Morgado + +USE_PROCD=1 +START=70 + +stop_service() { + # Load common utils + . /usr/share/ModemManager/modemmanager.common + # Set all configured interfaces as unavailable + mm_cleanup_interfaces +} + +start_service() { + # Setup ModemManager service + # + # We will make sure that the rundir always exists, and we initially cleanup + # all interfaces flagging them as unavailable. + # + # The cached events processing will wait for MM to be available in DBus + # and will make sure all ports are re-notified to ModemManager every time + # it starts. + # + # All these commands need to be executed on every MM start, even after + # procd-triggered respawns, which is why this is wrapped in a startup + # wrapper script called '/usr/sbin/ModemManager-wrapper'. + # + . /usr/share/ModemManager/modemmanager.common + procd_open_instance + procd_set_param command /usr/sbin/ModemManager-wrapper + procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" + procd_set_param pidfile "${MODEMMANAGER_PID_FILE}" + procd_close_instance +} diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/modemmanager.proto new file mode 100755 index 000000000..2cce0b7c2 --- /dev/null +++ b/modemmanager/files/modemmanager.proto @@ -0,0 +1,554 @@ +#!/bin/sh +# Copyright (C) 2016-2019 Aleksander Morgado + +[ -x /usr/bin/mmcli ] || exit 0 +[ -x /usr/sbin/pppd ] || exit 0 + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + . ./ppp.sh + init_proto "$@" +} + +cdr2mask () +{ + # Number of args to shift, 255..255, first non-255 byte, zeroes + set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0 + if [ "$1" -gt 1 ] + then + shift "$1" + else + shift + fi + echo "${1-0}"."${2-0}"."${3-0}"."${4-0}" +} + +# This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue +# The second argument must be exactly the name of the field to read +# +# Sample output: +# $ mmcli -m 0 -K +# modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0 +# modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752 +# modem.generic.manufacturer : Dell Inc. +# modem.generic.model : DW5821e Snapdragon X20 LTE +# modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026 +# modem.generic.carrier-configuration : GCF +# modem.generic.carrier-configuration-revision : 08E00009 +# modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE +# .... +modemmanager_get_field() { + local list=$1 + local field=$2 + local value="" + + [ -z "${list}" ] || [ -z "${field}" ] && return + + # there is always at least a whitespace after each key, and we use that as part of the + # key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result + # when grepping for 'modem.generic.state'. + line=$(echo "${list}" | grep "${field} ") + value=$(echo ${line#*:}) + + # not found? + [ -n "${value}" ] || return 2 + + # only print value if set + [ "${value}" != "--" ] && echo "${value}" + return 0 +} + +# build a comma-separated list of values from the list +modemmanager_get_multivalue_field() { + local list=$1 + local field=$2 + local value="" + local length idx item + + [ -z "${list}" ] || [ -z "${field}" ] && return + + length=$(modemmanager_get_field "${list}" "${field}.length") + [ -n "${length}" ] || return 0 + [ "$length" -ge 1 ] || return 0 + + idx=1 + while [ $idx -le "$length" ]; do + item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]") + [ -n "${item}" ] && [ "${item}" != "--" ] && { + [ -n "${value}" ] && value="${value}, " + value="${value}${item}" + } + idx=$((idx + 1)) + done + + # nothing built? + [ -n "${value}" ] || return 2 + + # only print value if set + echo "${value}" + return 0 +} + +modemmanager_cleanup_connection() { + local modemstatus="$1" + + local bearercount idx bearerpath + + bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") + + # do nothing if no bearers reported + [ -n "${bearercount}" ] && [ "$bearercount" -ge 1 ] && { + # explicitly disconnect just in case + mmcli --modem="${device}" --simple-disconnect >/dev/null 2>&1 + # and remove all bearer objects, if any found + idx=1 + while [ $idx -le "$bearercount" ]; do + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[$idx\]") + mmcli --modem "${device}" --delete-bearer="${bearerpath}" >/dev/null 2>&1 + idx=$((idx + 1)) + done + } +} + +modemmanager_connected_method_ppp_ipv4() { + local interface="$1" + local ttyname="$2" + local username="$3" + local password="$4" + local allowedauth="$5" + + # all auth types are allowed unless a user given list is given + local authopts + local pap=1 + local chap=1 + local mschap=1 + local mschapv2=1 + local eap=1 + + [ -n "$allowedauth" ] && { + pap=0 chap=0 mschap=0 mschapv2=0 eap=0 + for auth in $allowedauth; do + case $auth in + "pap") pap=1 ;; + "chap") chap=1 ;; + "mschap") mschap=1 ;; + "mschapv2") mschapv2=1 ;; + "eap") eap=1 ;; + *) ;; + esac + done + } + + [ $pap -eq 1 ] || append authopts "refuse-pap" + [ $chap -eq 1 ] || append authopts "refuse-chap" + [ $mschap -eq 1 ] || append authopts "refuse-mschap" + [ $mschapv2 -eq 1 ] || append authopts "refuse-mschap-v2" + [ $eap -eq 1 ] || append authopts "refuse-eap" + + proto_run_command "${interface}" /usr/sbin/pppd \ + "${ttyname}" \ + 115200 \ + nodetach \ + noaccomp \ + nobsdcomp \ + nopcomp \ + novj \ + noauth \ + $authopts \ + ${username:+ user $username} \ + ${password:+ password $password} \ + lcp-echo-failure 5 \ + lcp-echo-interval 15 \ + lock \ + crtscts \ + nodefaultroute \ + usepeerdns \ + ipparam "${interface}" \ + ip-up-script /lib/netifd/ppp-up \ + ip-down-script /lib/netifd/ppp-down +} + +modemmanager_disconnected_method_ppp_ipv4() { + local interface="$1" + + echo "running disconnection (ppp method)" + + [ -n "${ERROR}" ] && { + local errorstring + errorstring=$(ppp_exitcode_tostring "${ERROR}") + case "$ERROR" in + 0) + ;; + 2) + proto_notify_error "$interface" "$errorstring" + proto_block_restart "$interface" + ;; + *) + proto_notify_error "$interface" "$errorstring" + ;; + esac + } || echo "pppd result code not given" + + proto_kill_command "$interface" +} + +modemmanager_connected_method_dhcp_ipv4() { + local interface="$1" + local wwan="$2" + local metric="$3" + local defaultroute="$4" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + proto_send_update "${interface}" + + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@${interface}" + json_add_string proto "dhcp" + proto_add_dynamic_defaults + [ -n "$metric" ] && json_add_int metric "${metric}" + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +modemmanager_connected_method_static_ipv4() { + local interface="$1" + local wwan="$2" + local address="$3" + local prefix="$4" + local gateway="$5" + local mtu="$6" + local dns1="$7" + local dns2="$8" + local metric="$9" + local defaultroute="$10" + + local mask="" + + [ -n "${address}" ] || { + proto_notify_error "${interface}" ADDRESS_MISSING + return + } + + [ -n "${prefix}" ] || { + proto_notify_error "${interface}" PREFIX_MISSING + return + } + mask=$(cdr2mask "${prefix}") + + [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + echo "adding IPv4 address ${address}, netmask ${mask}" + proto_add_ipv4_address "${address}" "${mask}" + [ -n "${gateway}" ] && [ "${defaultroute}" != 0 ] && { + echo "adding default IPv4 route via ${gateway}" + proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}" + } + [ -n "${dns1}" ] && { + echo "adding primary DNS at ${dns1}" + proto_add_dns_server "${dns1}" + } + [ -n "${dns2}" ] && { + echo "adding secondary DNS at ${dns2}" + proto_add_dns_server "${dns2}" + } + [ -n "$metric" ] && json_add_int metric "${metric}" + proto_send_update "${interface}" +} + +modemmanager_connected_method_dhcp_ipv6() { + local interface="$1" + local wwan="$2" + local metric="$3" + local defaultroute="$4" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + proto_send_update "${interface}" + + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@${interface}" + json_add_string proto "dhcpv6" + proto_add_dynamic_defaults + json_add_string extendprefix 1 # RFC 7278: Extend an IPv6 /64 Prefix to LAN + [ -n "$metric" ] && json_add_int metric "${metric}" + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +modemmanager_connected_method_static_ipv6() { + local interface="$1" + local wwan="$2" + local address="$3" + local prefix="$4" + local gateway="$5" + local mtu="$6" + local dns1="$7" + local dns2="$8" + local metric="$9" + local defaultroute="$10" + + [ -n "${address}" ] || { + proto_notify_error "${interface}" ADDRESS_MISSING + return + } + + [ -n "${prefix}" ] || { + proto_notify_error "${interface}" PREFIX_MISSING + return + } + + [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + echo "adding IPv6 address ${address}, prefix ${prefix}" + proto_add_ipv6_address "${address}" "128" + proto_add_ipv6_prefix "${address}/${prefix}" + [ -n "${gateway}" ] && [ "$defaultroute" != 0 ] && { + echo "adding default IPv6 route via ${gateway}" + proto_add_ipv6_route "${gateway}" "128" + proto_add_ipv6_route "::0" "0" "${gateway}" "" "" "${address}/${prefix}" + } + [ -n "${dns1}" ] && { + echo "adding primary DNS at ${dns1}" + proto_add_dns_server "${dns1}" + } + [ -n "${dns2}" ] && { + echo "adding secondary DNS at ${dns2}" + proto_add_dns_server "${dns2}" + } + [ -n "$metric" ] && json_add_int metric "${metric}" + proto_send_update "${interface}" +} + +modemmanager_disconnected_method_common() { + local interface="$1" + + echo "running disconnection (common)" + proto_notify_error "${interface}" MM_DISCONNECT_IN_PROGRESS + + proto_init_update "*" 0 + proto_send_update "${interface}" +} + +proto_modemmanager_init_config() { + available=1 + no_device=1 + proto_config_add_string device + proto_config_add_string apn + proto_config_add_string 'allowedauth:list(string)' + proto_config_add_string username + proto_config_add_string password + proto_config_add_string pincode + proto_config_add_string iptype + proto_config_add_int signalrate + proto_config_add_boolean lowpower + proto_config_add_defaults +} + +proto_modemmanager_setup() { + local interface="$1" + + local modempath modemstatus bearercount bearerpath connectargs bearerstatus beareriface + local bearermethod_ipv4 bearermethod_ipv6 auth cliauth + local operatorname operatorid registration accesstech signalquality + + local device apn allowedauth username password pincode iptype metric signalrate + + local address prefix gateway mtu dns1 dns2 defaultroute + + json_get_vars device apn allowedauth username password pincode iptype metric signalrate defaultroute + + # validate sysfs path given in config + [ -n "${device}" ] || { + echo "No device specified" + proto_notify_error "${interface}" NO_DEVICE + proto_set_available "${interface}" 0 + return 1 + } + [ -e "${device}" ] || { + echo "Device not found in sysfs" + proto_set_available "${interface}" 0 + return 1 + } + + # validate that ModemManager is handling the modem at the sysfs path + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + modempath=$(modemmanager_get_field "${modemstatus}" "modem.dbus-path") + [ -n "${modempath}" ] || { + echo "Device not managed by ModemManager" + proto_notify_error "${interface}" DEVICE_NOT_MANAGED + proto_set_available "${interface}" 0 + return 1 + } + echo "modem available at ${modempath}" + + # always cleanup before attempting a new connection, just in case + modemmanager_cleanup_connection "${modemstatus}" + + # if allowedauth list given, build option string + for auth in $allowedauth; do + cliauth="${cliauth}${cliauth:+|}$auth" + done + + # setup connect args; APN mandatory (even if it may be empty) + echo "starting connection with apn '${apn}'..." + proto_notify_error "${interface}" MM_CONNECT_IN_PROGRESS + + connectargs="apn=${apn}${iptype:+,ip-type=${iptype}}${cliauth:+,allowed-auth=${cliauth}}${username:+,user=${username}}${password:+,password=${password}}${pincode:+,pin=${pincode}}" + mmcli --modem="${device}" --timeout 120 --simple-connect="${connectargs}" || { + proto_notify_error "${interface}" MM_CONNECT_FAILED + proto_block_restart "${interface}" + return 1 + } + + # check if Signal refresh rate is set + if [ -n "${signalrate}" ] && [ "${signalrate}" -eq "${signalrate}" ] 2>/dev/null; then + echo "setting signal refresh rate to ${signalrate} seconds" + mmcli --modem="${device}" --signal-setup="${signalrate}" + else + echo "signal refresh rate is not set" + fi + + # log additional useful information + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + operatorname=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-name") + [ -n "${operatorname}" ] && echo "network operator name: ${operatorname}" + operatorid=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-code") + [ -n "${operatorid}" ] && echo "network operator MCCMNC: ${operatorid}" + registration=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.registration-state") + [ -n "${registration}" ] && echo "registration type: ${registration}" + accesstech=$(modemmanager_get_multivalue_field "${modemstatus}" "modem.generic.access-technologies") + [ -n "${accesstech}" ] && echo "access technology: ${accesstech}" + signalquality=$(modemmanager_get_field "${modemstatus}" "modem.generic.signal-quality.value") + [ -n "${signalquality}" ] && echo "signal quality: ${signalquality}%" + + # we won't like it if there are more than one bearers, as that would mean the + # user manually created them, and that's unsupported by this proto + bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") + [ -n "${bearercount}" ] && [ "$bearercount" -eq 1 ] || { + proto_notify_error "${interface}" INVALID_BEARER_LIST + return 1 + } + + # load connected bearer information + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") + bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) + + # load network interface and method information + beareriface=$(modemmanager_get_field "${bearerstatus}" "bearer.status.interface") + bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") + bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") + + # setup IPv4 + [ -n "${bearermethod_ipv4}" ] && { + echo "IPv4 connection setup required in interface ${interface}: ${bearermethod_ipv4}" + case "${bearermethod_ipv4}" in + "dhcp") + modemmanager_connected_method_dhcp_ipv4 "${interface}" "${beareriface}" "${metric}" "${defaultroute}" + ;; + "static") + address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.address") + prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.prefix") + gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.gateway") + mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.mtu") + dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[1\]") + dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[2\]") + modemmanager_connected_method_static_ipv4 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" "${defaultroute}" + ;; + "ppp") + modemmanager_connected_method_ppp_ipv4 "${interface}" "${beareriface}" "${username}" "${password}" "${allowedauth}" + ;; + *) + proto_notify_error "${interface}" UNKNOWN_METHOD + return 1 + ;; + esac + } + + # setup IPv6 + # note: if using ipv4v6, both IPv4 and IPv6 settings will have the same MTU and metric values reported + [ -n "${bearermethod_ipv6}" ] && { + echo "IPv6 connection setup required in interface ${interface}: ${bearermethod_ipv6}" + case "${bearermethod_ipv6}" in + "dhcp") + modemmanager_connected_method_dhcp_ipv6 "${interface}" "${beareriface}" "${metric}" "${defaultroute}" + ;; + "static") + address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.address") + prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.prefix") + gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.gateway") + mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.mtu") + dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[1\]") + dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[2\]") + modemmanager_connected_method_static_ipv6 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" "${defaultroute}" + ;; + "ppp") + proto_notify_error "${interface}" "unsupported method" + return 1 + ;; + *) + proto_notify_error "${interface}" UNKNOWN_METHOD + return 1 + ;; + esac + } + + return 0 +} + +proto_modemmanager_teardown() { + local interface="$1" + + local modemstatus bearerpath errorstring + local bearermethod_ipv4 bearermethod_ipv6 + + local device lowpower iptype + json_get_vars device lowpower iptype + + echo "stopping network" + proto_notify_error "${interface}" MM_TEARDOWN_IN_PROGRESS + + # load connected bearer information, just the first one should be ok + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") + [ -n "${bearerpath}" ] || { + echo "couldn't load bearer path" + return + } + + # load bearer connection methods + bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) + bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") + [ -n "${bearermethod_ipv4}" ] && + echo "IPv4 connection teardown required in interface ${interface}: ${bearermethod_ipv4}" + bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") + [ -n "${bearermethod_ipv6}" ] && + echo "IPv6 connection teardown required in interface ${interface}: ${bearermethod_ipv6}" + + # disconnection handling only requires special treatment in IPv4/PPP + [ "${bearermethod_ipv4}" = "ppp" ] && modemmanager_disconnected_method_ppp_ipv4 "${interface}" + modemmanager_disconnected_method_common "${interface}" + + # disconnect + mmcli --modem="${device}" --simple-disconnect || + proto_notify_error "${interface}" DISCONNECT_FAILED + + # disable + mmcli --modem="${device}" --disable + proto_notify_error "${interface}" MM_MODEM_DISABLED + + # low power, only if requested + [ "${lowpower:-0}" -lt 1 ] || + mmcli --modem="${device}" --set-power-state-low +} + +[ -n "$INCLUDE_ONLY" ] || { + add_protocol modemmanager +} diff --git a/modemmanager/files/usr/sbin/ModemManager-wrapper b/modemmanager/files/usr/sbin/ModemManager-wrapper new file mode 100755 index 000000000..4fd64227f --- /dev/null +++ b/modemmanager/files/usr/sbin/ModemManager-wrapper @@ -0,0 +1,33 @@ +#!/bin/sh + +trap_with_arg() { + func="$1" ; shift + for sig ; do + # shellcheck disable=SC2064 + trap "$func $sig" "$sig" + done +} + +func_trap() { + logger "ModemManager-wrapper[$$]" "Sending signal ${1}..." + kill "-${1}" "$CHILD" 2>/dev/null +} + +main() { + . /usr/share/ModemManager/modemmanager.common + + trap_with_arg func_trap INT TERM KILL + + mkdir -p "${MODEMMANAGER_RUNDIR}" + chmod 0755 "${MODEMMANAGER_RUNDIR}" + mm_cleanup_interfaces + + /usr/sbin/ModemManager "$@" 1>/dev/null 2>/dev/null & + CHILD="$!" + + mm_report_events_from_cache + + wait "$CHILD" +} + +main "$@" diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 7dd629733..ac2b7496d 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -33,24 +33,24 @@ global_multipath_settings() { # Global MPTCP configuration if [ -f /proc/sys/net/mptcp/mptcp_enabled ]; then - sysctl -qw net.mptcp.mptcp_enabled="$multipath_status" - [ -z "$mptcp_path_manager" ] || sysctl -qw net.mptcp.mptcp_path_manager="$mptcp_path_manager" - [ -z "$mptcp_scheduler" ] || sysctl -qw net.mptcp.mptcp_scheduler="$mptcp_scheduler" - [ -z "$mptcp_checksum" ] || sysctl -qw net.mptcp.mptcp_checksum="$mptcp_checksum" - [ -z "$mptcp_debug" ] || sysctl -qw net.mptcp.mptcp_debug="$mptcp_debug" - [ -z "$mptcp_syn_retries" ] || sysctl -qw net.mptcp.mptcp_syn_retries="$mptcp_syn_retries" - [ -z "$mptcp_fullmesh_num_subflows" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/num_subflows="$mptcp_fullmesh_num_subflows" - [ -z "$mptcp_fullmesh_create_on_err" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/create_on_err="$mptcp_fullmesh_create_on_err" - [ -z "$mptcp_ndiffports_num_subflows" ] || sysctl -qw /sys/module/mptcp_ndiffports/parameters/num_subflows="$mptcp_ndiffports_num_subflows" - [ -z "$mptcp_rr_cwnd_limited" ] || sysctl -qw /sys/module/mptcp_rr/parameters/cwnd_limited="$mptcp_rr_cwnd_limited" - [ -z "$mptcp_rr_num_segments" ] || sysctl -qw /sys/module/mptcp_rr/parameters/num_segments="$mptcp_rr_num_segments" + sysctl -qew net.mptcp.mptcp_enabled="$multipath_status" + [ -z "$mptcp_path_manager" ] || sysctl -qew net.mptcp.mptcp_path_manager="$mptcp_path_manager" + [ -z "$mptcp_scheduler" ] || sysctl -qew net.mptcp.mptcp_scheduler="$mptcp_scheduler" + [ -z "$mptcp_checksum" ] || sysctl -qew net.mptcp.mptcp_checksum="$mptcp_checksum" + [ -z "$mptcp_debug" ] || sysctl -qew net.mptcp.mptcp_debug="$mptcp_debug" + [ -z "$mptcp_syn_retries" ] || sysctl -qew net.mptcp.mptcp_syn_retries="$mptcp_syn_retries" + [ -z "$mptcp_fullmesh_num_subflows" ] || sysctl -qew /sys/module/mptcp_fullmesh/parameters/num_subflows="$mptcp_fullmesh_num_subflows" + [ -z "$mptcp_fullmesh_create_on_err" ] || sysctl -qew /sys/module/mptcp_fullmesh/parameters/create_on_err="$mptcp_fullmesh_create_on_err" + [ -z "$mptcp_ndiffports_num_subflows" ] || sysctl -qew /sys/module/mptcp_ndiffports/parameters/num_subflows="$mptcp_ndiffports_num_subflows" + [ -z "$mptcp_rr_cwnd_limited" ] || sysctl -qew /sys/module/mptcp_rr/parameters/cwnd_limited="$mptcp_rr_cwnd_limited" + [ -z "$mptcp_rr_num_segments" ] || sysctl -qew /sys/module/mptcp_rr/parameters/num_segments="$mptcp_rr_num_segments" else - sysctl -qw net.mptcp.enabled="$multipath_status" + sysctl -qew net.mptcp.enabled="$multipath_status" ip mptcp limits set add_addr_accepted $mptcp_add_addr_accepted subflows $mptcp_subflows 2>&1 >/dev/null - [ -z "$mptcp_add_addr_timeout" ] || sysctl -qw net.mptcp.add_addr_timeout="$mptcp_add_addr_timeout" - [ -z "$mptcp_checksum" ] || sysctl -qw net.mptcp.checksum_enabled="$mptcp_checksum" + [ -z "$mptcp_add_addr_timeout" ] || sysctl -qew net.mptcp.add_addr_timeout="$mptcp_add_addr_timeout" + [ -z "$mptcp_checksum" ] || sysctl -qew net.mptcp.checksum_enabled="$mptcp_checksum" fi - [ -z "$congestion" ] || sysctl -qw net.ipv4.tcp_congestion_control="$congestion" + [ -z "$congestion" ] || sysctl -qew net.ipv4.tcp_congestion_control="$congestion" } interface_macaddr_count() { @@ -213,6 +213,7 @@ interface_multipath_settings() { [ -n "$netmask" ] && [ "$(echo $netmask | grep '/')" != "" ] && netmask="" [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep peer | awk '{print $4}' | cut -d/ -f2 | tr -d "\n") [ -z "$netmask" ] && netmask=$(ip -4 addr show dev $iface | grep inet | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") + [ -n "$ipaddr" ] && ipaddr=$(echo $ipaddr | cut -d/ -f1 | tr -d "\n") [ -n "$ipaddr" ] && [ -n "$netmask" ] && netmask=`ipcalc.sh $ipaddr $netmask | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` [ -n "$ipaddr" ] && [ -n "$netmask" ] && network=`ipcalc.sh $ipaddr $netmask | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi @@ -289,20 +290,20 @@ interface_multipath_settings() { ip6addr=`echo $ip6addr | cut -d/ -f1` netmask6=`ipcalc $ipaddr6 | sed -n '/PREFIX=/{;s/.*=//;s/ .*//;p;}'` network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` - if [ -z "$ip6addr" ] || [ -z "$network6" ]; then - ip6addr=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") - gateway6=$(ip -6 r list dev $iface | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") - [ -z "$gateway6" ] && gateway6=$(uci -q get "network.$config.ip6gw") - [ -z "$gateway6" ] && gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") - if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then - gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") - fi - if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then - gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") - fi - netmask6=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") - network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + fi + if [ -z "$ip6addr" ] || [ -z "$network6" ]; then + ip6addr=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f1 | tr -d "\n") + gateway6=$(ip -6 r list dev $iface | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n") + [ -z "$gateway6" ] && gateway6=$(uci -q get "network.$config.ip6gw") + [ -z "$gateway6" ] && gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then + gateway6=$(ubus call network.interface.$config status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n") fi + if [ -z "$gateway6" ] || [ "$( valid_subnet6 $gateway6 )" != "ok" ]; then + gateway6=$(ubus call network.interface.${config}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") + fi + netmask6=$(ip -6 addr show dev $iface | grep -v 'scope link' | grep inet6 | awk '{print $2}' | cut -d/ -f2 | tr -d "\n") + network6=`ipcalc $ip6addr | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` fi if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF >/dev/null @@ -315,7 +316,7 @@ interface_multipath_settings() { [ -n "$(ip -6 rule list | grep 6$id)" ] && ip -6 rule del table 6$id > /dev/null 2>&1 ip -6 route flush 6$id > /dev/null 2>&1 fi - if [ -n "$ip6addr" ] && [ -n "$gateway6" ] && [ -n "$network6" ]; then + if [ -n "$gateway6" ] && [ -n "$network6" ]; then if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then uci -q batch <<-EOF >/dev/null delete network.${config}_rule6 @@ -340,12 +341,12 @@ interface_multipath_settings() { commit network EOF else - ip -6 rule add from $ip6addr table 6$id pref 0 2>&1 >/dev/null + [ -n "$ip6addr" ] && ip -6 rule add from $ip6addr table 6$id pref 0 2>&1 >/dev/null ip -6 route replace $network6/$netmask6 dev $iface scope link metric 6$id 2>&1 >/dev/null ip -6 route replace $network6/$netmask6 dev $iface scope link table 6$id 2>&1 >/dev/null ip -6 route replace default via $gateway6 dev $iface table 6$id 2>&1 >/dev/null ip -6 route replace default via $gateway6 dev $iface metric 6$id 2>&1 >/dev/null - ip -6 route flush 6$id 2>&1 >/dev/null + #ip -6 route flush 6$id 2>&1 >/dev/null fi #config_get mode "$config" multipath "off" diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 972f3f203..4ddd9af5f 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -15,9 +15,10 @@ find_network_device() { [ "${name}" = "${device}" ] && device_section="${cfg}" } - - config_load network - config_foreach check_device device "$(uci -q netwok.${device}.device)" + if [ ! -z "$device" ]; then + config_load network + config_foreach check_device device "$(uci -q network.${device}.device)" + fi echo "${device_section}" } @@ -27,6 +28,7 @@ set_route() { PREVINTERFACE=$2 SETDEFAULT=$3 [ -z "$SETDEFAULT" ] && SETDEFAULT="yes" + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -53,7 +55,8 @@ set_route() { interface_gw=$(ubus call network.interface.${INTERFACE}_4 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") fi if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ]; then - [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "$PREVINTERFACE down. Replace default route by $interface_gw dev $interface_if" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && [ "$SETDEFAULT" = "yes" ] && _log "$PREVINTERFACE down. Replace default route by $interface_gw dev $interface_if" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && [ "$SETDEFAULT" != "yes" ] && _log "$PREVINTERFACE down. Replace default in table 991337 route by $interface_gw dev $interface_if" [ "$SETDEFAULT" = "yes" ] && ip route replace default scope global nexthop via $interface_gw dev $interface_if 2>&1 >/dev/null ip route replace default via $interface_gw dev $interface_if table 991337 2>&1 >/dev/null && SETROUTE=true fi @@ -66,6 +69,7 @@ set_route6() { PREVINTERFACE=$2 SETDEFAULT=$3 [ -z "$SETDEFAULT" ] && SETDEFAULT="yes" + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -107,6 +111,7 @@ set_server_default_route() { [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" config_get disabled $server disabled [ "$disabled" = "1" ] && return + [ -z "$OMR_TRACKER_INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { @@ -132,6 +137,7 @@ set_server_default_route6() { [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" config_get disabled $server disabled [ "$disabled" = "1" ] && return + [ -z "$OMR_TRACKER_INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { @@ -182,6 +188,7 @@ delete_server_default_route6() { set_routes_intf() { local multipath_config_route local INTERFACE=$1 + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -238,6 +245,7 @@ set_routes_intf() { set_routes_intf6() { local multipath_config_route local INTERFACE=$1 + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -310,6 +318,7 @@ set_routes_intf6() { set_route_balancing() { local multipath_config_route interface_gw interface_if INTERFACE=$1 + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -360,6 +369,7 @@ set_route_balancing() { set_route_balancing6() { local multipath_config_route interface_gw interface_if INTERFACE=$1 + [ -z "$INTERFACE" ] && return multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { @@ -425,6 +435,7 @@ set_route_balancing6() { set_server_all_routes() { local server=$1 + [ -z "$OMR_TRACKER_INTERFACE" ] && return server_route() { local serverip multipath_config_route serverip=$1 @@ -453,7 +464,7 @@ set_server_all_routes() { config_foreach set_routes_intf interface uintf="$(echo $routesintf | awk '{print $5}')" uintfb="$(echo $routesintfbackup | awk '{print $5}')" - if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 1 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf " ]) || ([ "$nbintf" = "1" ] && [ -n "$uintf" ] && [ "$(ip r show $serverip metric 1 | grep $uintf)" = "" ]); then + if [ -n "$routesintf" ] && ([ "$nbintf" -gt "1" ] && [ "$(ip r show $serverip metric 1 | tr -d '\t' | tr -d '\n' | sed 's/ *$//' | tr ' ' '\n' | sort | tr -d '\n')" != "$(echo $serverip $routesintf | sed 's/ *$//' | tr ' ' '\n' | sort | tr -d '\n')" ]) || ([ "$nbintf" = "1" ] && [ -n "$uintf" ] && [ "$(ip r show $serverip metric 1 | grep $uintf)" = "" ]); then while [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip r del $serverip done @@ -461,7 +472,7 @@ set_server_all_routes() { ip route replace $serverip scope global metric 1 $routesintf 2>&1 >/dev/null [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New server route is $(ip r show $serverip metric 1 | tr -d '\t' | tr -d '\n')" fi - if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip r show $serverip metric 999 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintfbackup " ]) || ([ "$nbintfb" = "1" ] && [ -n "$uintfb" ] && [ "$(ip r show $serverip metric 999 | grep $uintfb)" = "" ]); then + if [ -n "$routesintfbackup" ] && ([ "$nbintfb" -gt "1" ] && [ "$(ip r show $serverip metric 999 | tr -d '\t' | tr -d '\n' | sed 's/ *$//' | tr ' ' '\n' | sort | tr -d '\n')" != "$(echo $serverip $routesintfbackup | sed 's/ *$//' | tr ' ' '\n' | sort | tr -d '\n')" ]) || ([ "$nbintfb" = "1" ] && [ -n "$uintfb" ] && [ "$(ip r show $serverip metric 999 | grep $uintfb)" = "" ]); then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) backup default route $serverip $routesintfbackup nbintfb $nbintfb $OMR_TRACKER_DEVICE" ip route replace $serverip scope global metric 999 $routesintfbackup 2>&1 >/dev/null fi @@ -472,6 +483,7 @@ set_server_all_routes() { set_server_all_routes6() { local server=$1 + [ -z "$OMR_TRACKER_INTERFACE" ] && return server_route() { local serverip multipath_config_route serverip=$1 @@ -499,7 +511,7 @@ set_server_all_routes6() { config_foreach set_routes_intf6 interface uintf="$(echo $routesintf6 | awk '{print $5}')" uintfb="$(echo $routesintfbackup6 | awk '{print $5}')" - if [ -n "$routesintf6" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 1 | tr -d '\t' | tr -d '\n')" != "$serverip $routesintf6 " ]) || ([ "$nbintf6" = "1" ] && [ -n "$uintf" ] && [ "$(ip -6 r show $serverip metric 1 | grep $uintf)" = "" ]); then + if [ -n "$routesintf6" ] && ([ "$nbintf6" -gt "1" ] && [ "$(ip -6 r show $serverip metric 1 | tr -d '\t' | sort | tr -d '\n' | sed 's/ *$//')" != "$(echo $serverip $routesintf6 | sort | sed 's/ *$//')" ]) || ([ "$nbintf6" = "1" ] && [ -n "$uintf" ] && [ "$(ip -6 r show $serverip metric 1 | grep $uintf)" = "" ]); then while [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "$serverip" ] && [ "$(ip -6 r show $serverip | grep -v nexthop | sed 's/ //g' | tr -d '\n')" != "" ]; do ip -6 r del $serverip done @@ -520,6 +532,7 @@ set_server_all_routes6() { set_server_route() { local server=$1 + [ -z "$OMR_TRACKER_INTERFACE" ] && return server_route() { local serverip multipath_config_route serverip=$1 @@ -557,6 +570,7 @@ set_server_route() { set_server_route6() { local server=$1 + [ -z "$OMR_TRACKER_INTERFACE" ] && return server_route() { local serverip multipath_config_route serverip=$1 @@ -597,9 +611,13 @@ del_server_route() { remove_route() { local serverip="$1" [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" - [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" + [ -n "$serverip" ] && _log "Delete default route to $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" local metric - metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + if [ -z "$OMR_TRACKER_INTERFACE" ]; then + metric=0 + else + metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + fi [ -n "$metric" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip | grep $OMR_TRACKER_DEVICE)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 @@ -617,11 +635,15 @@ del_server_route6() { remove_route() { local serverip="$1" [ -n "$serverip" ] && serverip="$(resolveip -6 -t 5 $serverip | head -n 1 | tr -d '\n')" - [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" + [ -n "$serverip" ] && _log "Delete default route to $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" local metric - metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) - [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 - [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + if [ -z "$OMR_TRACKER_INTERFACE" ]; then + metric=0 + else + metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) + fi + [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$serverip"] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$serverip" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 } config_list_foreach $server ip remove_route if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then @@ -649,7 +671,7 @@ disable_pihole() { enable_pihole() { local server=$1 nbserver=$((nbserver+1)) - if [ "$(uci -q get openmptcprouter.${server}.pihole)" = "1" ] && [ "$(uci -q get dhcp.@dnsmasq[0].server | grep '127.0.0.1#5353')" != "" ]; then + if [ -n "$server" ] && [ "$(uci -q get openmptcprouter.${server}.pihole)" = "1" ] && [ "$(uci -q get dhcp.@dnsmasq[0].server | grep '127.0.0.1#5353')" != "" ]; then piholeenabled=$((piholeenabled+1)) fi } @@ -684,7 +706,7 @@ interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e # An interface in error will never be used in MPTCP if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then - if [ "$interface_up" = "true" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then + if [ "$interface_up" = "true" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then _log "No answer from $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE), restart interface" _log "Set $OMR_TRACKER_INTERFACE down" ifdown $OMR_TRACKER_INTERFACE @@ -697,7 +719,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ "$OMR_TRACKER_PREV_STATUS" = "$OMR_TRACKER_STATUS" ]; then exit 0 fi - if [ "$multipath_status" != "off" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ]; then + if [ "$multipath_status" != "off" ] || ([ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ]); then if [ "$OMR_TRACKER_STATUS_MSG" = "" ]; then _log "$OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) switched off" else @@ -713,7 +735,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ -n "$OMR_TRACKER_DEVICE_IP6" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set down > /dev/null 2>&1 fi - if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ] && [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ]; then + if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ] && [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ]; then VPN_BASE_INTF="$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.baseintf)" VPN_BASE_INTF_IP=$(ubus call network.interface.$VPN_BASE_INTF status | jsonfilter -e '@["ipv4-address"][0].address' | tr -d "\n") uci -q batch <<-EOF >/dev/null @@ -727,19 +749,25 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then config_foreach del_server_route6 server #if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(uci -q get openmptcprouter.settings.vpn)" != "mlvpn" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set balancing route (current: $(ip r) )" config_foreach set_server_all_routes server config_foreach set_server_all_routes6 server + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set balancing route done (new: $(ip r) )" fi fi - if ([ "$default_gw" = "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ] || [ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then - config_load network - config_foreach set_route interface $OMR_TRACKER_INTERFACE - config_foreach set_route6 interface $OMR_TRACKER_INTERFACE - elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath)" = "master" ]; then - config_load network - config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" - config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" + if [ -n "$OMR_TRACKER_INTERFACE" ]; then + if ([ "$default_gw" = "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ] || [ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ]) && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Default gw: $default_gw - Set routes (current: $(ip r) )" + config_load network + config_foreach set_route interface $OMR_TRACKER_INTERFACE + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New routes $(ip r)" + elif [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath)" = "master" ]; then + config_load network + config_foreach set_route interface $OMR_TRACKER_INTERFACE "no" + config_foreach set_route6 interface $OMR_TRACKER_INTERFACE "no" + fi fi mail_alert="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.mail_alert)" [ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)" @@ -836,15 +864,17 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om fi if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Current route: $(ip r)" ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null if [ "$(pgrep openmptcprouter-vps)" = "" ]; then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 fi [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && conntrack -D -p udp 2>&1 >/dev/null + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New route: $(ip r)" fi # Set VPN MTU - if [ -n "$OMR_TRACKER_LATENCY" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ]); then + if [ -n "$OMR_TRACKER_LATENCY" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ]); then local serverip=$(uci -q get shadowsocks-libev.sss0.server) [ -n "$serverip" ] && serverip="$(resolveip -4 -t 5 $serverip | head -n 1 | tr -d '\n')" if [ "$serverip" = "192.168.1.3" ] || [ "$serverip" = "127.0.0.1" ]; then @@ -853,8 +883,9 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE="interface" uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then - if [ -n "$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then - mtu=$(uci -q get network.$(find_network_device ${OMR_TRACKER_INTERFACE}).mtu) + OMR_NETWORK_DEVICE=$(find_network_device ${OMR_TRACKER_INTERFACE}) + if [ -n "$OMR_NETWORK_DEVICE" ] && [ -n "$(uci -q get network.$OMR_NETWORK_DEVICE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then + mtu=$(uci -q get network.$OMR_NETWORK_DEVICE.mtu) uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu [ -n "$mtu" ] && ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") @@ -938,7 +969,7 @@ if [ "$multipath_config" = "master" ]; then if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") - if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then + if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then _log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null fi @@ -968,7 +999,7 @@ if [ "$multipath_config" = "master" ]; then if [ "$(uci -q get openmptcprouter.settings.master)" = "balancing" ] && [ "$(ip route show default | grep weight)" = "" ] && [ "$(uci -q get openmptcprouter.settings.defaultgw)" != "0" ]; then omrvpn_intf=$(uci -q get "network.omrvpn.device" || echo "tun0") [ -z "$omrvpn_intf" ] && omrvpn_intf=$(uci -q get "network.omrvpn.ifname" || echo "tun0") - if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then + if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | grep -v metric | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ]; then routesbalancing="" routesbalancingbackup="" nbintf=0 @@ -980,8 +1011,10 @@ if [ "$multipath_config" = "master" ]; then config_foreach set_route_balancing6 interface [ -n "$routesbalancing" ] && { ([ "$nbintf" -gt "1" ] && [ "$(ip r show default metric 1 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancing " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 1 | grep $OMR_TRACKER_DEVICE)" = "" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { - _log "Set ip route replace default scope global $routesbalancing" + _log "Change in routes, set ip route replace default scope global $routesbalancing (omrvpn_intf: $omrvpn_intf)" + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Current route: $(ip r)" ip route replace default scope global metric 1 $routesbalancing 2>&1 >/dev/null + [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "New route: $(ip r)" } } [ -n "$routesbalancing6" ] && { @@ -992,7 +1025,7 @@ if [ "$multipath_config" = "master" ]; then } [ -n "$routesbalancingbackup" ] && { ([ "$nbintfb" -gt "1" ] && [ "$(ip r show default metric 999 | tr -d '\t' | tr -d '\n')" != "default via $routesbalancingbackup " ]) || ([ "$nbintf" = "1" ] && ([ "$(ip r show default metric 999 | grep $OMR_TRACKER_DEVICE)" = "" ] || [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]) && [ -n "$OMR_TRACKER_DEVICE_IP" ]) && { - _log "Set backup ip route replace default scope global $routesbalancingbackup" + _log "Set backup ip route replace default scope global metric 999 $routesbalancingbackup" ip route replace default scope global metric 999 $routesbalancingbackup 2>&1 >/dev/null } } @@ -1025,7 +1058,8 @@ if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then config_foreach set_server_route server fi if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then - ip r replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 + _log "Interface route not yet set, set route ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" + ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 fi fi if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then @@ -1056,7 +1090,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then serverip=$1 #gtudpst="up" #[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$multipath_config" = "backup" ] && [ "$(pgrep glorytun-udp)" != "" ] && gtudpst="backup" - if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP)" = "" ] && [ -n "$(resolveip -4 $serverip)" ]; then + if [ "$OMR_TRACKER_DEVICE_IP" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP | grep running)" = "" ] && [ -n "$(resolveip -4 $serverip)" ]; then if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 @@ -1071,7 +1105,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then fi fi fi - if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6)" = "" ] && [ -n "$(resolveip -6 $serverip)" ]; then + if [ "$OMR_TRACKER_DEVICE_IP6" != "" ] && [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" != "1" ] && [ "$(pgrep glorytun-udp)" != "" ] && [ "$(glorytun-udp path | grep $OMR_TRACKER_DEVICE_IP6 | grep running)" = "" ] && [ -n "$(resolveip -6 $serverip)" ]; then if [ "$download" != "0" ] && [ "$download" != "" ] && [ "$upload" != "0" ] && [ "$upload" != "" ]; then if [ "$(uci -q get glorytun-udp.vpn.rateauto)" = "1" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 to addr $serverip port ${gtudp_port} dev ${gtudp_dev} set up rate auto tx $((upload*1000/8)) rx $((download*1000/8)) pref 1 > /dev/null 2>&1 @@ -1101,7 +1135,7 @@ if [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; then fi [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && { [ "$multipath_status" = "$multipath_config" ] || { - if [ "$(sysctl -qn net.mptcp.mptcp_enabled | tr -d '\n')" = "1" ] || [ "$(sysctl -qn net.mptcp.enabled | tr -d '\n')" = "1" ]; then + if [ "$(sysctl -qen net.mptcp.mptcp_enabled | tr -d '\n')" = "1" ] || [ "$(sysctl -qen net.mptcp.enabled | tr -d '\n')" = "1" ]; then _log "Multipath $OMR_TRACKER_DEVICE switched to $multipath_config" multipath "$OMR_TRACKER_DEVICE" "$multipath_config" fi @@ -1507,7 +1541,7 @@ if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter fi -if [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then +if [ "$(uci -q show openmptcprouter | grep server)" != "" ] && [ "$(pgrep openmptcprouter-vps)" = "" ] && [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" = "" ] && ([ "$(uci -q show openmptcprouter | grep set_firewall=\'1\')" != "" ] || [ -z "$(iptables-save | grep omr_dst_bypass_${OMR_TRACKER_DEVICE})" ]); then _log "Set firewall on server" /etc/init.d/openmptcprouter-vps set_vps_firewall >/dev/null 2>&1 diff --git a/mptcpd/patches/remove_log.patch b/mptcpd/patches/remove_log.patch old mode 100644 new mode 100755 diff --git a/netifd/Makefile b/netifd/Makefile new file mode 100644 index 000000000..4b5f110da --- /dev/null +++ b/netifd/Makefile @@ -0,0 +1,52 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=netifd +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git +PKG_SOURCE_DATE:=2021-07-26 +PKG_SOURCE_VERSION:=440eb0647708274cc8d7d9e7c2bb0cfdfba90023 +PKG_MIRROR_HASH:=eed957036ab608fdc49bdf801fc5b4405fcd2a3a5e5d3343ec39898e156c10e9 +PKG_MAINTAINER:=Felix Fietkau + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/netifd + SECTION:=base + CATEGORY:=Base system + DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox + TITLE:=OpenWrt Network Interface Configuration Daemon +endef + +define Package/netifd/conffiles +/etc/udhcpc.user +/etc/udhcpc.user.d/ +endef + +TARGET_CFLAGS += \ + -I$(STAGING_DIR)/usr/include/libnl-tiny \ + -I$(STAGING_DIR)/usr/include \ + -flto + +TARGET_LDFLAGS += -flto -fuse-linker-plugin + +CMAKE_OPTIONS += \ + -DLIBNL_LIBS=-lnl-tiny \ + -DDEBUG=1 + +define Package/netifd/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/netifd $(1)/sbin/ + $(CP) ./files/* $(1)/ + $(INSTALL_DIR) $(1)/etc/udhcpc.user.d/ + $(CP) $(PKG_BUILD_DIR)/scripts/* $(1)/lib/netifd/ +endef + +$(eval $(call BuildPackage,netifd)) diff --git a/netifd/files/etc/hotplug.d/iface/00-netstate b/netifd/files/etc/hotplug.d/iface/00-netstate new file mode 100644 index 000000000..71ccb0191 --- /dev/null +++ b/netifd/files/etc/hotplug.d/iface/00-netstate @@ -0,0 +1,6 @@ +[ ifup = "$ACTION" ] && { + uci_toggle_state network "$INTERFACE" up 1 + [ -n "$DEVICE" ] && { + uci_toggle_state network "$INTERFACE" ifname "$DEVICE" + } +} diff --git a/netifd/files/etc/hotplug.d/net/20-smp-packet-steering b/netifd/files/etc/hotplug.d/net/20-smp-packet-steering new file mode 100644 index 000000000..8a86bf75f --- /dev/null +++ b/netifd/files/etc/hotplug.d/net/20-smp-packet-steering @@ -0,0 +1,67 @@ +#!/bin/sh +[ "$ACTION" = add ] || exit + +NPROCS="$(grep -c "^processor.*:" /proc/cpuinfo)" +[ "$NPROCS" -gt 1 ] || exit + +PROC_MASK="$(( (1 << $NPROCS) - 1 ))" + +find_irq_cpu() { + local dev="$1" + local match="$(grep -m 1 "$dev\$" /proc/interrupts)" + local cpu=0 + + [ -n "$match" ] && { + set -- $match + shift + for cur in $(seq 1 $NPROCS); do + [ "$1" -gt 0 ] && { + cpu=$(($cur - 1)) + break + } + shift + done + } + + echo "$cpu" +} + +set_hex_val() { + local file="$1" + local val="$2" + val="$(printf %x "$val")" + [ -n "$DEBUG" ] && echo "$file = $val" + echo "$val" > "$file" +} + +packet_steering="$(uci get "network.@globals[0].packet_steering")" +[ "$packet_steering" != 1 ] && exit 0 + +exec 512>/var/lock/smp_tune.lock +flock 512 || exit 1 + +for dev in /sys/class/net/*; do + [ -d "$dev" ] || continue + + # ignore virtual interfaces + [ -n "$(ls "${dev}/" | grep '^lower_')" ] && continue + [ -d "${dev}/device" ] || continue + + device="$(readlink "${dev}/device")" + device="$(basename "$device")" + irq_cpu="$(find_irq_cpu "$device")" + irq_cpu_mask="$((1 << $irq_cpu))" + + for q in ${dev}/queues/tx-*; do + set_hex_val "$q/xps_cpus" "$PROC_MASK" + done + + # ignore dsa slave ports for RPS + subsys="$(readlink "${dev}/device/subsystem")" + subsys="$(basename "$subsys")" + [ "$subsys" = "mdio_bus" ] && continue + + for q in ${dev}/queues/rx-*; do + set_hex_val "$q/rps_cpus" "$PROC_MASK" + done +done diff --git a/netifd/files/etc/init.d/network b/netifd/files/etc/init.d/network new file mode 100755 index 000000000..dc208c4ce --- /dev/null +++ b/netifd/files/etc/init.d/network @@ -0,0 +1,144 @@ +#!/bin/sh /etc/rc.common + +START=20 +STOP=90 + +USE_PROCD=1 + +init_switch() { + setup_switch() { return 0; } + + include /lib/network + setup_switch +} + +start_service() { + init_switch + + procd_open_instance + procd_set_param command /sbin/netifd + procd_set_param respawn + procd_set_param watch network.interface + [ -e /proc/sys/kernel/core_pattern ] && { + procd_set_param limits core="unlimited" + } + procd_close_instance +} + +reload_service() { + local rv=0 + + init_switch + ubus call network reload || rv=1 + /sbin/wifi reload_legacy + return $rv +} + +stop_service() { + /sbin/wifi down + ifdown -a + sleep 1 +} + +validate_atm_bridge_section() +{ + uci_validate_section network "atm-bridge" "${1}" \ + 'unit:uinteger:0' \ + 'vci:range(32, 65535):35' \ + 'vpi:range(0, 255):8' \ + 'atmdev:uinteger:0' \ + 'encaps:or("llc", "vc"):llc' \ + 'payload:or("bridged", "routed"):bridged' +} + +validate_route_section() +{ + uci_validate_section network route "${1}" \ + 'interface:string' \ + 'target:cidr4' \ + 'netmask:netmask4' \ + 'gateway:ip4addr' \ + 'metric:uinteger' \ + 'mtu:uinteger' \ + 'table:or(range(0,65535),string)' +} + +validate_route6_section() +{ + uci_validate_section network route6 "${1}" \ + 'interface:string' \ + 'target:cidr6' \ + 'gateway:ip6addr' \ + 'metric:uinteger' \ + 'mtu:uinteger' \ + 'table:or(range(0,65535),string)' +} + +validate_rule_section() +{ + uci_validate_section network rule "${1}" \ + 'in:string' \ + 'out:string' \ + 'src:cidr4' \ + 'dest:cidr4' \ + 'tos:range(0,31)' \ + 'mark:string' \ + 'invert:bool' \ + 'lookup:or(range(0,65535),string)' \ + 'goto:range(0,65535)' \ + 'action:or("prohibit", "unreachable", "blackhole", "throw")' +} + +validate_rule6_section() +{ + uci_validate_section network rule6 "${1}" \ + 'in:string' \ + 'out:string' \ + 'src:cidr6' \ + 'dest:cidr6' \ + 'tos:range(0,31)' \ + 'mark:string' \ + 'invert:bool' \ + 'lookup:or(range(0,65535),string)' \ + 'goto:range(0,65535)' \ + 'action:or("prohibit", "unreachable", "blackhole", "throw")' +} + +validate_switch_section() +{ + uci_validate_section network switch "${1}" \ + 'name:string' \ + 'enable:bool' \ + 'enable_vlan:bool' \ + 'reset:bool' \ + 'ar8xxx_mib_poll_interval:uinteger' \ + 'ar8xxx_mib_type:range(0,1)' +} + +validate_switch_vlan() +{ + uci_validate_section network switch_vlan "${1}" \ + 'device:string' \ + 'vlan:uinteger' \ + 'ports:list(ports)' +} + +service_triggers() +{ + procd_add_reload_trigger network wireless + + procd_open_validate + validate_atm_bridge_section + validate_route_section + [ -e /proc/sys/net/ipv6 ] && validate_route6_section + validate_rule_section + [ -e /proc/sys/net/ipv6 ] && validate_rule6_section + validate_switch_section + validate_switch_vlan + procd_close_validate +} + +shutdown() { + ifdown -a + sleep 1 +} diff --git a/netifd/files/etc/uci-defaults/14_migrate-dhcp-release b/netifd/files/etc/uci-defaults/14_migrate-dhcp-release new file mode 100644 index 000000000..f1b384eec --- /dev/null +++ b/netifd/files/etc/uci-defaults/14_migrate-dhcp-release @@ -0,0 +1,23 @@ +. /lib/functions.sh + +migrate_release() { + local config="$1" + local proto + local release + + config_get proto "$config" proto + config_get release "$config" release + + [ "$proto" = "dhcp" ] && [ -n "$release" ] && { + norelease="$((!$release))" + uci_set network "$config" norelease "$norelease" + uci_remove network "$config" release + } + +} + +config_load network +config_foreach migrate_release interface +uci commit network + +exit 0 diff --git a/netifd/files/etc/udhcpc.user b/netifd/files/etc/udhcpc.user new file mode 100644 index 000000000..78e2ba5f1 --- /dev/null +++ b/netifd/files/etc/udhcpc.user @@ -0,0 +1 @@ +# This script is sourced by udhcpc's dhcp.script at every DHCP event. diff --git a/netifd/files/lib/netifd/dhcp.script b/netifd/files/lib/netifd/dhcp.script new file mode 100755 index 000000000..c857c9fc0 --- /dev/null +++ b/netifd/files/lib/netifd/dhcp.script @@ -0,0 +1,120 @@ +#!/bin/sh +[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1 + +. /lib/functions.sh +. /lib/netifd/netifd-proto.sh + +set_classless_routes() { + local max=128 + while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do + proto_add_ipv4_route "${1%%/*}" "${1##*/}" "$2" "$ip" + max=$(($max-1)) + shift 2 + done +} + +setup_interface() { + proto_init_update "*" 1 + proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}" + # TODO: apply $broadcast + + local ip_net + eval "$(ipcalc.sh "$ip/$mask")";ip_net="$NETWORK" + + local i + for i in $router; do + local gw_net + eval "$(ipcalc.sh "$i/$mask")";gw_net="$NETWORK" + + [ "$ip_net" != "$gw_net" ] && proto_add_ipv4_route "$i" 32 "" "$ip" + #[ "$DEFAULTROUTE" = 0 ] || proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" + proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" + + local r + for r in $CUSTOMROUTES; do + proto_add_ipv4_route "${r%%/*}" "${r##*/}" "$i" "$ip" + done + done + + # CIDR STATIC ROUTES (rfc3442) + [ -n "$staticroutes" ] && set_classless_routes $staticroutes + [ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes + + for i in $dns; do + proto_add_dns_server "$i" + done + for i in $domain; do + proto_add_dns_search "$i" + done + + # TODO: Deprecate timesvr in favor of timesrv + if [ -n "$timesvr" -a -z "$timesrv" ]; then + timesrv="$timesvr" + echo "Environment variable 'timesvr' will be deprecated; use 'timesrv' instead." + fi + + proto_add_data + [ -n "$ZONE" ] && json_add_string zone "$ZONE" + [ -n "$ntpsrv" ] && json_add_string ntpserver "$ntpsrv" + [ -n "$timesrv" ] && json_add_string timeserver "$timesrv" + [ -n "$hostname" ] && json_add_string hostname "$hostname" + [ -n "$message" ] && json_add_string message "$message" + [ -n "$timezone" ] && json_add_int timezone "$timezone" + [ -n "$lease" ] && json_add_int leasetime "$lease" + proto_close_data + + proto_send_update "$INTERFACE" + + + if [ "$IFACE6RD" != 0 -a -n "$ip6rd" ]; then + local v4mask="${ip6rd%% *}" + ip6rd="${ip6rd#* }" + local ip6rdprefixlen="${ip6rd%% *}" + ip6rd="${ip6rd#* }" + local ip6rdprefix="${ip6rd%% *}" + ip6rd="${ip6rd#* }" + local ip6rdbr="${ip6rd%% *}" + + [ -n "$ZONE" ] || ZONE=$(fw3 -q network $INTERFACE 2>/dev/null) + [ -z "$IFACE6RD" -o "$IFACE6RD" = 1 ] && IFACE6RD=${INTERFACE}_6 + + json_init + json_add_string name "$IFACE6RD" + json_add_string ifname "@$INTERFACE" + json_add_string proto "6rd" + json_add_string peeraddr "$ip6rdbr" + json_add_int ip4prefixlen "$v4mask" + json_add_string ip6prefix "$ip6rdprefix" + json_add_int ip6prefixlen "$ip6rdprefixlen" + json_add_string tunlink "$INTERFACE" + [ -n "$IFACE6RD_DELEGATE" ] && json_add_boolean delegate "$IFACE6RD_DELEGATE" + [ -n "$ZONE6RD" ] || ZONE6RD=$ZONE + [ -n "$ZONE6RD" ] && json_add_string zone "$ZONE6RD" + [ -n "$MTU6RD" ] && json_add_string mtu "$MTU6RD" + json_close_object + + ubus call network add_dynamic "$(json_dump)" + fi +} + +deconfig_interface() { + proto_init_update "*" 0 + proto_send_update "$INTERFACE" +} + +case "$1" in + deconfig) + deconfig_interface + ;; + renew|bound) + setup_interface + ;; +esac + +# user rules +[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user "$@" +for f in /etc/udhcpc.user.d/*; do + [ -f "$f" ] && (. "$f" "$@") +done + +exit 0 diff --git a/netifd/files/lib/netifd/proto/dhcp.sh b/netifd/files/lib/netifd/proto/dhcp.sh new file mode 100755 index 000000000..8db848260 --- /dev/null +++ b/netifd/files/lib/netifd/proto/dhcp.sh @@ -0,0 +1,89 @@ +#!/bin/sh + +[ -L /sbin/udhcpc ] || exit 0 + +. /lib/functions.sh +. ../netifd-proto.sh +init_proto "$@" + +proto_dhcp_init_config() { + renew_handler=1 + + proto_config_add_string 'ipaddr:ipaddr' + proto_config_add_string 'hostname:hostname' + proto_config_add_string clientid + proto_config_add_string vendorid + proto_config_add_boolean 'broadcast:bool' + proto_config_add_boolean 'norelease:bool' + proto_config_add_string 'reqopts:list(string)' + proto_config_add_boolean 'defaultreqopts:bool' + proto_config_add_string iface6rd + proto_config_add_array 'sendopts:list(string)' + proto_config_add_boolean delegate + proto_config_add_string zone6rd + proto_config_add_string zone + proto_config_add_string mtu6rd + proto_config_add_string customroutes + proto_config_add_boolean classlessroute +} + +proto_dhcp_add_sendopts() { + [ -n "$1" ] && append "$3" "-x $1" +} + +proto_dhcp_setup() { + local config="$1" + local iface="$2" + + local ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute defaultroute + json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute defaultroute + + local opt dhcpopts + for opt in $reqopts; do + append dhcpopts "-O $opt" + done + + json_for_each_item proto_dhcp_add_sendopts sendopts dhcpopts + + [ -z "$hostname" ] && hostname="$(cat /proc/sys/kernel/hostname)" + [ "$hostname" = "*" ] && hostname= + + [ "$defaultreqopts" = 0 ] && defaultreqopts="-o" || defaultreqopts= + [ "$broadcast" = 1 ] && broadcast="-B" || broadcast= + [ "$norelease" = 1 ] && norelease="" || norelease="-R" + [ -n "$clientid" ] && clientid="-x 0x3d:${clientid//:/}" || clientid="-C" + [ -n "$iface6rd" ] && proto_export "IFACE6RD=$iface6rd" + [ "$iface6rd" != 0 -a -f /lib/netifd/proto/6rd.sh ] && append dhcpopts "-O 212" + [ -n "$zone6rd" ] && proto_export "ZONE6RD=$zone6rd" + [ -n "$zone" ] && proto_export "ZONE=$zone" + [ -n "$mtu6rd" ] && proto_export "MTU6RD=$mtu6rd" + [ -n "$customroutes" ] && proto_export "CUSTOMROUTES=$customroutes" + [ -n "$defaultroute" ] && proto_export "DEFAULTROUTE=$defaultroute" + [ "$delegate" = "0" ] && proto_export "IFACE6RD_DELEGATE=0" + # Request classless route option (see RFC 3442) by default + [ "$classlessroute" = "0" ] || append dhcpopts "-O 121" + + proto_export "INTERFACE=$config" + proto_run_command "$config" udhcpc \ + -p /var/run/udhcpc-$iface.pid \ + -s /lib/netifd/dhcp.script \ + -f -t 0 -i "$iface" \ + ${ipaddr:+-r $ipaddr} \ + ${hostname:+-x "hostname:$hostname"} \ + ${vendorid:+-V "$vendorid"} \ + $clientid $defaultreqopts $broadcast $norelease $dhcpopts +} + +proto_dhcp_renew() { + local interface="$1" + # SIGUSR1 forces udhcpc to renew its lease + local sigusr1="$(kill -l SIGUSR1)" + [ -n "$sigusr1" ] && proto_kill_command "$interface" $sigusr1 +} + +proto_dhcp_teardown() { + local interface="$1" + proto_kill_command "$interface" +} + +add_protocol dhcp diff --git a/netifd/files/lib/network/config.sh b/netifd/files/lib/network/config.sh new file mode 100755 index 000000000..4cd28e4ce --- /dev/null +++ b/netifd/files/lib/network/config.sh @@ -0,0 +1,76 @@ +#!/bin/sh +# Copyright (C) 2011 OpenWrt.org + +. /usr/share/libubox/jshn.sh + +find_config() { + local device="$1" + local ifdev ifl3dev ifobj + for ifobj in $(ubus list network.interface.\*); do + interface="${ifobj##network.interface.}" + ( + json_load "$(ifstatus $interface)" + json_get_var ifdev device + json_get_var ifl3dev l3_device + if [ "$device" = "$ifdev" ] || [ "$device" = "$ifl3dev" ]; then + echo "$interface" + exit 0 + else + exit 1 + fi + ) && return + done +} + +unbridge() { + return +} + +ubus_call() { + json_init + local _data="$(ubus -S call "$1" "$2")" + [ -z "$_data" ] && return 1 + json_load "$_data" + return 0 +} + + +fixup_interface() { + local config="$1" + local ifname type device l3dev + + config_get type "$config" type + config_get ifname "$config" ifname + [ "bridge" = "$type" ] && ifname="br-$config" + ubus_call "network.interface.$config" status || return 0 + json_get_var l3dev l3_device + [ -n "$l3dev" ] && ifname="$l3dev" + json_init + config_set "$config" ifname "$ifname" +} + +scan_interfaces() { + config_load network + config_foreach fixup_interface interface +} + +prepare_interface_bridge() { + local config="$1" + + [ -n "$config" ] || return 0 + ubus call network.interface."$config" prepare +} + +setup_interface() { + local iface="$1" + local config="$2" + + [ -n "$config" ] || return 0 + ubus call network.interface."$config" add_device "{ \"name\": \"$iface\" }" +} + +do_sysctl() { + [ -n "$2" ] && \ + sysctl -n -e -w "$1=$2" >/dev/null || \ + sysctl -n -e "$1" +} diff --git a/netifd/files/sbin/devstatus b/netifd/files/sbin/devstatus new file mode 100755 index 000000000..3c35b26a4 --- /dev/null +++ b/netifd/files/sbin/devstatus @@ -0,0 +1,12 @@ +#!/bin/sh +. /usr/share/libubox/jshn.sh +DEVICE="$1" + +[ -n "$DEVICE" ] || { + echo "Usage: $0 " + exit 1 +} + +json_init +json_add_string name "$DEVICE" +ubus call network.device status "$(json_dump)" diff --git a/netifd/files/sbin/ifdown b/netifd/files/sbin/ifdown new file mode 120000 index 000000000..a0e5c176a --- /dev/null +++ b/netifd/files/sbin/ifdown @@ -0,0 +1 @@ +ifup \ No newline at end of file diff --git a/netifd/files/sbin/ifstatus b/netifd/files/sbin/ifstatus new file mode 100755 index 000000000..8a951e6e1 --- /dev/null +++ b/netifd/files/sbin/ifstatus @@ -0,0 +1,13 @@ +#!/bin/sh +INTERFACE="$1" + +[ -n "$INTERFACE" ] || { + echo "Usage: $0 " + exit 1 +} + +ubus -S list "network.interface.$INTERFACE" >/dev/null || { + echo "Interface $INTERFACE not found" + exit 1 +} +ubus call network.interface status "{ \"interface\" : \"$INTERFACE\" }" diff --git a/netifd/files/sbin/ifup b/netifd/files/sbin/ifup new file mode 100755 index 000000000..15be535bb --- /dev/null +++ b/netifd/files/sbin/ifup @@ -0,0 +1,77 @@ +#!/bin/sh + +ifup_all= +setup_wifi= + +if_call() { + local interface="$1" + for mode in $modes; do + ubus call network.interface $mode "{ \"interface\" : \"$interface\" }" + done +} + +case "$0" in + *ifdown) modes=down;; + *ifup) + modes="down up" + setup_wifi=1 + ;; + *) echo "Invalid command: $0";; +esac + +while :; do + case "$1" in + -a) + ifup_all=1 + shift + ;; + -w) + setup_wifi= + shift + ;; + *) + break + ;; + esac +done + +[ "$modes" = "down up" ] && ubus call network reload +if [ -n "$ifup_all" ]; then + for interface in $(ubus -S list 'network.interface.*'); do + if_call "${interface##network.interface.}" + done + [ -n "$setup_wifi" ] && /sbin/wifi up + exit +else + ubus -S list "network.interface.$1" > /dev/null || { + echo "Interface $1 not found" + exit + } + if_call "$1" +fi + +if [ -n "$setup_wifi" ] && grep -sq config /etc/config/wireless; then + . /lib/functions.sh + + find_related_radios() { + local wdev wnet + config_get wdev "$1" device + config_get wnet "$1" network + + if [ -n "$wdev" ]; then + for wnet in $wnet; do + if [ "$wnet" = "$network" ]; then + append radio_devs "$wdev" "$N" + fi + done + fi + } + + network="$1" + config_load wireless + config_foreach find_related_radios wifi-iface + + for dev in $(echo "$radio_devs" | sort -u); do + /sbin/wifi up "$dev" + done +fi diff --git a/netifd/files/usr/share/udhcpc/default.script b/netifd/files/usr/share/udhcpc/default.script new file mode 100755 index 000000000..0a9eb0180 --- /dev/null +++ b/netifd/files/usr/share/udhcpc/default.script @@ -0,0 +1,57 @@ +#!/bin/sh +[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1 + +set_classless_routes() { + local max=128 + local type + while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do + [ ${1##*/} -eq 32 ] && type=host || type=net + echo "udhcpc: adding route for $type $1 via $2" + route add -$type "$1" gw "$2" dev "$interface" + max=$(($max-1)) + shift 2 + done +} + +setup_interface() { + echo "udhcpc: ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface" + ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface + + [ -n "$router" ] && [ "$router" != "0.0.0.0" ] && [ "$router" != "255.255.255.255" ] && { + echo "udhcpc: setting default routers: $router" + + local valid_gw="" + for i in $router ; do + route add default gw $i dev $interface + valid_gw="${valid_gw:+$valid_gw|}$i" + done + + eval $(route -n | awk ' + /^0.0.0.0\W{9}('$valid_gw')\W/ {next} + /^0.0.0.0/ {print "route del -net "$1" gw "$2";"} + ') + } + + # CIDR STATIC ROUTES (rfc3442) + [ -n "$staticroutes" ] && set_classless_routes $staticroutes + [ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes +} + + +applied= +case "$1" in + deconfig) + ip -4 addr flush dev "$interface" + ;; + renew) + setup_interface update + ;; + bound) + setup_interface ifup + ;; +esac + +# user rules +[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user + +exit 0 diff --git a/omr-tracker/files/etc/config/omr-tracker b/omr-tracker/files/etc/config/omr-tracker index 93aaf1674..f0c485a70 100755 --- a/omr-tracker/files/etc/config/omr-tracker +++ b/omr-tracker/files/etc/config/omr-tracker @@ -23,7 +23,7 @@ config defaults 'defaults' option interval_tries '1' option type 'ping' option wait_test '0' - option server_http_test '1' + option server_http_test '0' option restart_down '0' option mail_alert '0' diff --git a/omr-tracker/files/etc/init.d/omr-tracker b/omr-tracker/files/etc/init.d/omr-tracker index 479ce2d5e..419e2bd05 100755 --- a/omr-tracker/files/etc/init.d/omr-tracker +++ b/omr-tracker/files/etc/init.d/omr-tracker @@ -28,7 +28,7 @@ _validate_section() { 'wait_test:uinteger' \ 'type:string:undef' \ 'enabled:bool:1' \ - 'server_http_test:bool:1' \ + 'server_http_test:bool:0' \ 'options:string' [ -z "$hosts" ] && hosts=$tmp_hosts diff --git a/omr-tracker/files/etc/uci-defaults/omr-tracker b/omr-tracker/files/etc/uci-defaults/omr-tracker index 13e4fe990..7ae77dddf 100755 --- a/omr-tracker/files/etc/uci-defaults/omr-tracker +++ b/omr-tracker/files/etc/uci-defaults/omr-tracker @@ -95,7 +95,7 @@ fi if [ "$(uci -q get omr-tracker.defaults.server_http_test)" = "" ]; then uci -q batch <<-EOF >/dev/null - set omr-tracker.defaults.server_http_test=1 + set omr-tracker.defaults.server_http_test=0 commit omr-tracker EOF fi diff --git a/openmptcprouter/files/etc/firewall.ttl b/openmptcprouter/files/etc/firewall.ttl old mode 100644 new mode 100755 diff --git a/openmptcprouter/files/etc/hotplug.d/iface/00-nego b/openmptcprouter/files/etc/hotplug.d/iface/00-nego old mode 100644 new mode 100755 diff --git a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks index f47a4200c..7ddcc4e57 100755 --- a/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks +++ b/openmptcprouter/files/etc/uci-defaults/1930-omr-shadowsocks @@ -53,6 +53,7 @@ fi if [ "$(uci -q get shadowsocks-libev.hi3)" != "" ]; then port=1100 + [ "$NBCPU" -gt "10" ] && NBCPU=10 for c in $(seq 1 2 $NBCPU); do uci -q batch <<-EOF >/dev/null set shadowsocks-libev.hi$c.local_port=$port diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index 2f33329f9..2d4e3cbd9 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -14,7 +14,6 @@ if [ "$(uci -q get openmptcprouter.latest_versions)" = "" ]; then if [ "$(uci -q show dhcp | grep 127.0.0.1#5353)" = "" ]; then uci -q batch <<-EOF >/dev/null add_list dhcp.@dnsmasq[-1].server="127.0.0.1#5353" - add_list dhcp.@dnsmasq[-1].server="8.8.8.8" add_list dhcp.@dnsmasq[-1].server="/lan/" commit dhcp EOF diff --git a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm index 030400bb9..ace19d8a4 100755 --- a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm +++ b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm @@ -10,7 +10,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then set sqm.wan1.script="simple.qos" set sqm.wan1.qdisc_advanced='0' set sqm.wan1.linklayer='none' - set sqm.wan1.enabled='0' + set sqm.wan1.enabled='1' set sqm.wan1.interface="${wan1}" set sqm.wan1.download='0' set sqm.wan1.upload='0' @@ -23,7 +23,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then set sqm.wan2.script="simple.qos" set sqm.wan2.qdisc_advanced='0' set sqm.wan2.linklayer='none' - set sqm.wan2.enabled='0' + set sqm.wan2.enabled='1' set sqm.wan2.interface="${wan2}" set sqm.wan2.download='0' set sqm.wan2.upload='0' @@ -41,7 +41,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then set sqm.wan3.script="simple.qos" set sqm.wan3.qdisc_advanced='0' set sqm.wan3.linklayer='none' - set sqm.wan3.enabled='0' + set sqm.wan3.enabled='1' set sqm.wan3.interface="${wan3}" set sqm.wan3.download='0' set sqm.wan3.upload='0' @@ -60,7 +60,7 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then set sqm.wan4.script="simple.qos" set sqm.wan4.qdisc_advanced='0' set sqm.wan4.linklayer='none' - set sqm.wan4.enabled='0' + set sqm.wan4.enabled='1' set sqm.wan4.interface="${wan4}" set sqm.wan4.download='0' set sqm.wan4.upload='0' @@ -93,6 +93,8 @@ if [ "$(uci -q get sqm.omrvpn)" = "" ]; then EOF fi +sed -i 's/SQM_SYSLOG=1/SQM_SYSLOG=0/g' /etc/sqm/sqm.conf + rm -f /tmp/luci-indexcache exit 0 diff --git a/openmptcprouter/files/etc/uci-defaults/2060-omr-system b/openmptcprouter/files/etc/uci-defaults/2060-omr-system index 902dae6dc..dd68fb82c 100755 --- a/openmptcprouter/files/etc/uci-defaults/2060-omr-system +++ b/openmptcprouter/files/etc/uci-defaults/2060-omr-system @@ -24,5 +24,11 @@ fi uci -q set openmptcprouter.settings.scaling_governor='performance' uci -q commit openmptcprouter } +[ -n "$(ubus call system board | jsonfilter -e '@.board_name' | grep wrt)" ] && [ "$(uci -q get system.@system[0].compat_version)" == "" ] && { + uci -q batch <<-EOF >/dev/null + set system.@system[-1].compat_version='1.1' + commit system + EOF +} exit 0 \ No newline at end of file diff --git a/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan b/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan index b321023e0..cab4295ea 100755 --- a/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan +++ b/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan @@ -4,11 +4,9 @@ if [ "$(grep usbmode /etc/rc.local)" = "" ]; then sed -i 's:exit 0::g' /etc/rc.local cat <<-EOF >> /etc/rc.local /bin/sleep 5 - /sbin/usbmode -l + /sbin/usbmode -l 2>&1 /dev/null /bin/sleep 3 - /sbin/usbmode -s - /bin/sleep 3 - /etc/init.d/getserveratboot restart + /sbin/usbmode -s 2>&1 /dev/null exit 0 EOF fi diff --git a/r8125/Makefile b/r8125/Makefile new file mode 100644 index 000000000..e9b213c6e --- /dev/null +++ b/r8125/Makefile @@ -0,0 +1,45 @@ +# Attribution: https://gist.github.com/lenew/9b41ba901c3393047ede0766760f9d55 + +#Put this source to 'package/lean/r8125' folder of OpenWRT/LEDE SDK +#Build(make menuconfig, make defconfig, make) + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=r8125 +PKG_VERSION:=9.006.04 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/r8125 + TITLE:=Driver for Realtek r8125 chipsets + SUBMENU:=Network Devices + VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) + FILES:= $(PKG_BUILD_DIR)/r8125.ko + AUTOLOAD:=$(call AutoProbe,r8125) +endef + +define Package/r8125/description + This package contains a driver for Realtek r8125 chipsets. +endef + +R8125_MAKEOPTS= -C $(PKG_BUILD_DIR) \ + PATH="$(TARGET_PATH)" \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + TARGET="$(HAL_TARGET)" \ + TOOLPREFIX="$(KERNEL_CROSS)" \ + TOOLPATH="$(KERNEL_CROSS)" \ + KERNELPATH="$(LINUX_DIR)" \ + KERNELDIR="$(LINUX_DIR)" \ + LDOPTS=" " \ + DOMULTI=1 + +define Build/Compile + $(MAKE) $(R8125_MAKEOPTS) modules +endef + +$(eval $(call KernelPackage,r8125)) diff --git a/r8125/src/Makefile b/r8125/src/Makefile new file mode 100755 index 000000000..514c0acdd --- /dev/null +++ b/r8125/src/Makefile @@ -0,0 +1,197 @@ +# SPDX-License-Identifier: GPL-2.0-only +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ + +################################################################################ +# This product is covered by one or more of the following patents: +# US6,570,884, US6,115,776, and US6,327,625. +################################################################################ + +CONFIG_SOC_LAN = n +ENABLE_REALWOW_SUPPORT = n +ENABLE_DASH_SUPPORT = n +ENABLE_DASH_PRINTER_SUPPORT = n +CONFIG_DOWN_SPEED_100 = n +CONFIG_ASPM = y +ENABLE_S5WOL = y +ENABLE_S5_KEEP_CURR_MAC = n +ENABLE_EEE = y +ENABLE_S0_MAGIC_PACKET = n +ENABLE_TX_NO_CLOSE = y +ENABLE_MULTIPLE_TX_QUEUE = n +ENABLE_PTP_SUPPORT = n +ENABLE_PTP_MASTER_MODE = n +ENABLE_RSS_SUPPORT = y +ENABLE_LIB_SUPPORT = n +ENABLE_USE_FIRMWARE_FILE = n +DISABLE_PM_SUPPORT = n +DISABLE_MULTI_MSIX_VECTOR = n + +ifneq ($(KERNELRELEASE),) + obj-m := r8125.o + r8125-objs := r8125_n.o rtl_eeprom.o rtltool.o + ifeq ($(CONFIG_SOC_LAN), y) + EXTRA_CFLAGS += -DCONFIG_SOC_LAN + endif + ifeq ($(ENABLE_REALWOW_SUPPORT), y) + r8125-objs += r8125_realwow.o + EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT + endif + ifeq ($(ENABLE_DASH_SUPPORT), y) + r8125-objs += r8125_dash.o + EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT + endif + ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y) + r8125-objs += r8125_dash.o + EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT + endif + EXTRA_CFLAGS += -DCONFIG_R8125_NAPI + EXTRA_CFLAGS += -DCONFIG_R8125_VLAN + ifeq ($(CONFIG_DOWN_SPEED_100), y) + EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100 + endif + ifeq ($(CONFIG_ASPM), y) + EXTRA_CFLAGS += -DCONFIG_ASPM + endif + ifeq ($(ENABLE_S5WOL), y) + EXTRA_CFLAGS += -DENABLE_S5WOL + endif + ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y) + EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC + endif + ifeq ($(ENABLE_EEE), y) + EXTRA_CFLAGS += -DENABLE_EEE + endif + ifeq ($(ENABLE_S0_MAGIC_PACKET), y) + EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET + endif + ifeq ($(ENABLE_TX_NO_CLOSE), y) + EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE + endif + ifeq ($(ENABLE_MULTIPLE_TX_QUEUE), y) + EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE + endif + ifeq ($(ENABLE_PTP_SUPPORT), y) + r8125-objs += r8125_ptp.o + EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT + endif + ifeq ($(ENABLE_PTP_MASTER_MODE), y) + EXTRA_CFLAGS += -DENABLE_PTP_MASTER_MODE + endif + ifeq ($(ENABLE_RSS_SUPPORT), y) + r8125-objs += r8125_rss.o + EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT + endif + ifeq ($(ENABLE_LIB_SUPPORT), y) + r8125-objs += r8125_lib.o + EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT + endif + ifeq ($(ENABLE_USE_FIRMWARE_FILE), y) + r8125-objs += r8125_firmware.o + EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE + endif + ifeq ($(DISABLE_PM_SUPPORT), y) + EXTRA_CFLAGS += -DDISABLE_PM_SUPPORT + endif + ifeq ($(DISABLE_MULTI_MSIX_VECTOR), y) + EXTRA_CFLAGS += -DDISABLE_MULTI_MSIX_VECTOR + endif +else + BASEDIR := /lib/modules/$(shell uname -r) + KERNELDIR ?= $(BASEDIR)/build + PWD :=$(shell pwd) + DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net/ethernet -name realtek -type d) + ifeq ($(DRIVERDIR),) + DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net -name realtek -type d) + endif + ifeq ($(DRIVERDIR),) + DRIVERDIR := $(BASEDIR)/kernel/drivers/net + endif + RTKDIR := $(subst $(BASEDIR)/,,$(DRIVERDIR)) + + KERNEL_GCC_VERSION := $(shell cat /proc/version | sed -n 's/.*gcc version \([[:digit:]]\.[[:digit:]]\.[[:digit:]]\).*/\1/p') + CCVERSION = $(shell $(CC) -dumpversion) + + KVER = $(shell uname -r) + KMAJ = $(shell echo $(KVER) | \ + sed -e 's/^\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*.*/\1/') + KMIN = $(shell echo $(KVER) | \ + sed -e 's/^[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*.*/\1/') + KREV = $(shell echo $(KVER) | \ + sed -e 's/^[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/') + + kver_ge = $(shell \ + echo test | awk '{if($(KMAJ) < $(1)) {print 0} else { \ + if($(KMAJ) > $(1)) {print 1} else { \ + if($(KMIN) < $(2)) {print 0} else { \ + if($(KMIN) > $(2)) {print 1} else { \ + if($(KREV) < $(3)) {print 0} else { print 1 } \ + }}}}}' \ + ) + +.PHONY: all +all: print_vars clean modules install + +print_vars: + @echo + @echo "CC: " $(CC) + @echo "CCVERSION: " $(CCVERSION) + @echo "KERNEL_GCC_VERSION: " $(KERNEL_GCC_VERSION) + @echo "KVER: " $(KVER) + @echo "KMAJ: " $(KMAJ) + @echo "KMIN: " $(KMIN) + @echo "KREV: " $(KREV) + @echo "BASEDIR: " $(BASEDIR) + @echo "DRIVERDIR: " $(DRIVERDIR) + @echo "PWD: " $(PWD) + @echo "RTKDIR: " $(RTKDIR) + @echo + +.PHONY:modules +modules: +#ifeq ($(call kver_ge,5,0,0),1) + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +#else +# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules +#endif + +.PHONY:clean +clean: +#ifeq ($(call kver_ge,5,0,0),1) + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean +#else +# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) clean +#endif + +.PHONY:install +install: +#ifeq ($(call kver_ge,5,0,0),1) + $(MAKE) -C $(KERNELDIR) M=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install +#else +# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install +#endif + +endif diff --git a/r8125/src/Makefile_linux24x b/r8125/src/Makefile_linux24x new file mode 100755 index 000000000..d043fb00c --- /dev/null +++ b/r8125/src/Makefile_linux24x @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: GPL-2.0-only +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ + +################################################################################ +# This product is covered by one or more of the following patents: +# US6,570,884, US6,115,776, and US6,327,625. +################################################################################ + +CC := gcc +LD := ld +ARCH := $(shell uname -m | sed 's/i.86/i386/') +KSRC := /lib/modules/$(shell uname -r)/build +CONFIG_FILE := $(KSRC)/include/linux/autoconf.h +KMISC := /lib/modules/$(shell uname -r)/kernel/drivers/net/ + + +ifeq ($(ARCH),x86_64) + MODCFLAGS += -mcmodel=kernel -mno-red-zone +endif + +#standard flags for module builds +MODCFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall +MODCFLAGS += -I$(KSRC)/include -I. +MODCFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h +SOURCE := r8125_n.c rtl_eeprom.c rtltool.c +OBJS := $(SOURCE:.c=.o) + + +SMP := $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \ + grep CONFIG_SMP | awk '{print $$3}') + +ifneq ($(SMP),1) + SMP := 0 +endif + +ifeq ($(SMP),1) + MODCFLAGS += -D__SMP__ +endif + +modules: $(OBJS) + $(LD) -r $^ -o r8125.o + strip --strip-debug r8125.o + +%.o: %.c + $(CC) $(MODCFLAGS) -c $< -o $@ + +clean: + rm *.o -f + +install: + install -m 744 -c r8125.o $(KMISC) diff --git a/r8125/src/r8125.h b/r8125/src/r8125.h new file mode 100755 index 000000000..4875ccca4 --- /dev/null +++ b/r8125/src/r8125.h @@ -0,0 +1,2508 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef __R8125_H +#define __R8125_H + +//#include +#include +#include +#include +#include "r8125_dash.h" +#include "r8125_realwow.h" +#include "r8125_ptp.h" +#include "r8125_rss.h" +#ifdef ENABLE_LIB_SUPPORT +#include "r8125_lib.h" +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) +typedef int netdev_tx_t; +#endif + +/* +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)&& !defined(ENABLE_LIB_SUPPORT) +#define RTL_USE_NEW_INTR_API +#endif +*/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +#define skb_transport_offset(skb) (skb->h.raw - skb->data) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) +#define device_set_wakeup_enable(dev, val) do {} while (0) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) +static inline void ether_addr_copy(u8 *dst, const u8 *src) +{ + u16 *a = (u16 *)dst; + const u16 *b = (const u16 *)src; + + a[0] = b[0]; + a[1] = b[1]; + a[2] = b[2]; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) +#define IS_ERR_OR_NULL(ptr) (!ptr) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) +#define reinit_completion(x) ((x)->done = 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#define pm_runtime_mark_last_busy(x) +#define pm_runtime_put_autosuspend(x) pm_runtime_put(x) +#define pm_runtime_put_sync_autosuspend(x) pm_runtime_put_sync(x) + +static inline bool pm_runtime_suspended(struct device *dev) +{ + return dev->power.runtime_status == RPM_SUSPENDED + && !dev->power.disable_depth; +} + +static inline bool pm_runtime_active(struct device *dev) +{ + return dev->power.runtime_status == RPM_ACTIVE + || dev->power.disable_depth; +} +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +#define queue_delayed_work(long_wq, work, delay) schedule_delayed_work(work, delay) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) +#define netif_printk(priv, type, level, netdev, fmt, args...) \ + do { \ + if (netif_msg_##type(priv)) \ + printk(level "%s: " fmt,(netdev)->name , ##args); \ + } while (0) + +#define netif_emerg(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_EMERG, netdev, fmt, ##args) +#define netif_alert(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_ALERT, netdev, fmt, ##args) +#define netif_crit(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_CRIT, netdev, fmt, ##args) +#define netif_err(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_ERR, netdev, fmt, ##args) +#define netif_warn(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_WARNING, netdev, fmt, ##args) +#define netif_notice(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_NOTICE, netdev, fmt, ##args) +#define netif_info(priv, type, netdev, fmt, args...) \ + netif_printk(priv, type, KERN_INFO, (netdev), fmt, ##args) +#endif +#endif +#endif +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) +#define setup_timer(_timer, _function, _data) \ +do { \ + (_timer)->function = _function; \ + (_timer)->data = _data; \ + init_timer(_timer); \ +} while (0) +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) +#if defined(skb_vlan_tag_present) && !defined(vlan_tx_tag_present) +#define vlan_tx_tag_present skb_vlan_tag_present +#endif +#if defined(skb_vlan_tag_get) && !defined(vlan_tx_tag_get) +#define vlan_tx_tag_get skb_vlan_tag_get +#endif +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) + +#define RTL_ALLOC_SKB_INTR(napi, length) dev_alloc_skb(length) +#ifdef CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) +#undef RTL_ALLOC_SKB_INTR +#define RTL_ALLOC_SKB_INTR(napi, length) napi_alloc_skb(napi, length) +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) +#define netdev_features_t u32 +#endif +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) +#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK +#else +#ifndef NETIF_F_ALL_CSUM +#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK +#endif +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) +#define ENABLE_R8125_PROCFS +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#define NETIF_F_HW_VLAN_RX NETIF_F_HW_VLAN_CTAG_RX +#define NETIF_F_HW_VLAN_TX NETIF_F_HW_VLAN_CTAG_TX +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +#define __devinit +#define __devexit +#define __devexit_p(func) func +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +#define CHECKSUM_PARTIAL CHECKSUM_HW +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#define irqreturn_t void +#define IRQ_HANDLED 1 +#define IRQ_NONE 0 +#define IRQ_RETVAL(x) +#endif + +#ifndef NETIF_F_RXALL +#define NETIF_F_RXALL 0 +#endif + +#ifndef NETIF_F_RXFCS +#define NETIF_F_RXFCS 0 +#endif + +#ifndef HAVE_FREE_NETDEV +#define free_netdev(x) kfree(x) +#endif + +#ifndef SET_NETDEV_DEV +#define SET_NETDEV_DEV(net, pdev) +#endif + +#ifndef SET_MODULE_OWNER +#define SET_MODULE_OWNER(dev) +#endif + +#ifndef SA_SHIRQ +#define SA_SHIRQ IRQF_SHARED +#endif + +#ifndef NETIF_F_GSO +#define gso_size tso_size +#define gso_segs tso_segs +#endif + +#ifndef PCI_VENDOR_ID_DLINK +#define PCI_VENDOR_ID_DLINK 0x1186 +#endif + +#ifndef dma_mapping_error +#define dma_mapping_error(a,b) 0 +#endif + +#ifndef netif_err +#define netif_err(a,b,c,d) +#endif + +#ifndef AUTONEG_DISABLE +#define AUTONEG_DISABLE 0x00 +#endif + +#ifndef AUTONEG_ENABLE +#define AUTONEG_ENABLE 0x01 +#endif + +#ifndef BMCR_SPEED1000 +#define BMCR_SPEED1000 0x0040 +#endif + +#ifndef BMCR_SPEED100 +#define BMCR_SPEED100 0x2000 +#endif + +#ifndef BMCR_SPEED10 +#define BMCR_SPEED10 0x0000 +#endif + +#ifndef SPEED_UNKNOWN +#define SPEED_UNKNOWN -1 +#endif + +#ifndef DUPLEX_UNKNOWN +#define DUPLEX_UNKNOWN 0xff +#endif + +#ifndef SUPPORTED_Pause +#define SUPPORTED_Pause (1 << 13) +#endif + +#ifndef SUPPORTED_Asym_Pause +#define SUPPORTED_Asym_Pause (1 << 14) +#endif + +#ifndef MDIO_EEE_100TX +#define MDIO_EEE_100TX 0x0002 +#endif + +#ifndef MDIO_EEE_1000T +#define MDIO_EEE_1000T 0x0004 +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#ifdef CONFIG_NET_POLL_CONTROLLER +#define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8125_netpoll +#else +#define RTL_NET_POLL_CONTROLLER +#endif + +#ifdef CONFIG_R8125_VLAN +#define RTL_SET_VLAN dev->vlan_rx_register=rtl8125_vlan_rx_register +#else +#define RTL_SET_VLAN +#endif + +#define RTL_NET_DEVICE_OPS(ops) dev->open=rtl8125_open; \ + dev->hard_start_xmit=rtl8125_start_xmit; \ + dev->get_stats=rtl8125_get_stats; \ + dev->stop=rtl8125_close; \ + dev->tx_timeout=rtl8125_tx_timeout; \ + dev->set_multicast_list=rtl8125_set_rx_mode; \ + dev->change_mtu=rtl8125_change_mtu; \ + dev->set_mac_address=rtl8125_set_mac_address; \ + dev->do_ioctl=rtl8125_do_ioctl; \ + RTL_NET_POLL_CONTROLLER; \ + RTL_SET_VLAN; +#else +#define RTL_NET_DEVICE_OPS(ops) dev->netdev_ops=&ops +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef true +#define true 1 +#endif + +//Hardware will continue interrupt 10 times after interrupt finished. +#define RTK_KEEP_INTERRUPT_COUNT (10) + +//the low 32 bit address of receive buffer must be 8-byte alignment. +#ifndef NET_IP_ALIGN +#define NET_IP_ALIGN 2 +#endif +#define RTK_RX_ALIGN 8 + +#ifdef CONFIG_R8125_NAPI +#define NAPI_SUFFIX "-NAPI" +#else +#define NAPI_SUFFIX "" +#endif +#if defined(ENABLE_DASH_PRINTER_SUPPORT) +#define DASH_SUFFIX "-PRINTER" +#elif defined(ENABLE_DASH_SUPPORT) +#define DASH_SUFFIX "-DASH" +#else +#define DASH_SUFFIX "" +#endif + +#if defined(ENABLE_REALWOW_SUPPORT) +#define REALWOW_SUFFIX "-REALWOW" +#else +#define REALWOW_SUFFIX "" +#endif + +#if defined(ENABLE_PTP_SUPPORT) +#define PTP_SUFFIX "-PTP" +#else +#define PTP_SUFFIX "" +#endif + +#if defined(ENABLE_RSS_SUPPORT) +#define RSS_SUFFIX "-RSS" +#else +#define RSS_SUFFIX "" +#endif + +#define RTL8125_VERSION "9.006.04" NAPI_SUFFIX DASH_SUFFIX REALWOW_SUFFIX PTP_SUFFIX RSS_SUFFIX +#define MODULENAME "r8125" +#define PFX MODULENAME ": " + +#define GPL_CLAIM "\ +r8125 Copyright (C) 2021 Realtek NIC software team \n \ +This program comes with ABSOLUTELY NO WARRANTY; for details, please see . \n \ +This is free software, and you are welcome to redistribute it under certain conditions; see . \n" + +#ifdef RTL8125_DEBUG +#define assert(expr) \ + if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n", \ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) +#else +#define assert(expr) do {} while (0) +#define dprintk(fmt, args...) do {} while (0) +#endif /* RTL8125_DEBUG */ + +#define R8125_MSG_DEFAULT \ + (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) + +#ifdef CONFIG_R8125_NAPI +#define rtl8125_rx_hwaccel_skb vlan_hwaccel_receive_skb +#define rtl8125_rx_quota(count, quota) min(count, quota) +#else +#define rtl8125_rx_hwaccel_skb vlan_hwaccel_rx +#define rtl8125_rx_quota(count, quota) count +#endif + +/* MAC address length */ +#ifndef MAC_ADDR_LEN +#define MAC_ADDR_LEN 6 +#endif + +#ifndef MAC_PROTOCOL_LEN +#define MAC_PROTOCOL_LEN 2 +#endif + +#ifndef ETH_FCS_LEN +#define ETH_FCS_LEN 4 +#endif + +#ifndef NETIF_F_TSO6 +#define NETIF_F_TSO6 0 +#endif + +#define Reserved2_data 7 +#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ +#define TX_DMA_BURST_unlimited 7 +#define TX_DMA_BURST_1024 6 +#define TX_DMA_BURST_512 5 +#define TX_DMA_BURST_256 4 +#define TX_DMA_BURST_128 3 +#define TX_DMA_BURST_64 2 +#define TX_DMA_BURST_32 1 +#define TX_DMA_BURST_16 0 +#define Reserved1_data 0x3F +#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ +#define Jumbo_Frame_1k ETH_DATA_LEN +#define Jumbo_Frame_2k (2*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_3k (3*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_4k (4*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_5k (5*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_6k (6*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_7k (7*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_8k (8*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define Jumbo_Frame_9k (9*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) +#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ +#define RxEarly_off_V1 (0x07 << 11) +#define RxEarly_off_V2 (1 << 11) +#define Rx_Single_fetch_V2 (1 << 14) + +#define R8125_REGS_SIZE (256) +#define R8125_MAC_REGS_SIZE (256) +#define R8125_PHY_REGS_SIZE (16*2) +#define R8125_EPHY_REGS_SIZE (31*2) +#define R8125_ERI_REGS_SIZE (0x100) +#define R8125_REGS_DUMP_SIZE (0x400) +#define R8125_PCI_REGS_SIZE (0x100) +#define R8125_NAPI_WEIGHT 64 + +#define R8125_MAX_MSIX_VEC_8125B 32 +#define R8125_MIN_MSIX_VEC_8125B 17 +#define R8125_MAX_MSIX_VEC 32 +#define R8125_MAX_RX_QUEUES_VEC_V3 (16) + +#define RTL8125_TX_TIMEOUT (6 * HZ) +#define RTL8125_LINK_TIMEOUT (1 * HZ) +#define RTL8125_ESD_TIMEOUT (2 * HZ) + +#define NUM_TX_DESC 1024 /* Number of Tx descriptor registers */ +#define NUM_RX_DESC 1024 /* Number of Rx descriptor registers */ + +#define RX_BUF_SIZE 0x05F3 /* 0x05F3 = 1522bye + 1 */ +#define R8125_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) +#define R8125_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) +#define R8125_MAX_TX_QUEUES (2) +#define R8125_MAX_RX_QUEUES (4) +#define R8125_MAX_QUEUES R8125_MAX_RX_QUEUES + +#define OCP_STD_PHY_BASE 0xa400 + +#ifdef ENABLE_LIB_SUPPORT +#define R8125_MULTI_RX_Q(tp) 0 +#else +#define R8125_MULTI_RX_Q(tp) (tp->num_rx_rings > 1) +#endif + +#define NODE_ADDRESS_SIZE 6 + +#define SHORT_PACKET_PADDING_BUF_SIZE 256 + +#define RTK_MAGIC_DEBUG_VALUE 0x0badbeef + +/* write/read MMIO register */ +#define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg)) +#define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg)) +#define RTL_W32(tp, reg, val32) writel((val32), tp->mmio_addr + (reg)) +#define RTL_R8(tp, reg) readb(tp->mmio_addr + (reg)) +#define RTL_R16(tp, reg) readw(tp->mmio_addr + (reg)) +#define RTL_R32(tp, reg) ((unsigned long) readl(tp->mmio_addr + (reg))) + +#ifndef DMA_64BIT_MASK +#define DMA_64BIT_MASK 0xffffffffffffffffULL +#endif + +#ifndef DMA_32BIT_MASK +#define DMA_32BIT_MASK 0x00000000ffffffffULL +#endif + +#ifndef NETDEV_TX_OK +#define NETDEV_TX_OK 0 /* driver took care of packet */ +#endif + +#ifndef NETDEV_TX_BUSY +#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ +#endif + +#ifndef NETDEV_TX_LOCKED +#define NETDEV_TX_LOCKED -1t /* driver tx lock was already taken */ +#endif + +#ifndef ADVERTISED_Pause +#define ADVERTISED_Pause (1 << 13) +#endif + +#ifndef ADVERTISED_Asym_Pause +#define ADVERTISED_Asym_Pause (1 << 14) +#endif + +#ifndef ADVERTISE_PAUSE_CAP +#define ADVERTISE_PAUSE_CAP 0x400 +#endif + +#ifndef ADVERTISE_PAUSE_ASYM +#define ADVERTISE_PAUSE_ASYM 0x800 +#endif + +#ifndef MII_CTRL1000 +#define MII_CTRL1000 0x09 +#endif + +#ifndef ADVERTISE_1000FULL +#define ADVERTISE_1000FULL 0x200 +#endif + +#ifndef ADVERTISE_1000HALF +#define ADVERTISE_1000HALF 0x100 +#endif + +#ifndef ADVERTISED_2500baseX_Full +#define ADVERTISED_2500baseX_Full 0x8000 +#endif + +#define RTK_ADVERTISE_2500FULL 0x80 +#define RTK_LPA_ADVERTISE_2500FULL 0x20 +#define RTK_LPA_ADVERTISE_5000FULL 0x40 +#define RTK_LPA_ADVERTISE_10000FULL 0x800 + +/* Tx NO CLOSE */ +#define MAX_TX_NO_CLOSE_DESC_PTR_V2 0x10000 +#define TX_NO_CLOSE_SW_PTR_MASK_V2 0x1FFFF + +#ifndef ETH_MIN_MTU +#define ETH_MIN_MTU 68 +#endif + +#define D0_SPEED_UP_SPEED_DISABLE 0 +#define D0_SPEED_UP_SPEED_1000 1 +#define D0_SPEED_UP_SPEED_2500 2 + +#ifndef WRITE_ONCE +#define WRITE_ONCE(var, val) (*((volatile typeof(val) *)(&(var))) = (val)) +#endif +#ifndef READ_ONCE +#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) +#endif + +/*****************************************************************************/ + +//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) +#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ + (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ + ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) +/* copied from linux kernel 2.6.20 include/linux/netdev.h */ +#define NETDEV_ALIGN 32 +#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) + +static inline void *netdev_priv(struct net_device *dev) +{ + return (char *)dev + ((sizeof(struct net_device) + + NETDEV_ALIGN_CONST) + & ~NETDEV_ALIGN_CONST); +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) + +/*****************************************************************************/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +#define RTLDEV tp +#else +#define RTLDEV dev +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +/*****************************************************************************/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +typedef struct net_device *napi_ptr; +typedef int *napi_budget; + +#define napi dev +#define RTL_NAPI_CONFIG(ndev, priv, function, weig) ndev->poll=function; \ + ndev->weight=weig; +#define RTL_NAPI_QUOTA(budget, ndev) min(*budget, ndev->quota) +#define RTL_GET_PRIV(stuct_ptr, priv_struct) netdev_priv(stuct_ptr) +#define RTL_GET_NETDEV(priv_ptr) +#define RTL_RX_QUOTA(budget) *budget +#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) *budget -= work_done; \ + ndev->quota -= work_done; +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev) +#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev) +#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev) +#define RTL_NAPI_RETURN_VALUE work_done >= work_to_do +#define RTL_NAPI_ENABLE(dev, napi) netif_poll_enable(dev) +#define RTL_NAPI_DISABLE(dev, napi) netif_poll_disable(dev) +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) +#else +typedef struct napi_struct *napi_ptr; +typedef int napi_budget; + +#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) +#define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) +#define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) +#define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; +#define RTL_RX_QUOTA(budget) budget +#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev, napi) +#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev, napi) +#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev, napi) +#endif +#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,29) +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(napi) +#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(napi) +#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(napi) +#endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete_done(napi, work_done) +#else +#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete(napi) +#endif +#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) napi_schedule_prep(napi) +#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __napi_schedule(napi) +#endif +#define RTL_NAPI_RETURN_VALUE work_done +#define RTL_NAPI_ENABLE(dev, napi) napi_enable(napi) +#define RTL_NAPI_DISABLE(dev, napi) napi_disable(napi) +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +#define RTL_NAPI_DEL(priv) +#else +#define RTL_NAPI_DEL(priv) netif_napi_del(&priv->napi) +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + +/*****************************************************************************/ +#ifdef CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) napi_consume_skb(skb, budget) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); +#else +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) +#else //CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); +#else +#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); +#endif +#endif //CONFIG_R8125_NAPI + +/*****************************************************************************/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) +#ifdef __CHECKER__ +#define __iomem __attribute__((noderef, address_space(2))) +extern void __chk_io_ptr(void __iomem *); +#define __bitwise __attribute__((bitwise)) +#else +#define __iomem +#define __chk_io_ptr(x) (void)0 +#define __bitwise +#endif +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) + +/*****************************************************************************/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) +#ifdef __CHECKER__ +#define __force __attribute__((force)) +#else +#define __force +#endif +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) + +#ifndef module_param +#define module_param(v,t,p) MODULE_PARM(v, "i"); +#endif + +#ifndef PCI_DEVICE +#define PCI_DEVICE(vend,dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID +#endif + +/*****************************************************************************/ +/* 2.5.28 => 2.4.23 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) + +static inline void _kc_synchronize_irq(void) +{ + synchronize_irq(); +} +#undef synchronize_irq +#define synchronize_irq(X) _kc_synchronize_irq() + +#include +#define work_struct tq_struct +#undef INIT_WORK +#define INIT_WORK(a,b,c) INIT_TQUEUE(a,(void (*)(void *))b,c) +#undef container_of +#define container_of list_entry +#define schedule_work schedule_task +#define flush_scheduled_work flush_scheduled_tasks +#endif /* 2.5.28 => 2.4.17 */ + +/*****************************************************************************/ +/* 2.6.4 => 2.6.0 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) +#define MODULE_VERSION(_version) MODULE_INFO(version, _version) +#endif /* 2.6.4 => 2.6.0 */ +/*****************************************************************************/ +/* 2.6.0 => 2.5.28 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) +#define MODULE_INFO(version, _version) +#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT +#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 +#endif + +#define pci_set_consistent_dma_mask(dev,mask) 1 + +#undef dev_put +#define dev_put(dev) __dev_put(dev) + +#ifndef skb_fill_page_desc +#define skb_fill_page_desc _kc_skb_fill_page_desc +extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); +#endif + +#ifndef pci_dma_mapping_error +#define pci_dma_mapping_error _kc_pci_dma_mapping_error +static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) +{ + return dma_addr == 0; +} +#endif + +#undef ALIGN +#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) + +#endif /* 2.6.0 => 2.5.28 */ + +/*****************************************************************************/ +/* 2.4.22 => 2.4.17 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) +#define pci_name(x) ((x)->slot_name) +#endif /* 2.4.22 => 2.4.17 */ + +/*****************************************************************************/ +/* 2.6.5 => 2.6.0 */ +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) +#define pci_dma_sync_single_for_cpu pci_dma_sync_single +#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu +#endif /* 2.6.5 => 2.6.0 */ + +/*****************************************************************************/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +/* + * initialize a work-struct's func and data pointers: + */ +#define PREPARE_WORK(_work, _func, _data) \ + do { \ + (_work)->func = _func; \ + (_work)->data = _data; \ + } while (0) + +#endif +/*****************************************************************************/ +/* 2.6.4 => 2.6.0 */ +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) && \ + LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)) || \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4))) +#define ETHTOOL_OPS_COMPAT +#endif /* 2.6.4 => 2.6.0 */ + +/*****************************************************************************/ +/* Installations with ethtool version without eeprom, adapter id, or statistics + * support */ + +#ifndef ETH_GSTRING_LEN +#define ETH_GSTRING_LEN 32 +#endif + +#ifndef ETHTOOL_GSTATS +#define ETHTOOL_GSTATS 0x1d +#undef ethtool_drvinfo +#define ethtool_drvinfo k_ethtool_drvinfo +struct k_ethtool_drvinfo { + u32 cmd; + char driver[32]; + char version[32]; + char fw_version[32]; + char bus_info[32]; + char reserved1[32]; + char reserved2[16]; + u32 n_stats; + u32 testinfo_len; + u32 eedump_len; + u32 regdump_len; +}; + +struct ethtool_stats { + u32 cmd; + u32 n_stats; + u64 data[0]; +}; +#endif /* ETHTOOL_GSTATS */ + +#ifndef ETHTOOL_PHYS_ID +#define ETHTOOL_PHYS_ID 0x1c +#endif /* ETHTOOL_PHYS_ID */ + +#ifndef ETHTOOL_GSTRINGS +#define ETHTOOL_GSTRINGS 0x1b +enum ethtool_stringset { + ETH_SS_TEST = 0, + ETH_SS_STATS, +}; +struct ethtool_gstrings { + u32 cmd; /* ETHTOOL_GSTRINGS */ + u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ + u32 len; /* number of strings in the string set */ + u8 data[0]; +}; +#endif /* ETHTOOL_GSTRINGS */ + +#ifndef ETHTOOL_TEST +#define ETHTOOL_TEST 0x1a +enum ethtool_test_flags { + ETH_TEST_FL_OFFLINE = (1 << 0), + ETH_TEST_FL_FAILED = (1 << 1), +}; +struct ethtool_test { + u32 cmd; + u32 flags; + u32 reserved; + u32 len; + u64 data[0]; +}; +#endif /* ETHTOOL_TEST */ + +#ifndef ETHTOOL_GEEPROM +#define ETHTOOL_GEEPROM 0xb +#undef ETHTOOL_GREGS +struct ethtool_eeprom { + u32 cmd; + u32 magic; + u32 offset; + u32 len; + u8 data[0]; +}; + +struct ethtool_value { + u32 cmd; + u32 data; +}; +#endif /* ETHTOOL_GEEPROM */ + +#ifndef ETHTOOL_GLINK +#define ETHTOOL_GLINK 0xa +#endif /* ETHTOOL_GLINK */ + +#ifndef ETHTOOL_GREGS +#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ +#define ethtool_regs _kc_ethtool_regs +/* for passing big chunks of data */ +struct _kc_ethtool_regs { + u32 cmd; + u32 version; /* driver-specific, indicates different chips/revs */ + u32 len; /* bytes */ + u8 data[0]; +}; +#endif /* ETHTOOL_GREGS */ + +#ifndef ETHTOOL_GMSGLVL +#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ +#endif +#ifndef ETHTOOL_SMSGLVL +#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ +#endif +#ifndef ETHTOOL_NWAY_RST +#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ +#endif +#ifndef ETHTOOL_GLINK +#define ETHTOOL_GLINK 0x0000000a /* Get link status */ +#endif +#ifndef ETHTOOL_GEEPROM +#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ +#endif +#ifndef ETHTOOL_SEEPROM +#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ +#endif +#ifndef ETHTOOL_GCOALESCE +#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ +/* for configuring coalescing parameters of chip */ +#define ethtool_coalesce _kc_ethtool_coalesce +struct _kc_ethtool_coalesce { + u32 cmd; /* ETHTOOL_{G,S}COALESCE */ + + /* How many usecs to delay an RX interrupt after + * a packet arrives. If 0, only rx_max_coalesced_frames + * is used. + */ + u32 rx_coalesce_usecs; + + /* How many packets to delay an RX interrupt after + * a packet arrives. If 0, only rx_coalesce_usecs is + * used. It is illegal to set both usecs and max frames + * to zero as this would cause RX interrupts to never be + * generated. + */ + u32 rx_max_coalesced_frames; + + /* Same as above two parameters, except that these values + * apply while an IRQ is being serviced by the host. Not + * all cards support this feature and the values are ignored + * in that case. + */ + u32 rx_coalesce_usecs_irq; + u32 rx_max_coalesced_frames_irq; + + /* How many usecs to delay a TX interrupt after + * a packet is sent. If 0, only tx_max_coalesced_frames + * is used. + */ + u32 tx_coalesce_usecs; + + /* How many packets to delay a TX interrupt after + * a packet is sent. If 0, only tx_coalesce_usecs is + * used. It is illegal to set both usecs and max frames + * to zero as this would cause TX interrupts to never be + * generated. + */ + u32 tx_max_coalesced_frames; + + /* Same as above two parameters, except that these values + * apply while an IRQ is being serviced by the host. Not + * all cards support this feature and the values are ignored + * in that case. + */ + u32 tx_coalesce_usecs_irq; + u32 tx_max_coalesced_frames_irq; + + /* How many usecs to delay in-memory statistics + * block updates. Some drivers do not have an in-memory + * statistic block, and in such cases this value is ignored. + * This value must not be zero. + */ + u32 stats_block_coalesce_usecs; + + /* Adaptive RX/TX coalescing is an algorithm implemented by + * some drivers to improve latency under low packet rates and + * improve throughput under high packet rates. Some drivers + * only implement one of RX or TX adaptive coalescing. Anything + * not implemented by the driver causes these values to be + * silently ignored. + */ + u32 use_adaptive_rx_coalesce; + u32 use_adaptive_tx_coalesce; + + /* When the packet rate (measured in packets per second) + * is below pkt_rate_low, the {rx,tx}_*_low parameters are + * used. + */ + u32 pkt_rate_low; + u32 rx_coalesce_usecs_low; + u32 rx_max_coalesced_frames_low; + u32 tx_coalesce_usecs_low; + u32 tx_max_coalesced_frames_low; + + /* When the packet rate is below pkt_rate_high but above + * pkt_rate_low (both measured in packets per second) the + * normal {rx,tx}_* coalescing parameters are used. + */ + + /* When the packet rate is (measured in packets per second) + * is above pkt_rate_high, the {rx,tx}_*_high parameters are + * used. + */ + u32 pkt_rate_high; + u32 rx_coalesce_usecs_high; + u32 rx_max_coalesced_frames_high; + u32 tx_coalesce_usecs_high; + u32 tx_max_coalesced_frames_high; + + /* How often to do adaptive coalescing packet rate sampling, + * measured in seconds. Must not be zero. + */ + u32 rate_sample_interval; +}; +#endif /* ETHTOOL_GCOALESCE */ + +#ifndef ETHTOOL_SCOALESCE +#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ +#endif +#ifndef ETHTOOL_GRINGPARAM +#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ +/* for configuring RX/TX ring parameters */ +#define ethtool_ringparam _kc_ethtool_ringparam +struct _kc_ethtool_ringparam { + u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ + + /* Read only attributes. These indicate the maximum number + * of pending RX/TX ring entries the driver will allow the + * user to set. + */ + u32 rx_max_pending; + u32 rx_mini_max_pending; + u32 rx_jumbo_max_pending; + u32 tx_max_pending; + + /* Values changeable by the user. The valid values are + * in the range 1 to the "*_max_pending" counterpart above. + */ + u32 rx_pending; + u32 rx_mini_pending; + u32 rx_jumbo_pending; + u32 tx_pending; +}; +#endif /* ETHTOOL_GRINGPARAM */ + +#ifndef ETHTOOL_SRINGPARAM +#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ +#endif +#ifndef ETHTOOL_GPAUSEPARAM +#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ +/* for configuring link flow control parameters */ +#define ethtool_pauseparam _kc_ethtool_pauseparam +struct _kc_ethtool_pauseparam { + u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ + + /* If the link is being auto-negotiated (via ethtool_cmd.autoneg + * being true) the user may set 'autonet' here non-zero to have the + * pause parameters be auto-negotiated too. In such a case, the + * {rx,tx}_pause values below determine what capabilities are + * advertised. + * + * If 'autoneg' is zero or the link is not being auto-negotiated, + * then {rx,tx}_pause force the driver to use/not-use pause + * flow control. + */ + u32 autoneg; + u32 rx_pause; + u32 tx_pause; +}; +#endif /* ETHTOOL_GPAUSEPARAM */ + +#ifndef ETHTOOL_SPAUSEPARAM +#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ +#endif +#ifndef ETHTOOL_GRXCSUM +#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_SRXCSUM +#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_GTXCSUM +#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_STXCSUM +#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_GSG +#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable +* (ethtool_value) */ +#endif +#ifndef ETHTOOL_SSG +#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable +* (ethtool_value). */ +#endif +#ifndef ETHTOOL_TEST +#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ +#endif +#ifndef ETHTOOL_GSTRINGS +#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ +#endif +#ifndef ETHTOOL_PHYS_ID +#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ +#endif +#ifndef ETHTOOL_GSTATS +#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ +#endif +#ifndef ETHTOOL_GTSO +#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ +#endif +#ifndef ETHTOOL_STSO +#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ +#endif + +#ifndef ETHTOOL_BUSINFO_LEN +#define ETHTOOL_BUSINFO_LEN 32 +#endif + +/*****************************************************************************/ + +enum RTL8125_registers { + MAC0 = 0x00, /* Ethernet hardware address. */ + MAC4 = 0x04, + MAR0 = 0x08, /* Multicast filter. */ + CounterAddrLow = 0x10, + CounterAddrHigh = 0x14, + CustomLED = 0x18, + TxDescStartAddrLow = 0x20, + TxDescStartAddrHigh = 0x24, + TxHDescStartAddrLow = 0x28, + TxHDescStartAddrHigh = 0x2c, + FLASH = 0x30, + INT_CFG0_8125 = 0x34, + ERSR = 0x36, + ChipCmd = 0x37, + TxPoll = 0x38, + IntrMask = 0x3C, + IntrStatus = 0x3E, + TxConfig = 0x40, + RxConfig = 0x44, + TCTR = 0x48, + Cfg9346 = 0x50, + Config0 = 0x51, + Config1 = 0x52, + Config2 = 0x53, + Config3 = 0x54, + Config4 = 0x55, + Config5 = 0x56, + TDFNR = 0x57, + TimeInt0 = 0x58, + TimeInt1 = 0x5C, + PHYAR = 0x60, + CSIDR = 0x64, + CSIAR = 0x68, + PHYstatus = 0x6C, + MACDBG = 0x6D, + GPIO = 0x6E, + PMCH = 0x6F, + ERIDR = 0x70, + ERIAR = 0x74, + INT_CFG1_8125 = 0x7A, + EPHY_RXER_NUM = 0x7C, + EPHYAR = 0x80, + TimeInt2 = 0x8C, + OCPDR = 0xB0, + MACOCP = 0xB0, + OCPAR = 0xB4, + SecMAC0 = 0xB4, + SecMAC4 = 0xB8, + PHYOCP = 0xB8, + DBG_reg = 0xD1, + TwiCmdReg = 0xD2, + MCUCmd_reg = 0xD3, + RxMaxSize = 0xDA, + EFUSEAR = 0xDC, + CPlusCmd = 0xE0, + IntrMitigate = 0xE2, + RxDescAddrLow = 0xE4, + RxDescAddrHigh = 0xE8, + MTPS = 0xEC, + FuncEvent = 0xF0, + PPSW = 0xF2, + FuncEventMask = 0xF4, + TimeInt3 = 0xF4, + FuncPresetState = 0xF8, + CMAC_IBCR0 = 0xF8, + CMAC_IBCR2 = 0xF9, + CMAC_IBIMR0 = 0xFA, + CMAC_IBISR0 = 0xFB, + FuncForceEvent = 0xFC, + //8125 + IMR0_8125 = 0x38, + ISR0_8125 = 0x3C, + TPPOLL_8125 = 0x90, + IMR1_8125 = 0x800, + ISR1_8125 = 0x802, + IMR2_8125 = 0x804, + ISR2_8125 = 0x806, + IMR3_8125 = 0x808, + ISR3_8125 = 0x80A, + BACKUP_ADDR0_8125 = 0x19E0, + BACKUP_ADDR1_8125 = 0X19E4, + TCTR0_8125 = 0x0048, + TCTR1_8125 = 0x004C, + TCTR2_8125 = 0x0088, + TCTR3_8125 = 0x001C, + TIMER_INT0_8125 = 0x0058, + TIMER_INT1_8125 = 0x005C, + TIMER_INT2_8125 = 0x008C, + TIMER_INT3_8125 = 0x00F4, + INT_MITI_V2_0_RX = 0x0A00, + INT_MITI_V2_0_TX = 0x0A02, + INT_MITI_V2_1_RX = 0x0A08, + INT_MITI_V2_1_TX = 0x0A0A, + IMR_V2_CLEAR_REG_8125 = 0x0D00, + ISR_V2_8125 = 0x0D04, + IMR_V2_SET_REG_8125 = 0x0D0C, + TDU_STA_8125 = 0x0D08, + RDU_STA_8125 = 0x0D0A, + TX_NEW_CTRL = 0x203E, + TNPDS_Q1_LOW_8125 = 0x2100, + PLA_TXQ0_IDLE_CREDIT = 0x2500, + PLA_TXQ1_IDLE_CREDIT = 0x2504, + SW_TAIL_PTR0_8125 = 0x2800, + HW_CLO_PTR0_8125 = 0x2802, + RDSAR_Q1_LOW_8125 = 0x4000, + RSS_CTRL_8125 = 0x4500, + Q_NUM_CTRL_8125 = 0x4800, + RSS_KEY_8125 = 0x4600, + RSS_INDIRECTION_TBL_8125_V2 = 0x4700, + EEE_TXIDLE_TIMER_8125 = 0x6048, + PTP_CTRL_8125 = 0x6800, + PTP_STATUS_8125 = 0x6802, + PTP_ISR_8125 = 0x6804, + PTP_IMR_8125 = 0x6805, + PTP_TIME_CORRECT_CMD_8125 = 0x6806, + PTP_SOFT_CONFIG_Time_NS_8125 = 0x6808, + PTP_SOFT_CONFIG_Time_S_8125 = 0x680C, + PTP_LOCAL_Time_SUB_NS_8125 = 0x6814, + PTP_LOCAL_Time_NS_8125 = 0x6818, + PTP_LOCAL_Time_S_8125 = 0x681C, + PTP_Time_SHIFTER_S_8125 = 0x6856, + PPS_RISE_TIME_NS_8125 = 0x68A0, + PPS_RISE_TIME_S_8125 = 0x68A4, +}; + +enum RTL8125_register_content { + /* InterruptStatusBits */ + SYSErr = 0x8000, + PCSTimeout = 0x4000, + SWInt = 0x0100, + TxDescUnavail = 0x0080, + RxFIFOOver = 0x0040, + LinkChg = 0x0020, + RxDescUnavail = 0x0010, + TxErr = 0x0008, + TxOK = 0x0004, + RxErr = 0x0002, + RxOK = 0x0001, + RxDU1 = 0x0002, + RxOK1 = 0x0001, + + /* RxStatusDesc */ + RxRWT = (1 << 22), + RxRES = (1 << 21), + RxRUNT = (1 << 20), + RxCRC = (1 << 19), + + RxRWT_V3 = (1 << 18), + RxRES_V3 = (1 << 20), + RxRUNT_V3 = (1 << 19), + RxCRC_V3 = (1 << 17), + + /* ChipCmdBits */ + StopReq = 0x80, + CmdReset = 0x10, + CmdRxEnb = 0x08, + CmdTxEnb = 0x04, + RxBufEmpty = 0x01, + + /* Cfg9346Bits */ + Cfg9346_Lock = 0x00, + Cfg9346_Unlock = 0xC0, + Cfg9346_EEDO = (1 << 0), + Cfg9346_EEDI = (1 << 1), + Cfg9346_EESK = (1 << 2), + Cfg9346_EECS = (1 << 3), + Cfg9346_EEM0 = (1 << 6), + Cfg9346_EEM1 = (1 << 7), + + /* rx_mode_bits */ + AcceptErr = 0x20, + AcceptRunt = 0x10, + AcceptBroadcast = 0x08, + AcceptMulticast = 0x04, + AcceptMyPhys = 0x02, + AcceptAllPhys = 0x01, + + /* Transmit Priority Polling*/ + HPQ = 0x80, + NPQ = 0x40, + FSWInt = 0x01, + + /* RxConfigBits */ + Reserved2_shift = 13, + RxCfgDMAShift = 8, + EnableRxDescV3 = (1 << 24), + EnableOuterVlan = (1 << 23), + EnableInnerVlan = (1 << 22), + RxCfg_128_int_en = (1 << 15), + RxCfg_fet_multi_en = (1 << 14), + RxCfg_half_refetch = (1 << 13), + RxCfg_pause_slot_en = (1 << 11), + RxCfg_9356SEL = (1 << 6), + + /* TxConfigBits */ + TxInterFrameGapShift = 24, + TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ + TxMACLoopBack = (1 << 17), /* MAC loopback */ + + /* Config1 register */ + LEDS1 = (1 << 7), + LEDS0 = (1 << 6), + Speed_down = (1 << 4), + MEMMAP = (1 << 3), + IOMAP = (1 << 2), + VPD = (1 << 1), + PMEnable = (1 << 0), /* Power Management Enable */ + + /* Config2 register */ + PMSTS_En = (1 << 5), + + /* Config3 register */ + Isolate_en = (1 << 12), /* Isolate enable */ + MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ + LinkUp = (1 << 4), /* This bit is reserved in RTL8125B.*/ + /* Wake up when the cable connection is re-established */ + ECRCEN = (1 << 3), /* This bit is reserved in RTL8125B*/ + Jumbo_En0 = (1 << 2), /* This bit is reserved in RTL8125B*/ + RDY_TO_L23 = (1 << 1), /* This bit is reserved in RTL8125B*/ + Beacon_en = (1 << 0), /* This bit is reserved in RTL8125B*/ + + /* Config4 register */ + Jumbo_En1 = (1 << 1), /* This bit is reserved in RTL8125B*/ + + /* Config5 register */ + BWF = (1 << 6), /* Accept Broadcast wakeup frame */ + MWF = (1 << 5), /* Accept Multicast wakeup frame */ + UWF = (1 << 4), /* Accept Unicast wakeup frame */ + LanWake = (1 << 1), /* LanWake enable/disable */ + PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ + + /* CPlusCmd */ + EnableBist = (1 << 15), + Macdbgo_oe = (1 << 14), + Normal_mode = (1 << 13), + Force_halfdup = (1 << 12), + Force_rxflow_en = (1 << 11), + Force_txflow_en = (1 << 10), + Cxpl_dbg_sel = (1 << 9),//This bit is reserved in RTL8125B + ASF = (1 << 8),//This bit is reserved in RTL8125C + PktCntrDisable = (1 << 7), + RxVlan = (1 << 6), + RxChkSum = (1 << 5), + Macdbgo_sel = 0x001C, + INTT_0 = 0x0000, + INTT_1 = 0x0001, + INTT_2 = 0x0002, + INTT_3 = 0x0003, + + /* rtl8125_PHYstatus */ + PowerSaveStatus = 0x80, + _2500bpsF = 0x400, + TxFlowCtrl = 0x40, + RxFlowCtrl = 0x20, + _1000bpsF = 0x10, + _100bps = 0x08, + _10bps = 0x04, + LinkStatus = 0x02, + FullDup = 0x01, + + /* DBG_reg */ + Fix_Nak_1 = (1 << 4), + Fix_Nak_2 = (1 << 3), + DBGPIN_E2 = (1 << 0), + + /* ResetCounterCommand */ + CounterReset = 0x1, + /* DumpCounterCommand */ + CounterDump = 0x8, + + /* PHY access */ + PHYAR_Flag = 0x80000000, + PHYAR_Write = 0x80000000, + PHYAR_Read = 0x00000000, + PHYAR_Reg_Mask = 0x1f, + PHYAR_Reg_shift = 16, + PHYAR_Data_Mask = 0xffff, + + /* EPHY access */ + EPHYAR_Flag = 0x80000000, + EPHYAR_Write = 0x80000000, + EPHYAR_Read = 0x00000000, + EPHYAR_Reg_Mask = 0x3f, + EPHYAR_Reg_Mask_v2 = 0x7f, + EPHYAR_Reg_shift = 16, + EPHYAR_Data_Mask = 0xffff, + + /* CSI access */ + CSIAR_Flag = 0x80000000, + CSIAR_Write = 0x80000000, + CSIAR_Read = 0x00000000, + CSIAR_ByteEn = 0x0f, + CSIAR_ByteEn_shift = 12, + CSIAR_Addr_Mask = 0x0fff, + + /* ERI access */ + ERIAR_Flag = 0x80000000, + ERIAR_Write = 0x80000000, + ERIAR_Read = 0x00000000, + ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment */ + ERIAR_ExGMAC = 0, + ERIAR_MSIX = 1, + ERIAR_ASF = 2, + ERIAR_OOB = 2, + ERIAR_Type_shift = 16, + ERIAR_ByteEn = 0x0f, + ERIAR_ByteEn_shift = 12, + + /* OCP GPHY access */ + OCPDR_Write = 0x80000000, + OCPDR_Read = 0x00000000, + OCPDR_Reg_Mask = 0xFF, + OCPDR_Data_Mask = 0xFFFF, + OCPDR_GPHY_Reg_shift = 16, + OCPAR_Flag = 0x80000000, + OCPAR_GPHY_Write = 0x8000F060, + OCPAR_GPHY_Read = 0x0000F060, + OCPR_Write = 0x80000000, + OCPR_Read = 0x00000000, + OCPR_Addr_Reg_shift = 16, + OCPR_Flag = 0x80000000, + OCP_STD_PHY_BASE_PAGE = 0x0A40, + + /* MCU Command */ + Now_is_oob = (1 << 7), + Txfifo_empty = (1 << 5), + Rxfifo_empty = (1 << 4), + + /* E-FUSE access */ + EFUSE_WRITE = 0x80000000, + EFUSE_WRITE_OK = 0x00000000, + EFUSE_READ = 0x00000000, + EFUSE_READ_OK = 0x80000000, + EFUSE_WRITE_V3 = 0x40000000, + EFUSE_WRITE_OK_V3 = 0x00000000, + EFUSE_READ_V3 = 0x80000000, + EFUSE_READ_OK_V3 = 0x00000000, + EFUSE_Reg_Mask = 0x03FF, + EFUSE_Reg_Shift = 8, + EFUSE_Check_Cnt = 300, + EFUSE_READ_FAIL = 0xFF, + EFUSE_Data_Mask = 0x000000FF, + + /* GPIO */ + GPIO_en = (1 << 0), + + /* PTP */ + PTP_ISR_TOK = (1 << 1), + PTP_ISR_TER = (1 << 2), + PTP_EXEC_CMD = (1 << 7), + PTP_ADJUST_TIME_NS_NEGATIVE = (1 << 30), + PTP_ADJUST_TIME_S_NEGATIVE = (1ULL << 48), + + /* New Interrupt Bits */ + INT_CFG0_ENABLE_8125 = (1 << 0), + INT_CFG0_TIMEOUT0_BYPASS_8125 = (1 << 1), + INT_CFG0_MITIGATION_BYPASS_8125 = (1 << 2), + ISRIMR_V2_ROK_Q0 = (1 << 0), + ISRIMR_TOK_Q0 = (1 << 16), + ISRIMR_TOK_Q1 = (1 << 18), + ISRIMR_V2_LINKCHG = (1 << 21), + + /* Magic Number */ + RTL8125_MAGIC_NUMBER = 0x0badbadbadbadbadull, +}; + +enum _DescStatusBit { + DescOwn = (1 << 31), /* Descriptor is owned by NIC */ + RingEnd = (1 << 30), /* End of descriptor ring */ + FirstFrag = (1 << 29), /* First segment of a packet */ + LastFrag = (1 << 28), /* Final segment of a packet */ + + DescOwn_V3 = (DescOwn), /* Descriptor is owned by NIC */ + RingEnd_V3 = (RingEnd), /* End of descriptor ring */ + FirstFrag_V3 = (1 << 25), /* First segment of a packet */ + LastFrag_V3 = (1 << 24), /* Final segment of a packet */ + + /* Tx private */ + /*------ offset 0 of tx descriptor ------*/ + LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ + GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */ + GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */ + LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */ + MSSShift = 16, /* MSS value position */ + MSSMask = 0x7FFU, /* MSS value 11 bits */ + TxIPCS = (1 << 18), /* Calculate IP checksum */ + TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */ + TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */ + TxVlanTag = (1 << 17), /* Add VLAN tag */ + + /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only begin @@@@@@*/ + TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */ + TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */ + TxIPCS_C = (1 << 29), /* Calculate IP checksum */ + TxIPV6F_C = (1 << 28), /* Indicate it is an IPv6 packet */ + /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only end @@@@@@*/ + + + /* Rx private */ + /*------ offset 0 of rx descriptor ------*/ + PID1 = (1 << 18), /* Protocol ID bit 1/2 */ + PID0 = (1 << 17), /* Protocol ID bit 2/2 */ + +#define RxProtoUDP (PID1) +#define RxProtoTCP (PID0) +#define RxProtoIP (PID1 | PID0) +#define RxProtoMask RxProtoIP + + RxIPF = (1 << 16), /* IP checksum failed */ + RxUDPF = (1 << 15), /* UDP/IP checksum failed */ + RxTCPF = (1 << 14), /* TCP/IP checksum failed */ + RxVlanTag = (1 << 16), /* VLAN tag available */ + + /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ + RxUDPT = (1 << 18), + RxTCPT = (1 << 17), + /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ + + /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ + RxV6F = (1 << 31), + RxV4F = (1 << 30), + /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ + + + PID1_v3 = (1 << 29), /* Protocol ID bit 1/2 */ + PID0_v3 = (1 << 28), /* Protocol ID bit 2/2 */ + +#define RxProtoUDP_v3 (PID1_v3) +#define RxProtoTCP_v3 (PID0_v3) +#define RxProtoIP_v3 (PID1_v3 | PID0_v3) +#define RxProtoMask_v3 RxProtoIP_v3 + + RxIPF_v3 = (1 << 26), /* IP checksum failed */ + RxUDPF_v3 = (1 << 25), /* UDP/IP checksum failed */ + RxTCPF_v3 = (1 << 24), /* TCP/IP checksum failed */ + RxSCTPF_v3 = (1 << 23), /* TCP/IP checksum failed */ + RxVlanTag_v3 = (RxVlanTag), /* VLAN tag available */ + + /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ + RxUDPT_v3 = (1 << 29), + RxTCPT_v3 = (1 << 28), + RxSCTP_v3 = (1 << 27), + /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ + + /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ + RxV6F_v3 = (RxV6F), + RxV4F_v3 = (RxV4F), + /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ +}; + +enum features { +// RTL_FEATURE_WOL = (1 << 0), + RTL_FEATURE_MSI = (1 << 1), + RTL_FEATURE_MSIX = (1 << 2), +}; + +enum wol_capability { + WOL_DISABLED = 0, + WOL_ENABLED = 1 +}; + +enum bits { + BIT_0 = (1 << 0), + BIT_1 = (1 << 1), + BIT_2 = (1 << 2), + BIT_3 = (1 << 3), + BIT_4 = (1 << 4), + BIT_5 = (1 << 5), + BIT_6 = (1 << 6), + BIT_7 = (1 << 7), + BIT_8 = (1 << 8), + BIT_9 = (1 << 9), + BIT_10 = (1 << 10), + BIT_11 = (1 << 11), + BIT_12 = (1 << 12), + BIT_13 = (1 << 13), + BIT_14 = (1 << 14), + BIT_15 = (1 << 15), + BIT_16 = (1 << 16), + BIT_17 = (1 << 17), + BIT_18 = (1 << 18), + BIT_19 = (1 << 19), + BIT_20 = (1 << 20), + BIT_21 = (1 << 21), + BIT_22 = (1 << 22), + BIT_23 = (1 << 23), + BIT_24 = (1 << 24), + BIT_25 = (1 << 25), + BIT_26 = (1 << 26), + BIT_27 = (1 << 27), + BIT_28 = (1 << 28), + BIT_29 = (1 << 29), + BIT_30 = (1 << 30), + BIT_31 = (1 << 31) +}; + +enum effuse { + EFUSE_NOT_SUPPORT = 0, + EFUSE_SUPPORT_V1, + EFUSE_SUPPORT_V2, + EFUSE_SUPPORT_V3, + EFUSE_SUPPORT_V4, +}; +#define RsvdMask 0x3fffc000 +#define RsvdMaskV3 0x3fff8000 + +struct TxDesc { + u32 opts1; + u32 opts2; + u64 addr; + u32 reserved0; + u32 reserved1; + u32 reserved2; + u32 reserved3; +}; + +struct RxDesc { + u32 opts1; + u32 opts2; + u64 addr; +}; + +struct RxDescV3 { + union { + struct { + u32 rsv1; + u32 rsv2; + } RxDescDDWord1; + }; + + union { + struct { + u32 RSSResult; + u16 HeaderBufferLen; + u16 HeaderInfo; + } RxDescNormalDDWord2; + + struct { + u32 rsv5; + u32 rsv6; + } RxDescDDWord2; + }; + + union { + u64 addr; + + struct { + u32 TimeStampLow; + u32 TimeStampHigh; + } RxDescTimeStamp; + + struct { + u32 rsv8; + u32 rsv9; + } RxDescDDWord3; + }; + + union { + struct { + u32 opts2; + u32 opts1; + } RxDescNormalDDWord4; + + struct { + u16 TimeStampHHigh; + u16 rsv11; + u32 opts1; + } RxDescPTPDDWord4; + }; +}; + +enum rxdesc_type { + RXDESC_TYPE_NORMAL=0, + RXDESC_TYPE_NEXT, + RXDESC_TYPE_PTP, + RXDESC_TYPE_MAX +}; + +//Rx Desc Type +enum rx_desc_ring_type { + RX_DESC_RING_TYPE_UNKNOWN=0, + RX_DESC_RING_TYPE_1, + RX_DESC_RING_TYPE_2, + RX_DESC_RING_TYPE_3, + RX_DESC_RING_TYPE_MAX +}; + +enum rx_desc_len { + RX_DESC_LEN_TYPE_1 = (sizeof(struct RxDesc)), + RX_DESC_LEN_TYPE_3 = (sizeof(struct RxDescV3)) +}; + +struct ring_info { + struct sk_buff *skb; + u32 len; + u8 __pad[sizeof(void *) - sizeof(u32)]; +}; + +struct pci_resource { + u8 cmd; + u8 cls; + u16 io_base_h; + u16 io_base_l; + u16 mem_base_h; + u16 mem_base_l; + u8 ilr; + u16 resv_0x1c_h; + u16 resv_0x1c_l; + u16 resv_0x20_h; + u16 resv_0x20_l; + u16 resv_0x24_h; + u16 resv_0x24_l; + u16 resv_0x2c_h; + u16 resv_0x2c_l; + u32 pci_sn_l; + u32 pci_sn_h; +}; + +enum r8125_flag { + R8125_FLAG_DOWN = 0, + R8125_FLAG_TASK_RESET_PENDING, + R8125_FLAG_TASK_ESD_CHECK_PENDING, + R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, + R8125_FLAG_MAX +}; + +struct rtl8125_tx_ring { + void* priv; + u32 index; + u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ + u32 dirty_tx; + struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ + dma_addr_t TxPhyAddr; + struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ + + u32 NextHwDesCloPtr; + u32 BeginHwDesCloPtr; + + u16 hw_clo_ptr_reg; + u16 sw_tail_ptr_reg; + + u16 tdsar_reg; /* Transmit Descriptor Start Address */ +}; + +struct rtl8125_rx_ring { + void* priv; + u32 index; + u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ + u32 dirty_rx; + struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ + u64 RxDescPhyAddr[NUM_RX_DESC]; /* Rx desc physical address*/ + dma_addr_t RxPhyAddr; + struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ + + u16 rdsar_reg; /* Receive Descriptor Start Address */ +}; + +struct r8125_napi { +#ifdef CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) + struct napi_struct napi; +#endif +#endif + void* priv; + int index; +}; + +struct r8125_irq { + irq_handler_t handler; + unsigned int vector; + u8 requested; + char name[IFNAMSIZ + 10]; +}; + +#pragma pack(1) +struct rtl8125_regs { + //00 + u8 mac_id[6]; + u16 reg_06; + u8 mar[8]; + //10 + u64 dtccr; + u16 ledsel0; + u16 legreg; + u32 tctr3; + //20 + u32 txq0_dsc_st_addr_0; + u32 txq0_dsc_st_addr_2; + u64 reg_28; + //30 + u16 rit; + u16 ritc; + u16 reg_34; + u8 reg_36; + u8 command; + u32 imr0; + u32 isr0; + //40 + u32 tcr; + u32 rcr; + u32 tctr0; + u32 tctr1; + //50 + u8 cr93c46; + u8 config0; + u8 config1; + u8 config2; + u8 config3; + u8 config4; + u8 config5; + u8 tdfnr; + u32 timer_int0; + u32 timer_int1; + //60 + u32 gphy_mdcmdio; + u32 csidr; + u32 csiar; + u16 phy_status; + u8 config6; + u8 pmch; + //70 + u32 eridr; + u32 eriar; + u16 config7; + u16 reg_7a; + u32 ephy_rxerr_cnt; + //80 + u32 ephy_mdcmdio; + u16 ledsel2; + u16 ledsel1; + u32 tctr2; + u32 timer_int2; + //90 + u8 tppoll0; + u8 reg_91; + u16 reg_92; + u16 led_feature; + u16 ledsel3; + u16 eee_led_config; + u16 reg_9a; + u32 reg_9c; + //a0 + u32 reg_a0; + u32 reg_a4; + u32 reg_a8; + u32 reg_ac; + //b0 + u32 patch_dbg; + u32 reg_b4; + u32 gphy_ocp; + u32 reg_bc; + //c0 + u32 reg_c0; + u32 reg_c4; + u32 reg_c8; + u16 otp_cmd; + u16 otp_pg_config; + //d0 + u16 phy_pwr; + u8 twsi_ctrl; + u8 oob_ctrl; + u16 mac_dbgo; + u16 mac_dbg; + u16 reg_d8; + u16 rms; + u32 efuse_data; + //e0 + u16 cplus_cmd; + u16 reg_e2; + u32 rxq0_dsc_st_addr_0; + u32 rxq0_dsc_st_addr_2; + u16 reg_ec; + u16 tx10midle_cnt; + //f0 + u16 misc0; + u16 misc1; + u32 timer_int3; + u32 cmac_ib; + u16 reg_fc; + u16 sw_rst; +}; +#pragma pack() + +struct rtl8125_regs_save { + union { + u8 mac_io[R8125_MAC_REGS_SIZE]; + + struct rtl8125_regs mac_reg; + }; + u16 pcie_phy[R8125_EPHY_REGS_SIZE/2]; + u16 eth_phy[R8125_PHY_REGS_SIZE/2]; + u32 eri_reg[R8125_ERI_REGS_SIZE/4]; + u32 pci_reg[R8125_PCI_REGS_SIZE/4]; + u16 sw_tail_ptr_reg[R8125_MAX_TX_QUEUES]; + u16 hw_clo_ptr_reg[R8125_MAX_TX_QUEUES]; + + //ktime_t begin_ktime; + //ktime_t end_ktime; + //u64 duration_ns; + + u16 sw0_tail_ptr; + u16 next_hwq0_clo_ptr; + u16 sw1_tail_ptr; + u16 next_hwq1_clo_ptr; + + u16 int_miti_rxq0; + u16 int_miti_txq0; + u16 int_miti_rxq1; + u16 int_miti_txq1; + u8 int_config; + u32 imr_new; + u32 isr_new; + + u8 tdu_status; + u16 rdu_status; + + u16 tc_mode; + + u32 txq1_dsc_st_addr_0; + u32 txq1_dsc_st_addr_2; + + u32 pla_tx_q0_idle_credit; + u32 pla_tx_q1_idle_credit; + + u32 rxq1_dsc_st_addr_0; + u32 rxq1_dsc_st_addr_2; + + u32 rss_ctrl; + u8 rss_key[RTL8125_RSS_KEY_SIZE]; + u8 rss_i_table[RTL8125_MAX_INDIRECTION_TABLE_ENTRIES]; + u16 rss_queue_num_sel_r; +}; + +struct rtl8125_counters { + /* legacy */ + u64 tx_packets; + u64 rx_packets; + u64 tx_errors; + u32 rx_errors; + u16 rx_missed; + u16 align_errors; + u32 tx_one_collision; + u32 tx_multi_collision; + u64 rx_unicast; + u64 rx_broadcast; + u32 rx_multicast; + u16 tx_aborted; + u16 tx_underrun; + + /* extended */ + u64 tx_octets; + u64 rx_octets; + u64 rx_multicast64; + u64 tx_unicast64; + u64 tx_broadcast64; + u64 tx_multicast64; + u32 tx_pause_on; + u32 tx_pause_off; + u32 tx_pause_all; + u32 tx_deferred; + u32 tx_late_collision; + u32 tx_all_collision; + u32 tx_aborted32; + u32 align_errors32; + u32 rx_frame_too_long; + u32 rx_runt; + u32 rx_pause_on; + u32 rx_pause_off; + u32 rx_pause_all; + u32 rx_unknown_opcode; + u32 rx_mac_error; + u32 tx_underrun32; + u32 rx_mac_missed; + u32 rx_tcam_dropped; + u32 tdu; + u32 rdu; +}; + +/* Flow Control Settings */ +enum rtl8125_fc_mode { + rtl8125_fc_none = 0, + rtl8125_fc_rx_pause, + rtl8125_fc_tx_pause, + rtl8125_fc_full, + rtl8125_fc_default +}; + +struct rtl8125_private { + void __iomem *mmio_addr; /* memory map physical address */ + struct pci_dev *pci_dev; /* Index of PCI device */ + struct net_device *dev; + struct r8125_napi r8125napi[R8125_MAX_MSIX_VEC]; + struct r8125_irq irq_tbl[R8125_MAX_MSIX_VEC]; + unsigned int irq_nvecs; + unsigned int max_irq_nvecs; + unsigned int min_irq_nvecs; + //struct msix_entry msix_entries[R8125_MAX_MSIX_VEC]; + struct net_device_stats stats; /* statistics of net device */ + spinlock_t lock; /* spin lock flag */ + u32 msg_enable; + u32 tx_tcp_csum_cmd; + u32 tx_udp_csum_cmd; + u32 tx_ip_csum_cmd; + u32 tx_ipv6_csum_cmd; + int max_jumbo_frame_size; + int chipset; + u32 mcfg; + //u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ + //u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ + //u32 dirty_rx; + //u32 dirty_tx; + //struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ + //struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ + //dma_addr_t TxPhyAddr; + //dma_addr_t RxPhyAddr; + //struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ + //struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ + unsigned rx_buf_sz; + u16 HwSuppNumTxQueues; + u16 HwSuppNumRxQueues; + unsigned int num_tx_rings; + unsigned int num_rx_rings; + struct rtl8125_tx_ring tx_ring[R8125_MAX_TX_QUEUES]; + struct rtl8125_rx_ring rx_ring[R8125_MAX_RX_QUEUES]; +#ifdef ENABLE_LIB_SUPPORT + struct atomic_notifier_head lib_nh; + struct rtl8125_ring lib_tx_ring[R8125_MAX_TX_QUEUES]; + struct rtl8125_ring lib_rx_ring[R8125_MAX_RX_QUEUES]; +#endif + //struct timer_list esd_timer; + //struct timer_list link_timer; + struct pci_resource pci_cfg_space; + unsigned int esd_flag; + unsigned int pci_cfg_is_read; + unsigned int rtl8125_rx_config; + u16 cp_cmd; + u32 intr_mask; + u32 timer_intr_mask; + u16 isr_reg[R8125_MAX_QUEUES]; + u16 imr_reg[R8125_MAX_QUEUES]; + int phy_auto_nego_reg; + int phy_1000_ctrl_reg; + int phy_2500_ctrl_reg; + u8 org_mac_addr[NODE_ADDRESS_SIZE]; + struct rtl8125_counters *tally_vaddr; + dma_addr_t tally_paddr; + +#ifdef CONFIG_R8125_VLAN + struct vlan_group *vlgrp; +#endif + u8 wol_enabled; + u32 wol_opts; + u8 efuse_ver; + u8 eeprom_type; + u8 autoneg; + u8 duplex; + u32 speed; + u32 advertising; + enum rtl8125_fc_mode fcpause; + u16 eeprom_len; + u16 cur_page; + u32 bios_setting; + + int (*set_speed)(struct net_device *, u8 autoneg, u32 speed, u8 duplex, u32 adv); +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + void (*get_settings)(struct net_device *, struct ethtool_cmd *); +#else + void (*get_settings)(struct net_device *, struct ethtool_link_ksettings *); +#endif + void (*phy_reset_enable)(struct net_device *); + unsigned int (*phy_reset_pending)(struct net_device *); + unsigned int (*link_ok)(struct net_device *); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + struct work_struct reset_task; + struct work_struct esd_task; + struct work_struct linkchg_task; +#else + struct delayed_work reset_task; + struct delayed_work esd_task; + struct delayed_work linkchg_task; +#endif + DECLARE_BITMAP(task_flags, R8125_FLAG_MAX); + unsigned features; + + u8 org_pci_offset_99; + u8 org_pci_offset_180; + u8 issue_offset_99_event; + + u8 org_pci_offset_80; + u8 org_pci_offset_81; + u8 use_timer_interrrupt; + + u32 keep_intr_cnt; + + u8 HwIcVerUnknown; + u8 NotWrRamCodeToMicroP; + u8 NotWrMcuPatchCode; + u8 HwHasWrRamCodeToMicroP; + + u16 sw_ram_code_ver; + u16 hw_ram_code_ver; + + u8 rtk_enable_diag; + + u8 ShortPacketSwChecksum; + + u8 UseSwPaddingShortPkt; + + u8 RequireAdcBiasPatch; + u16 AdcBiasPatchIoffset; + + u8 RequireAdjustUpsTxLinkPulseTiming; + u16 SwrCnt1msIni; + + u8 HwSuppNowIsOobVer; + + u8 RequiredSecLanDonglePatch; + + u8 RequirePhyMdiSwapPatch; + + u8 RequireLSOPatch; + + u32 HwFiberModeVer; + u32 HwFiberStat; + u8 HwSwitchMdiToFiber; + + u16 NicCustLedValue; + + u8 HwSuppMagicPktVer; + + u8 HwSuppLinkChgWakeUpVer; + + u8 HwSuppCheckPhyDisableModeVer; + + u8 random_mac; + + u16 phy_reg_aner; + u16 phy_reg_anlpar; + u16 phy_reg_gbsr; + u16 phy_reg_status_2500; + + u32 HwPcieSNOffset; + + u8 HwSuppTxNoCloseVer; + u8 EnableTxNoClose; + + u8 HwSuppIsrVer; + u8 HwCurrIsrVer; + + u8 HwSuppIntMitiVer; + + u8 HwSuppExtendTallyCounterVer; + + u8 check_keep_link_speed; + u8 resume_not_chg_speed; + + u8 HwSuppD0SpeedUpVer; + u8 D0SpeedUpSpeed; + + u8 ring_lib_enabled; + + const char *fw_name; + struct rtl8125_fw *rtl_fw; + u32 ocp_base; + + //Dash+++++++++++++++++ + u8 HwSuppDashVer; + u8 DASH; + u8 dash_printer_enabled; + u8 HwPkgDet; + void __iomem *mapped_cmac_ioaddr; /* mapped cmac memory map physical address */ + void __iomem *cmac_ioaddr; /* cmac memory map physical address */ + +#ifdef ENABLE_DASH_SUPPORT + u16 AfterRecvFromFwBufLen; + u8 AfterRecvFromFwBuf[RECV_FROM_FW_BUF_SIZE]; + u16 AfterSendToFwBufLen; + u8 AfterSendToFwBuf[SEND_TO_FW_BUF_SIZE]; + u16 SendToFwBufferLen; + u32 SizeOfSendToFwBuffer; + u32 SizeOfSendToFwBufferMemAlloc; + u32 NumOfSendToFwBuffer; + + u8 OobReq; + u8 OobAck; + u32 OobReqComplete; + u32 OobAckComplete; + + u8 RcvFwReqSysOkEvt; + u8 RcvFwDashOkEvt; + u8 SendFwHostOkEvt; + + u8 DashFwDisableRx; + + void *UnalignedSendToFwBufferVa; + void *SendToFwBuffer; + u64 SendToFwBufferPhy; + u8 SendingToFw; + dma_addr_t UnalignedSendToFwBufferPa; + PTX_DASH_SEND_FW_DESC TxDashSendFwDesc; + u64 TxDashSendFwDescPhy; + u8 *UnalignedTxDashSendFwDescVa; + u32 SizeOfTxDashSendFwDescMemAlloc; + u32 SizeOfTxDashSendFwDesc; + u32 NumTxDashSendFwDesc; + u32 CurrNumTxDashSendFwDesc; + u32 LastSendNumTxDashSendFwDesc; + dma_addr_t UnalignedTxDashSendFwDescPa; + + u32 NumRecvFromFwBuffer; + u32 SizeOfRecvFromFwBuffer; + u32 SizeOfRecvFromFwBufferMemAlloc; + void *RecvFromFwBuffer; + u64 RecvFromFwBufferPhy; + + void *UnalignedRecvFromFwBufferVa; + dma_addr_t UnalignedRecvFromFwBufferPa; + PRX_DASH_FROM_FW_DESC RxDashRecvFwDesc; + u64 RxDashRecvFwDescPhy; + u8 *UnalignedRxDashRecvFwDescVa; + u32 SizeOfRxDashRecvFwDescMemAlloc; + u32 SizeOfRxDashRecvFwDesc; + u32 NumRxDashRecvFwDesc; + u32 CurrNumRxDashRecvFwDesc; + dma_addr_t UnalignedRxDashRecvFwDescPa; + u8 DashReqRegValue; + u16 HostReqValue; + + u32 CmacResetIsrCounter; + u8 CmacResetIntr; + u8 CmacResetting; + u8 CmacOobIssueCmacReset; + u32 CmacResetbyFwCnt; + +#if defined(ENABLE_DASH_PRINTER_SUPPORT) + struct completion fw_ack; + struct completion fw_req; + struct completion fw_host_ok; +#endif + //Dash----------------- +#endif //ENABLE_DASH_SUPPORT + + //Realwow++++++++++++++ + u8 HwSuppKCPOffloadVer; + + u8 EnableDhcpTimeoutWake; + u8 EnableTeredoOffload; + u8 EnableKCPOffload; +#ifdef ENABLE_REALWOW_SUPPORT + u32 DhcpTimeout; + MP_KCP_INFO MpKCPInfo; + //Realwow-------------- +#endif //ENABLE_REALWOW_SUPPORT + + struct ethtool_eee eee; + +#ifdef ENABLE_R8125_PROCFS + //Procfs support + struct proc_dir_entry *proc_dir; +#endif + u8 InitRxDescType; + u16 RxDescLength; //V1 16 Byte V2 32 Bytes + u32 RxDescRingLength; + + u8 HwSuppPtpVer; + u8 EnablePtp; + u8 ptp_master_mode; + s64 ptp_adjust; +#ifdef ENABLE_PTP_SUPPORT + u32 tx_hwtstamp_timeouts; + u32 tx_hwtstamp_skipped; + struct work_struct ptp_tx_work; + struct sk_buff *ptp_tx_skb; + struct hwtstamp_config hwtstamp_config; + unsigned long ptp_tx_start; + struct ptp_clock_info ptp_clock_info; + struct ptp_clock *ptp_clock; +#endif + + u8 HwSuppRssVer; + u8 EnableRss; + u16 HwSuppIndirTblEntries; +#ifdef ENABLE_RSS_SUPPORT + u32 rss_flags; + /* Receive Side Scaling settings */ + u8 rss_key[RTL8125_RSS_KEY_SIZE]; + u8 rss_indir_tbl[RTL8125_MAX_INDIRECTION_TABLE_ENTRIES]; + u32 rss_options; +#endif +}; + +#ifdef ENABLE_LIB_SUPPORT +static inline unsigned int +rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) +{ + int count, i; + + for (count = 0, i = tp->num_tx_rings; i < tp->HwSuppNumTxQueues; i++) + if(tp->lib_tx_ring[i].enabled) + count++; + + return count; +} + +static inline unsigned int +rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) +{ + int count, i; + + for (count = 0, i = tp->num_rx_rings; i < tp->HwSuppNumRxQueues; i++) + if(tp->lib_rx_ring[i].enabled) + count++; + + return count; +} + +#else +static inline unsigned int +rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) +{ + return 0; +} + +static inline unsigned int +rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) +{ + return 0; +} +#endif + +static inline unsigned int +rtl8125_tot_tx_rings(struct rtl8125_private *tp) +{ + return tp->num_tx_rings + rtl8125_num_lib_tx_rings(tp); +} + +static inline unsigned int +rtl8125_tot_rx_rings(struct rtl8125_private *tp) +{ + return tp->num_rx_rings + rtl8125_num_lib_rx_rings(tp); +} + +enum eetype { + EEPROM_TYPE_NONE=0, + EEPROM_TYPE_93C46, + EEPROM_TYPE_93C56, + EEPROM_TWSI +}; + +enum mcfg { + CFG_METHOD_2=2, + CFG_METHOD_3, + CFG_METHOD_4, + CFG_METHOD_5, + CFG_METHOD_DEFAULT, + CFG_METHOD_MAX +}; + +#define LSO_32K 32000 +#define LSO_64K 64000 + +#define NIC_MIN_PHYS_BUF_COUNT (2) +#define NIC_MAX_PHYS_BUF_COUNT_LSO_64K (24) +#define NIC_MAX_PHYS_BUF_COUNT_LSO2 (16*4) + +#define GTTCPHO_SHIFT 18 +#define GTTCPHO_MAX 0x7fU +#define GTPKTSIZE_MAX 0x3ffffU +#define TCPHO_SHIFT 18 +#define TCPHO_MAX 0x3ffU +#define LSOPKTSIZE_MAX 0xffffU +#define MSS_MAX 0x07ffu /* MSS value */ + +#define OOB_CMD_RESET 0x00 +#define OOB_CMD_DRIVER_START 0x05 +#define OOB_CMD_DRIVER_STOP 0x06 +#define OOB_CMD_SET_IPMAC 0x41 + +#define WAKEUP_MAGIC_PACKET_NOT_SUPPORT (0) +#define WAKEUP_MAGIC_PACKET_V1 (1) +#define WAKEUP_MAGIC_PACKET_V2 (2) +#define WAKEUP_MAGIC_PACKET_V3 (3) + +//Ram Code Version +#define NIC_RAMCODE_VERSION_CFG_METHOD_2 (0x0b11) +#define NIC_RAMCODE_VERSION_CFG_METHOD_3 (0x0b33) +#define NIC_RAMCODE_VERSION_CFG_METHOD_4 (0x0b17) +#define NIC_RAMCODE_VERSION_CFG_METHOD_5 (0x0b55) + +//hwoptimize +#define HW_PATCH_SOC_LAN (BIT_0) +#define HW_PATCH_SAMSUNG_LAN_DONGLE (BIT_2) + +static const u16 other_q_intr_mask = (RxOK1 | RxDU1); + +void rtl8125_mdio_write(struct rtl8125_private *tp, u16 RegAddr, u16 value); +void rtl8125_mdio_prot_write(struct rtl8125_private *tp, u32 RegAddr, u32 value); +void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, u32 RegAddr, u32 value); +u32 rtl8125_mdio_read(struct rtl8125_private *tp, u16 RegAddr); +u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, u32 RegAddr); +u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, u32 RegAddr); +void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value); +void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value); +u32 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr); +void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); +void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); +void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 data); +void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd); +void rtl8125_init_ring_indexes(struct rtl8125_private *tp); +int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); +void rtl8125_oob_mutex_lock(struct rtl8125_private *tp); +u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len); +u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 base_address); +u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, u32 base_address); +u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type); +u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, u32 base_address); +int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); +int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, u32 base_address); +u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr); +void rtl8125_wait_txrx_fifo_empty(struct net_device *dev); +void rtl8125_enable_now_is_oob(struct rtl8125_private *tp); +void rtl8125_disable_now_is_oob(struct rtl8125_private *tp); +void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp); +void rtl8125_dash2_disable_tx(struct rtl8125_private *tp); +void rtl8125_dash2_enable_tx(struct rtl8125_private *tp); +void rtl8125_dash2_disable_rx(struct rtl8125_private *tp); +void rtl8125_dash2_enable_rx(struct rtl8125_private *tp); +void rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev); +void rtl8125_mark_to_asic(struct rtl8125_private *tp, struct RxDesc *desc, u32 rx_buf_sz); + +static inline void +rtl8125_make_unusable_by_asic(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { + ((struct RxDescV3 *)desc)->addr = RTL8125_MAGIC_NUMBER; + ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1 &= ~cpu_to_le32(DescOwn | RsvdMaskV3); + } else { + desc->addr = RTL8125_MAGIC_NUMBER; + desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); + } +} + +static inline struct RxDesc* +rtl8125_get_rxdesc(struct rtl8125_private *tp, struct RxDesc *RxDescBase, u32 const cur_rx) +{ + return (struct RxDesc*)((u8*)RxDescBase + (cur_rx * tp->RxDescLength)); +} + +static inline void +rtl8125_disable_hw_interrupt_v2(struct rtl8125_private *tp, + u32 message_id) +{ + RTL_W32(tp, IMR_V2_CLEAR_REG_8125, BIT(message_id)); +} + +static inline void +rtl8125_enable_hw_interrupt_v2(struct rtl8125_private *tp, u32 message_id) +{ + RTL_W32(tp, IMR_V2_SET_REG_8125, BIT(message_id)); +} + +int rtl8125_open(struct net_device *dev); +int rtl8125_close(struct net_device *dev); +void rtl8125_hw_config(struct net_device *dev); +void rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, u32 message_id, u8 timer_intmiti_val); +void rtl8125_set_rx_q_num(struct rtl8125_private *tp, unsigned int num_rx_queues); +void rtl8125_set_tx_q_num(struct rtl8125_private *tp, unsigned int num_tx_queues); +void rtl8125_hw_start(struct net_device *dev); +void rtl8125_hw_reset(struct net_device *dev); +void rtl8125_tx_clear(struct rtl8125_private *tp); +void rtl8125_rx_clear(struct rtl8125_private *tp); +int rtl8125_init_ring(struct net_device *dev); +void rtl8125_hw_set_rx_packet_filter(struct net_device *dev); +void rtl8125_enable_hw_linkchg_interrupt(struct rtl8125_private *tp); +int rtl8125_dump_tally_counter(struct rtl8125_private *tp, dma_addr_t paddr); + +#ifndef ENABLE_LIB_SUPPORT +static inline void rtl8125_lib_reset_prepare(struct rtl8125_private *tp) { } +static inline void rtl8125_lib_reset_complete(struct rtl8125_private *tp) { } +#endif + +#define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0 ) +#define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0) +#define HW_SUPPORT_D0_SPEED_UP(_M) ((_M)->HwSuppD0SpeedUpVer > 0) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) +#define netdev_mc_count(dev) ((dev)->mc_count) +#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) +#define netdev_for_each_mc_addr(mclist, dev) \ + for (mclist = dev->mc_list; mclist; mclist = mclist->next) +#endif + +#endif /* __R8125_H */ diff --git a/r8125/src/r8125_dash.h b/r8125/src/r8125_dash.h new file mode 100755 index 000000000..f86d4255a --- /dev/null +++ b/r8125/src/r8125_dash.h @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_R8125_DASH_H +#define _LINUX_R8125_DASH_H + +#include + +#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2 + +enum rtl_dash_cmd { + RTL_DASH_ARP_NS_OFFLOAD = 0, + RTL_DASH_SET_OOB_IPMAC, + RTL_DASH_NOTIFY_OOB, + + RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW, + RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE, + RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA, + RTL_DASH_OOB_REQ, + RTL_DASH_OOB_ACK, + RTL_DASH_DETACH_OOB_REQ, + RTL_DASH_DETACH_OOB_ACK, + + RTL_FW_SET_IPV4 = 0x10, + RTL_FW_GET_IPV4, + RTL_FW_SET_IPV6, + RTL_FW_GET_IPV6, + RTL_FW_SET_EXT_SNMP, + RTL_FW_GET_EXT_SNMP, + RTL_FW_SET_WAKEUP_PATTERN, + RTL_FW_GET_WAKEUP_PATTERN, + RTL_FW_DEL_WAKEUP_PATTERN, + + RTLT_DASH_COMMAND_INVALID, +}; + +struct rtl_dash_ip_mac { + struct sockaddr ifru_addr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; +}; + +struct rtl_dash_ioctl_struct { + __u32 cmd; + __u32 offset; + __u32 len; + union { + __u32 data; + void *data_buffer; + }; +}; + +struct settings_ipv4 { + __u32 IPv4addr; + __u32 IPv4mask; + __u32 IPv4Gateway; +}; + +struct settings_ipv6 { + __u32 reserved; + __u32 prefixLen; + __u16 IPv6addr[8]; + __u16 IPv6Gateway[8]; +}; + +struct settings_ext_snmp { + __u16 index; + __u16 oid_get_len; + __u8 oid_for_get[24]; + __u8 reserved0[26]; + __u16 value_len; + __u8 value[256]; + __u8 supported; + __u8 reserved1[27]; +}; + +struct wakeup_pattern { + __u8 index; + __u8 valid; + __u8 start; + __u8 length; + __u8 name[36]; + __u8 mask[16]; + __u8 pattern[128]; + __u32 reserved[2]; +}; + +typedef struct _RX_DASH_FROM_FW_DESC { + u16 length; + u8 statusLowByte; + u8 statusHighByte; + u32 resv; + u64 BufferAddress; +} +RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC; + +typedef struct _TX_DASH_SEND_FW_DESC { + u16 length; + u8 statusLowByte; + u8 statusHighByte; + u32 resv; + u64 BufferAddress; +} +TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC; + +typedef struct _OSOOBHdr { + u32 len; + u8 type; + u8 flag; + u8 hostReqV; + u8 res; +} +OSOOBHdr, *POSOOBHdr; + +typedef struct _RX_DASH_BUFFER_TYPE_2 { + OSOOBHdr oobhdr; + u8 RxDataBuffer[0]; +} +RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2; + +#define ALIGN_8 (0x7) +#define ALIGN_16 (0xf) +#define ALIGN_32 (0x1f) +#define ALIGN_64 (0x3f) +#define ALIGN_256 (0xff) +#define ALIGN_4096 (0xfff) + +#define OCP_REG_CONFIG0 (0x10) +#define OCP_REG_CONFIG0_REV_F (0xB8) +#define OCP_REG_DASH_POLL (0x30) +#define OCP_REG_HOST_REQ (0x34) +#define OCP_REG_DASH_REQ (0x35) +#define OCP_REG_CR (0x36) +#define OCP_REG_DMEMSTA (0x38) +#define OCP_REG_GPHYAR (0x60) + + +#define OCP_REG_CONFIG0_DASHEN BIT_15 +#define OCP_REG_CONFIG0_OOBRESET BIT_14 +#define OCP_REG_CONFIG0_APRDY BIT_13 +#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12 +#define OCP_REG_CONFIG0_DRIVERRDY BIT_11 +#define OCP_REG_CONFIG0_OOB_WDT BIT_9 +#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8 +#define OCP_REG_CONFIG0_TLSEN BIT_7 + +#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0 ) +#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1 ) +#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2 ) +#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3 ) + +#define RECV_FROM_FW_BUF_SIZE (1520) +#define SEND_TO_FW_BUF_SIZE (1520) + +#define RX_DASH_FROM_FW_OWN BIT_15 +#define TX_DASH_SEND_FW_OWN BIT_15 +#define TX_DASH_SEND_FW_OWN_HIGHBYTE BIT_7 + +#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3) +#define TXS_EXC BIT_4 +#define TXS_LNKF BIT_5 +#define TXS_OWC BIT_6 +#define TXS_TES BIT_7 +#define TXS_UNF BIT_9 +#define TXS_LGSEN BIT_11 +#define TXS_LS BIT_12 +#define TXS_FS BIT_13 +#define TXS_EOR BIT_14 +#define TXS_OWN BIT_15 + +#define TPPool_HRDY 0x20 + +#define HostReqReg (0xC0) +#define SystemMasterDescStartAddrLow (0xF0) +#define SystemMasterDescStartAddrHigh (0xF4) +#define SystemSlaveDescStartAddrLow (0xF8) +#define SystemSlaveDescStartAddrHigh (0xFC) + +//DASH Request Type +#define WSMANREG 0x01 +#define OSPUSHDATA 0x02 + +#define RXS_OWN BIT_15 +#define RXS_EOR BIT_14 +#define RXS_FS BIT_13 +#define RXS_LS BIT_12 + +#define ISRIMR_DP_DASH_OK BIT_15 +#define ISRIMR_DP_HOST_OK BIT_13 +#define ISRIMR_DP_REQSYS_OK BIT_11 + +#define ISRIMR_DASH_INTR_EN BIT_12 +#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15 + +#define ISRIMR_DASH_TYPE2_ROK BIT_0 +#define ISRIMR_DASH_TYPE2_RDU BIT_1 +#define ISRIMR_DASH_TYPE2_TOK BIT_2 +#define ISRIMR_DASH_TYPE2_TDU BIT_3 +#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4 +#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5 +#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6 + +#define CMAC_OOB_STOP 0x25 +#define CMAC_OOB_INIT 0x26 +#define CMAC_OOB_RESET 0x2a + +#define NO_BASE_ADDRESS 0x00000000 +#define RTL8168FP_OOBMAC_BASE 0xBAF70000 +#define RTL8168FP_CMAC_IOBASE 0xBAF20000 +#define RTL8168FP_KVM_BASE 0xBAF80400 +#define CMAC_SYNC_REG 0x20 +#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98 +#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F + +/* cmac write/read MMIO register */ +#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg)) +#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg))) + +int rtl8125_dash_ioctl(struct net_device *dev, struct ifreq *ifr); +void HandleDashInterrupt(struct net_device *dev); +int AllocateDashShareMemory(struct net_device *dev); +void FreeAllocatedDashShareMemory(struct net_device *dev); +void DashHwInit(struct net_device *dev); + + +#endif /* _LINUX_R8125_DASH_H */ diff --git a/r8125/src/r8125_firmware.c b/r8125/src/r8125_firmware.c new file mode 100755 index 000000000..ac4ea626b --- /dev/null +++ b/r8125/src/r8125_firmware.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8168 is the Linux device driver released for Realtek Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include +#include + +#include "r8125_firmware.h" + +enum rtl_fw_opcode { + PHY_READ = 0x0, + PHY_DATA_OR = 0x1, + PHY_DATA_AND = 0x2, + PHY_BJMPN = 0x3, + PHY_MDIO_CHG = 0x4, + PHY_CLEAR_READCOUNT = 0x7, + PHY_WRITE = 0x8, + PHY_READCOUNT_EQ_SKIP = 0x9, + PHY_COMP_EQ_SKIPN = 0xa, + PHY_COMP_NEQ_SKIPN = 0xb, + PHY_WRITE_PREVIOUS = 0xc, + PHY_SKIPN = 0xd, + PHY_DELAY_MS = 0xe, +}; + +struct fw_info { + u32 magic; + char version[RTL8125_VER_SIZE]; + __le32 fw_start; + __le32 fw_len; + u8 chksum; +} __packed; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) +#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) +#endif +#define FW_OPCODE_SIZE sizeof_field(struct rtl8125_fw_phy_action, code[0]) + +static bool rtl8125_fw_format_ok(struct rtl8125_fw *rtl_fw) +{ + const struct firmware *fw = rtl_fw->fw; + struct fw_info *fw_info = (struct fw_info *)fw->data; + struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; + + if (fw->size < FW_OPCODE_SIZE) + return false; + + if (!fw_info->magic) { + size_t i, size, start; + u8 checksum = 0; + + if (fw->size < sizeof(*fw_info)) + return false; + + for (i = 0; i < fw->size; i++) + checksum += fw->data[i]; + if (checksum != 0) + return false; + + start = le32_to_cpu(fw_info->fw_start); + if (start > fw->size) + return false; + + size = le32_to_cpu(fw_info->fw_len); + if (size > (fw->size - start) / FW_OPCODE_SIZE) + return false; + + strscpy(rtl_fw->version, fw_info->version, RTL8125_VER_SIZE); + + pa->code = (__le32 *)(fw->data + start); + pa->size = size; + } else { + if (fw->size % FW_OPCODE_SIZE) + return false; + + strscpy(rtl_fw->version, rtl_fw->fw_name, RTL8125_VER_SIZE); + + pa->code = (__le32 *)fw->data; + pa->size = fw->size / FW_OPCODE_SIZE; + } + + return true; +} + +static bool rtl8125_fw_data_ok(struct rtl8125_fw *rtl_fw) +{ + struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; + size_t index; + + for (index = 0; index < pa->size; index++) { + u32 action = le32_to_cpu(pa->code[index]); + u32 val = action & 0x0000ffff; + u32 regno = (action & 0x0fff0000) >> 16; + + switch (action >> 28) { + case PHY_READ: + case PHY_DATA_OR: + case PHY_DATA_AND: + case PHY_CLEAR_READCOUNT: + case PHY_WRITE: + case PHY_WRITE_PREVIOUS: + case PHY_DELAY_MS: + break; + + case PHY_MDIO_CHG: + if (val > 1) + goto out; + break; + + case PHY_BJMPN: + if (regno > index) + goto out; + break; + case PHY_READCOUNT_EQ_SKIP: + if (index + 2 >= pa->size) + goto out; + break; + case PHY_COMP_EQ_SKIPN: + case PHY_COMP_NEQ_SKIPN: + case PHY_SKIPN: + if (index + 1 + regno >= pa->size) + goto out; + break; + + default: + dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); + return false; + } + } + + return true; +out: + dev_err(rtl_fw->dev, "Out of range of firmware\n"); + return false; +} + +void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw) +{ + struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; + rtl8125_fw_write_t fw_write = rtl_fw->phy_write; + rtl8125_fw_read_t fw_read = rtl_fw->phy_read; + int predata = 0, count = 0; + size_t index; + + for (index = 0; index < pa->size; index++) { + u32 action = le32_to_cpu(pa->code[index]); + u32 data = action & 0x0000ffff; + u32 regno = (action & 0x0fff0000) >> 16; + enum rtl_fw_opcode opcode = action >> 28; + + if (!action) + break; + + switch (opcode) { + case PHY_READ: + predata = fw_read(tp, regno); + count++; + break; + case PHY_DATA_OR: + predata |= data; + break; + case PHY_DATA_AND: + predata &= data; + break; + case PHY_BJMPN: + index -= (regno + 1); + break; + case PHY_MDIO_CHG: + if (data) { + fw_write = rtl_fw->mac_mcu_write; + fw_read = rtl_fw->mac_mcu_read; + } else { + fw_write = rtl_fw->phy_write; + fw_read = rtl_fw->phy_read; + } + + break; + case PHY_CLEAR_READCOUNT: + count = 0; + break; + case PHY_WRITE: + fw_write(tp, regno, data); + break; + case PHY_READCOUNT_EQ_SKIP: + if (count == data) + index++; + break; + case PHY_COMP_EQ_SKIPN: + if (predata == data) + index += regno; + break; + case PHY_COMP_NEQ_SKIPN: + if (predata != data) + index += regno; + break; + case PHY_WRITE_PREVIOUS: + fw_write(tp, regno, predata); + break; + case PHY_SKIPN: + index += regno; + break; + case PHY_DELAY_MS: + mdelay(data); + break; + } + } +} + +void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw) +{ + release_firmware(rtl_fw->fw); +} + +int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw) +{ + int rc; + + rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); + if (rc < 0) + goto out; + + if (!rtl8125_fw_format_ok(rtl_fw) || !rtl8125_fw_data_ok(rtl_fw)) { + release_firmware(rtl_fw->fw); + rc = -EINVAL; + goto out; + } + + return 0; +out: + dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", + rtl_fw->fw_name, rc); + return rc; +} diff --git a/r8125/src/r8125_firmware.h b/r8125/src/r8125_firmware.h new file mode 100755 index 000000000..1961be5d5 --- /dev/null +++ b/r8125/src/r8125_firmware.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_rtl8125_FIRMWARE_H +#define _LINUX_rtl8125_FIRMWARE_H + +#include +#include + +struct rtl8125_private; +typedef void (*rtl8125_fw_write_t)(struct rtl8125_private *tp, u16 reg, u16 val); +typedef u32 (*rtl8125_fw_read_t)(struct rtl8125_private *tp, u16 reg); + +#define RTL8125_VER_SIZE 32 + +struct rtl8125_fw { + rtl8125_fw_write_t phy_write; + rtl8125_fw_read_t phy_read; + rtl8125_fw_write_t mac_mcu_write; + rtl8125_fw_read_t mac_mcu_read; + const struct firmware *fw; + const char *fw_name; + struct device *dev; + + char version[RTL8125_VER_SIZE]; + + struct rtl8125_fw_phy_action { + __le32 *code; + size_t size; + } phy_action; +}; + +int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw); +void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw); +void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw); + +#endif /* _LINUX_rtl8125_FIRMWARE_H */ diff --git a/r8125/src/r8125_n.c b/r8125/src/r8125_n.c new file mode 100755 index 000000000..fd96e8f8e --- /dev/null +++ b/r8125/src/r8125_n.c @@ -0,0 +1,15150 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +/* + * This driver is modified from r8169.c in Linux kernel 2.6.18 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +#include +#include +#endif +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) +#include +#endif +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#define dev_printk(A,B,fmt,args...) printk(A fmt,##args) +#else +#include +#include +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) +#include +#endif + +#include +#include + +#include "r8125.h" +#include "rtl_eeprom.h" +#include "rtltool.h" +#include "r8125_firmware.h" + +#ifdef ENABLE_R8125_PROCFS +#include +#include +#endif + +#define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw" +#define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw" + +/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). + The RTL chips use a 64 element hash table based on the Ethernet CRC. */ +static const int multicast_filter_limit = 32; + +static const struct { + const char *name; + const char *fw_name; +} rtl_chip_fw_infos[] = { + /* PCI-E devices. */ + [CFG_METHOD_2] = {"RTL8125A" }, + [CFG_METHOD_3] = {"RTL8125A", FIRMWARE_8125A_3}, + [CFG_METHOD_4] = {"RTL8125B", }, + [CFG_METHOD_5] = {"RTL8125B", FIRMWARE_8125B_2}, + [CFG_METHOD_DEFAULT] = {"Unknown", }, +}; + +#define _R(NAME,MAC,RCR,MASK,JumFrameSz) \ + { .name = NAME, .mcfg = MAC, .RCR_Cfg = RCR, .RxConfigMask = MASK, .jumbo_frame_sz = JumFrameSz } + +static const struct { + const char *name; + u8 mcfg; + u32 RCR_Cfg; + u32 RxConfigMask; /* Clears the bits supported by this chip */ + u32 jumbo_frame_sz; +} rtl_chip_info[] = { + _R("RTL8125A", + CFG_METHOD_2, + BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_9k), + + _R("RTL8125A", + CFG_METHOD_3, + BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_9k), + + _R("RTL8125B", + CFG_METHOD_4, + BIT_30 | RxCfg_pause_slot_en | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_9k), + + _R("RTL8125B", + CFG_METHOD_5, + BIT_30 | RxCfg_pause_slot_en | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_9k), + + _R("Unknown", + CFG_METHOD_DEFAULT, + (RX_DMA_BURST << RxCfgDMAShift), + 0xff7e5880, + Jumbo_Frame_1k) +}; +#undef _R + + +#ifndef PCI_VENDOR_ID_DLINK +#define PCI_VENDOR_ID_DLINK 0x1186 +#endif + +static struct pci_device_id rtl8125_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125), }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x3000), }, + {0,}, +}; + +MODULE_DEVICE_TABLE(pci, rtl8125_pci_tbl); + +static int rx_copybreak = 0; +static int use_dac = 1; +static int timer_count = 0x2600; +static int timer_count_v2 = (0x2600 / 0x100); + +static struct { + u32 msg_enable; +} debug = { -1 }; + +static unsigned int speed_mode = SPEED_2500; +static unsigned int duplex_mode = DUPLEX_FULL; +static unsigned int autoneg_mode = AUTONEG_ENABLE; +static unsigned int advertising_mode = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_2500baseX_Full; +#ifdef CONFIG_ASPM +static int aspm = 1; +#else +static int aspm = 0; +#endif +#ifdef ENABLE_S5WOL +static int s5wol = 1; +#else +static int s5wol = 0; +#endif +#ifdef ENABLE_S5_KEEP_CURR_MAC +static int s5_keep_curr_mac = 1; +#else +static int s5_keep_curr_mac = 0; +#endif +#ifdef ENABLE_EEE +static int eee_enable = 1; +#else +static int eee_enable = 0; +#endif +#ifdef CONFIG_SOC_LAN +static ulong hwoptimize = HW_PATCH_SOC_LAN; +#else +static ulong hwoptimize = 0; +#endif +#ifdef ENABLE_S0_MAGIC_PACKET +static int s0_magic_packet = 1; +#else +static int s0_magic_packet = 0; +#endif +#ifdef ENABLE_TX_NO_CLOSE +static int tx_no_close_enable = 1; +#else +static int tx_no_close_enable = 0; +#endif +#ifdef ENABLE_PTP_MASTER_MODE +static int enable_ptp_master_mode = 1; +#else +static int enable_ptp_master_mode = 0; +#endif +#ifdef DISABLE_PM_SUPPORT +static int disable_pm_support = 1; +#else +static int disable_pm_support = 0; +#endif + +MODULE_AUTHOR("Realtek and the Linux r8125 crew "); +MODULE_DESCRIPTION("Realtek RTL8125 2.5Gigabit Ethernet driver"); + +module_param(speed_mode, uint, 0); +MODULE_PARM_DESC(speed_mode, "force phy operation. Deprecated by ethtool (8)."); + +module_param(duplex_mode, uint, 0); +MODULE_PARM_DESC(duplex_mode, "force phy operation. Deprecated by ethtool (8)."); + +module_param(autoneg_mode, uint, 0); +MODULE_PARM_DESC(autoneg_mode, "force phy operation. Deprecated by ethtool (8)."); + +module_param(advertising_mode, uint, 0); +MODULE_PARM_DESC(advertising_mode, "force phy operation. Deprecated by ethtool (8)."); + +module_param(aspm, int, 0); +MODULE_PARM_DESC(aspm, "Enable ASPM."); + +module_param(s5wol, int, 0); +MODULE_PARM_DESC(s5wol, "Enable Shutdown Wake On Lan."); + +module_param(s5_keep_curr_mac, int, 0); +MODULE_PARM_DESC(s5_keep_curr_mac, "Enable Shutdown Keep Current MAC Address."); + +module_param(rx_copybreak, int, 0); +MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); + +module_param(use_dac, int, 0); +MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); + +module_param(timer_count, int, 0); +MODULE_PARM_DESC(timer_count, "Timer Interrupt Interval."); + +module_param(eee_enable, int, 0); +MODULE_PARM_DESC(eee_enable, "Enable Energy Efficient Ethernet."); + +module_param(hwoptimize, ulong, 0); +MODULE_PARM_DESC(hwoptimize, "Enable HW optimization function."); + +module_param(s0_magic_packet, int, 0); +MODULE_PARM_DESC(s0_magic_packet, "Enable S0 Magic Packet."); + +module_param(tx_no_close_enable, int, 0); +MODULE_PARM_DESC(tx_no_close_enable, "Enable TX No Close."); + +module_param(enable_ptp_master_mode, int, 0); +MODULE_PARM_DESC(enable_ptp_master_mode, "Enable PTP Master Mode."); + +module_param(disable_pm_support, int, 0); +MODULE_PARM_DESC(disable_pm_support, "Disable PM support."); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) +module_param_named(debug, debug.msg_enable, int, 0); +MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); +#endif//LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + +MODULE_LICENSE("GPL"); +#ifdef ENABLE_USE_FIRMWARE_FILE +MODULE_FIRMWARE(FIRMWARE_8125A_3); +MODULE_FIRMWARE(FIRMWARE_8125B_2); +#endif + +MODULE_VERSION(RTL8125_VERSION); + +/* +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) +static void rtl8125_esd_timer(unsigned long __opaque); +#else +static void rtl8125_esd_timer(struct timer_list *t); +#endif +*/ +/* +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) +static void rtl8125_link_timer(unsigned long __opaque); +#else +static void rtl8125_link_timer(struct timer_list *t); +#endif +*/ + +static netdev_tx_t rtl8125_start_xmit(struct sk_buff *skb, struct net_device *dev); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +#else +static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs); +#else +static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance); +#endif +static void rtl8125_set_rx_mode(struct net_device *dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +static void rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue); +#else +static void rtl8125_tx_timeout(struct net_device *dev); +#endif +static struct net_device_stats *rtl8125_get_stats(struct net_device *dev); +static int rtl8125_rx_interrupt(struct net_device *, struct rtl8125_private *, struct rtl8125_rx_ring *, napi_budget); +static int rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget); +static int rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, const int message_id, int budget); +static int rtl8125_change_mtu(struct net_device *dev, int new_mtu); +static void rtl8125_down(struct net_device *dev); + +static int rtl8125_set_mac_address(struct net_device *dev, void *p); +static void rtl8125_rar_set(struct rtl8125_private *tp, uint8_t *addr); +static void rtl8125_desc_addr_fill(struct rtl8125_private *); +static void rtl8125_tx_desc_init(struct rtl8125_private *tp); +static void rtl8125_rx_desc_init(struct rtl8125_private *tp); + +static u32 mdio_direct_read_phy_ocp(struct rtl8125_private *tp, u16 RegAddr); +static u16 rtl8125_get_hw_phy_mcu_code_ver(struct rtl8125_private *tp); +static void rtl8125_phy_power_up(struct net_device *dev); +static void rtl8125_phy_power_down(struct net_device *dev); +static int rtl8125_set_speed(struct net_device *dev, u8 autoneg, u32 speed, u8 duplex, u32 adv); +static bool rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp); +static bool rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp); + +#ifdef CONFIG_R8125_NAPI +static int rtl8125_poll(napi_ptr napi, napi_budget budget); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_reset_task(void *_data); +static void rtl8125_esd_task(void *_data); +static void rtl8125_linkchg_task(void *_data); +#else +static void rtl8125_reset_task(struct work_struct *work); +static void rtl8125_esd_task(struct work_struct *work); +static void rtl8125_linkchg_task(struct work_struct *work); +#endif +static void rtl8125_schedule_reset_work(struct rtl8125_private *tp); +static void rtl8125_schedule_esd_work(struct rtl8125_private *tp); +static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp); +static void rtl8125_init_all_schedule_work(struct rtl8125_private *tp); +static void rtl8125_cancel_all_schedule_work(struct rtl8125_private *tp); + +static inline struct device *tp_to_dev(struct rtl8125_private *tp) +{ + return &tp->pci_dev->dev; +} + +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) && \ + LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,00))) +void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, + u32 legacy_u32) +{ + bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); + dst[0] = legacy_u32; +} + +bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, + const unsigned long *src) +{ + bool retval = true; + + /* TODO: following test will soon always be true */ + if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { + __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); + + bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_fill(ext, 32); + bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); + if (bitmap_intersects(ext, src, + __ETHTOOL_LINK_MODE_MASK_NBITS)) { + /* src mask goes beyond bit 31 */ + retval = false; + } + } + *legacy_u32 = src[0]; + return retval; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) + +#ifndef LPA_1000FULL +#define LPA_1000FULL 0x0800 +#endif + +#ifndef LPA_1000HALF +#define LPA_1000HALF 0x0400 +#endif + +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) +static inline void eth_hw_addr_random(struct net_device *dev) +{ + random_ether_addr(dev->dev_addr); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#undef ethtool_ops +#define ethtool_ops _kc_ethtool_ops + +struct _kc_ethtool_ops { + int (*get_settings)(struct net_device *, struct ethtool_cmd *); + int (*set_settings)(struct net_device *, struct ethtool_cmd *); + void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); + int (*get_regs_len)(struct net_device *); + void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); + void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); + int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); + u32 (*get_msglevel)(struct net_device *); + void (*set_msglevel)(struct net_device *, u32); + int (*nway_reset)(struct net_device *); + u32 (*get_link)(struct net_device *); + int (*get_eeprom_len)(struct net_device *); + int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); + int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); + int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); + int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); + void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); + int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); + void (*get_pauseparam)(struct net_device *, + struct ethtool_pauseparam*); + int (*set_pauseparam)(struct net_device *, + struct ethtool_pauseparam*); + u32 (*get_rx_csum)(struct net_device *); + int (*set_rx_csum)(struct net_device *, u32); + u32 (*get_tx_csum)(struct net_device *); + int (*set_tx_csum)(struct net_device *, u32); + u32 (*get_sg)(struct net_device *); + int (*set_sg)(struct net_device *, u32); + u32 (*get_tso)(struct net_device *); + int (*set_tso)(struct net_device *, u32); + int (*self_test_count)(struct net_device *); + void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); + void (*get_strings)(struct net_device *, u32 stringset, u8 *); + int (*phys_id)(struct net_device *, u32); + int (*get_stats_count)(struct net_device *); + void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, + u64 *); +} *ethtool_ops = NULL; + +#undef SET_ETHTOOL_OPS +#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) + +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) +#ifndef SET_ETHTOOL_OPS +#define SET_ETHTOOL_OPS(netdev,ops) \ + ( (netdev)->ethtool_ops = (ops) ) +#endif //SET_ETHTOOL_OPS +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) + +//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) +#ifndef netif_msg_init +#define netif_msg_init _kc_netif_msg_init +/* copied from linux kernel 2.6.20 include/linux/netdevice.h */ +static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) +{ + /* use default */ + if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) + return default_msg_enable_bits; + if (debug_value == 0) /* no output */ + return 0; + /* set low N bits */ + return (1 << debug_value) - 1; +} + +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) +static inline void eth_copy_and_sum (struct sk_buff *dest, + const unsigned char *src, + int len, int base) +{ + memcpy (dest->data, src, len); +} +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) +/* copied from linux kernel 2.6.20 /include/linux/time.h */ +/* Parameters used to convert the timespec values: */ +#define MSEC_PER_SEC 1000L + +/* copied from linux kernel 2.6.20 /include/linux/jiffies.h */ +/* + * Change timeval to jiffies, trying to avoid the + * most obvious overflows.. + * + * And some not so obvious. + * + * Note that we don't want to return MAX_LONG, because + * for various timeout reasons we often end up having + * to wait "jiffies+1" in order to guarantee that we wait + * at _least_ "jiffies" - so "jiffies+1" had better still + * be positive. + */ +#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1) + +/* + * Convert jiffies to milliseconds and back. + * + * Avoid unnecessary multiplications/divisions in the + * two most common HZ cases: + */ +static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) +{ +#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) + return (MSEC_PER_SEC / HZ) * j; +#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) + return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); +#else + return (j * MSEC_PER_SEC) / HZ; +#endif +} + +static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) +{ + if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) + return MAX_JIFFY_OFFSET; +#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) + return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); +#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) + return m * (HZ / MSEC_PER_SEC); +#else + return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; +#endif +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) + +/* copied from linux kernel 2.6.12.6 /include/linux/pm.h */ +typedef int __bitwise pci_power_t; + +/* copied from linux kernel 2.6.12.6 /include/linux/pci.h */ +typedef u32 __bitwise pm_message_t; + +#define PCI_D0 ((pci_power_t __force) 0) +#define PCI_D1 ((pci_power_t __force) 1) +#define PCI_D2 ((pci_power_t __force) 2) +#define PCI_D3hot ((pci_power_t __force) 3) +#define PCI_D3cold ((pci_power_t __force) 4) +#define PCI_POWER_ERROR ((pci_power_t __force) -1) + +/* copied from linux kernel 2.6.12.6 /drivers/pci/pci.c */ +/** + * pci_choose_state - Choose the power state of a PCI device + * @dev: PCI device to be suspended + * @state: target sleep state for the whole system. This is the value + * that is passed to suspend() function. + * + * Returns PCI power state suitable for given device and given system + * message. + */ + +pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) +{ + if (!pci_find_capability(dev, PCI_CAP_ID_PM)) + return PCI_D0; + + switch (state) { + case 0: + return PCI_D0; + case 3: + return PCI_D3hot; + default: + printk("They asked me for state %d\n", state); +// BUG(); + } + return PCI_D0; +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) +/** + * msleep_interruptible - sleep waiting for waitqueue interruptions + * @msecs: Time in milliseconds to sleep for + */ +#define msleep_interruptible _kc_msleep_interruptible +unsigned long _kc_msleep_interruptible(unsigned int msecs) +{ + unsigned long timeout = _kc_msecs_to_jiffies(msecs); + + while (timeout && !signal_pending(current)) { + set_current_state(TASK_INTERRUPTIBLE); + timeout = schedule_timeout(timeout); + } + return _kc_jiffies_to_msecs(timeout); +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) +/* copied from linux kernel 2.6.20 include/linux/sched.h */ +#ifndef __sched +#define __sched __attribute__((__section__(".sched.text"))) +#endif + +/* copied from linux kernel 2.6.20 kernel/timer.c */ +signed long __sched schedule_timeout_uninterruptible(signed long timeout) +{ + __set_current_state(TASK_UNINTERRUPTIBLE); + return schedule_timeout(timeout); +} + +/* copied from linux kernel 2.6.20 include/linux/mii.h */ +#undef if_mii +#define if_mii _kc_if_mii +static inline struct mii_ioctl_data *if_mii(struct ifreq *rq) +{ + return (struct mii_ioctl_data *) &rq->ifr_ifru; +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) + +static u32 rtl8125_read_thermal_sensor(struct rtl8125_private *tp) +{ + u16 ts_digout; + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + ts_digout = mdio_direct_read_phy_ocp(tp, 0xBD84); + ts_digout &= 0x3ff; + break; + default: + ts_digout = 0xffff; + break; + } + + return ts_digout; +} + +int rtl8125_dump_tally_counter(struct rtl8125_private *tp, dma_addr_t paddr) +{ + u32 cmd; + u32 WaitCnt; + int retval = -1; + + RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); + cmd = (u64)paddr & DMA_BIT_MASK(32); + RTL_W32(tp, CounterAddrLow, cmd); + RTL_W32(tp, CounterAddrLow, cmd | CounterDump); + + WaitCnt = 0; + while (RTL_R32(tp, CounterAddrLow) & CounterDump) { + udelay(10); + + WaitCnt++; + if (WaitCnt > 20) + break; + } + + if (WaitCnt <= 20) + retval = 0; + + return retval; +} + +#ifdef ENABLE_R8125_PROCFS +/**************************************************************************** +* -----------------------------PROCFS STUFF------------------------- +***************************************************************************** +*/ + +static struct proc_dir_entry *rtl8125_proc; +static int proc_init_num = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +static int proc_get_driver_variable(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump Driver Variable\n"); + + rtnl_lock(); + + seq_puts(m, "Variable\tValue\n----------\t-----\n"); + seq_printf(m, "MODULENAME\t%s\n", MODULENAME); + seq_printf(m, "driver version\t%s\n", RTL8125_VERSION); + seq_printf(m, "mcfg\t%d\n", tp->mcfg); + seq_printf(m, "chipset\t%d\n", tp->chipset); + seq_printf(m, "chipset_name\t%s\n", rtl_chip_info[tp->chipset].name); + seq_printf(m, "mtu\t%d\n", dev->mtu); + seq_printf(m, "NUM_RX_DESC\t0x%x\n", NUM_RX_DESC); + seq_printf(m, "cur_rx0\t0x%x\n", tp->rx_ring[0].cur_rx); + seq_printf(m, "dirty_rx0\t0x%x\n", tp->rx_ring[0].dirty_rx); + seq_printf(m, "cur_rx1\t0x%x\n", tp->rx_ring[1].cur_rx); + seq_printf(m, "dirty_rx1\t0x%x\n", tp->rx_ring[1].dirty_rx); + seq_printf(m, "cur_rx2\t0x%x\n", tp->rx_ring[2].cur_rx); + seq_printf(m, "dirty_rx2\t0x%x\n", tp->rx_ring[2].dirty_rx); + seq_printf(m, "cur_rx3\t0x%x\n", tp->rx_ring[3].cur_rx); + seq_printf(m, "dirty_rx3\t0x%x\n", tp->rx_ring[3].dirty_rx); + seq_printf(m, "NUM_TX_DESC\t0x%x\n", NUM_TX_DESC); + seq_printf(m, "cur_tx0\t0x%x\n", tp->tx_ring[0].cur_tx); + seq_printf(m, "dirty_tx0\t0x%x\n", tp->tx_ring[0].dirty_tx); + seq_printf(m, "cur_tx1\t0x%x\n", tp->tx_ring[1].cur_tx); + seq_printf(m, "dirty_tx1\t0x%x\n", tp->tx_ring[1].dirty_tx); + seq_printf(m, "rx_buf_sz\t0x%x\n", tp->rx_buf_sz); + seq_printf(m, "esd_flag\t0x%x\n", tp->esd_flag); + seq_printf(m, "pci_cfg_is_read\t0x%x\n", tp->pci_cfg_is_read); + seq_printf(m, "rtl8125_rx_config\t0x%x\n", tp->rtl8125_rx_config); + seq_printf(m, "cp_cmd\t0x%x\n", tp->cp_cmd); + seq_printf(m, "intr_mask\t0x%x\n", tp->intr_mask); + seq_printf(m, "timer_intr_mask\t0x%x\n", tp->timer_intr_mask); + seq_printf(m, "wol_enabled\t0x%x\n", tp->wol_enabled); + seq_printf(m, "wol_opts\t0x%x\n", tp->wol_opts); + seq_printf(m, "efuse_ver\t0x%x\n", tp->efuse_ver); + seq_printf(m, "eeprom_type\t0x%x\n", tp->eeprom_type); + seq_printf(m, "autoneg\t0x%x\n", tp->autoneg); + seq_printf(m, "duplex\t0x%x\n", tp->duplex); + seq_printf(m, "speed\t%d\n", tp->speed); + seq_printf(m, "advertising\t0x%x\n", tp->advertising); + seq_printf(m, "eeprom_len\t0x%x\n", tp->eeprom_len); + seq_printf(m, "cur_page\t0x%x\n", tp->cur_page); + seq_printf(m, "bios_setting\t0x%x\n", tp->bios_setting); + seq_printf(m, "features\t0x%x\n", tp->features); + seq_printf(m, "org_pci_offset_99\t0x%x\n", tp->org_pci_offset_99); + seq_printf(m, "org_pci_offset_180\t0x%x\n", tp->org_pci_offset_180); + seq_printf(m, "issue_offset_99_event\t0x%x\n", tp->issue_offset_99_event); + seq_printf(m, "org_pci_offset_80\t0x%x\n", tp->org_pci_offset_80); + seq_printf(m, "org_pci_offset_81\t0x%x\n", tp->org_pci_offset_81); + seq_printf(m, "use_timer_interrrupt\t0x%x\n", tp->use_timer_interrrupt); + seq_printf(m, "HwIcVerUnknown\t0x%x\n", tp->HwIcVerUnknown); + seq_printf(m, "NotWrRamCodeToMicroP\t0x%x\n", tp->NotWrRamCodeToMicroP); + seq_printf(m, "NotWrMcuPatchCode\t0x%x\n", tp->NotWrMcuPatchCode); + seq_printf(m, "HwHasWrRamCodeToMicroP\t0x%x\n", tp->HwHasWrRamCodeToMicroP); + seq_printf(m, "sw_ram_code_ver\t0x%x\n", tp->sw_ram_code_ver); + seq_printf(m, "hw_ram_code_ver\t0x%x\n", tp->hw_ram_code_ver); + seq_printf(m, "rtk_enable_diag\t0x%x\n", tp->rtk_enable_diag); + seq_printf(m, "ShortPacketSwChecksum\t0x%x\n", tp->ShortPacketSwChecksum); + seq_printf(m, "UseSwPaddingShortPkt\t0x%x\n", tp->UseSwPaddingShortPkt); + seq_printf(m, "RequireAdcBiasPatch\t0x%x\n", tp->RequireAdcBiasPatch); + seq_printf(m, "AdcBiasPatchIoffset\t0x%x\n", tp->AdcBiasPatchIoffset); + seq_printf(m, "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n", tp->RequireAdjustUpsTxLinkPulseTiming); + seq_printf(m, "SwrCnt1msIni\t0x%x\n", tp->SwrCnt1msIni); + seq_printf(m, "HwSuppNowIsOobVer\t0x%x\n", tp->HwSuppNowIsOobVer); + seq_printf(m, "HwFiberModeVer\t0x%x\n", tp->HwFiberModeVer); + seq_printf(m, "HwFiberStat\t0x%x\n", tp->HwFiberStat); + seq_printf(m, "HwSwitchMdiToFiber\t0x%x\n", tp->HwSwitchMdiToFiber); + seq_printf(m, "NicCustLedValue\t0x%x\n", tp->NicCustLedValue); + seq_printf(m, "RequiredSecLanDonglePatch\t0x%x\n", tp->RequiredSecLanDonglePatch); + seq_printf(m, "HwSuppDashVer\t0x%x\n", tp->HwSuppDashVer); + seq_printf(m, "DASH\t0x%x\n", tp->DASH); + seq_printf(m, "dash_printer_enabled\t0x%x\n", tp->dash_printer_enabled); + seq_printf(m, "HwSuppKCPOffloadVer\t0x%x\n", tp->HwSuppKCPOffloadVer); + seq_printf(m, "speed_mode\t0x%x\n", speed_mode); + seq_printf(m, "duplex_mode\t0x%x\n", duplex_mode); + seq_printf(m, "autoneg_mode\t0x%x\n", autoneg_mode); + seq_printf(m, "advertising_mode\t0x%x\n", advertising_mode); + seq_printf(m, "aspm\t0x%x\n", aspm); + seq_printf(m, "s5wol\t0x%x\n", s5wol); + seq_printf(m, "s5_keep_curr_mac\t0x%x\n", s5_keep_curr_mac); + seq_printf(m, "eee_enable\t0x%x\n", tp->eee.eee_enabled); + seq_printf(m, "hwoptimize\t0x%lx\n", hwoptimize); + seq_printf(m, "proc_init_num\t0x%x\n", proc_init_num); + seq_printf(m, "s0_magic_packet\t0x%x\n", s0_magic_packet); + seq_printf(m, "HwSuppMagicPktVer\t0x%x\n", tp->HwSuppMagicPktVer); + seq_printf(m, "HwSuppLinkChgWakeUpVer\t0x%x\n", tp->HwSuppLinkChgWakeUpVer); + seq_printf(m, "HwSuppD0SpeedUpVer\t0x%x\n", tp->HwSuppD0SpeedUpVer); + seq_printf(m, "D0SpeedUpSpeed\t0x%x\n", tp->D0SpeedUpSpeed); + seq_printf(m, "HwSuppCheckPhyDisableModeVer\t0x%x\n", tp->HwSuppCheckPhyDisableModeVer); + seq_printf(m, "HwPkgDet\t0x%x\n", tp->HwPkgDet); + seq_printf(m, "HwSuppTxNoCloseVer\t0x%x\n", tp->HwSuppTxNoCloseVer); + seq_printf(m, "EnableTxNoClose\t0x%x\n", tp->EnableTxNoClose); + seq_printf(m, "NextHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].NextHwDesCloPtr); + seq_printf(m, "BeginHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].BeginHwDesCloPtr); + seq_printf(m, "NextHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].NextHwDesCloPtr); + seq_printf(m, "BeginHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].BeginHwDesCloPtr); + seq_printf(m, "InitRxDescType\t0x%x\n", tp->InitRxDescType); + seq_printf(m, "RxDescLength\t0x%x\n", tp->RxDescLength); + seq_printf(m, "num_rx_rings\t0x%x\n", tp->num_rx_rings); + seq_printf(m, "num_tx_rings\t0x%x\n", tp->num_tx_rings); + seq_printf(m, "tot_rx_rings\t0x%x\n", rtl8125_tot_rx_rings(tp)); + seq_printf(m, "tot_tx_rings\t0x%x\n", rtl8125_tot_tx_rings(tp)); + seq_printf(m, "EnableRss\t0x%x\n", tp->EnableRss); + seq_printf(m, "EnablePtp\t0x%x\n", tp->EnablePtp); + seq_printf(m, "ptp_master_mode\t0x%x\n", tp->ptp_master_mode); + seq_printf(m, "min_irq_nvecs\t0x%x\n", tp->min_irq_nvecs); + seq_printf(m, "irq_nvecs\t0x%x\n", tp->irq_nvecs); + seq_printf(m, "ring_lib_enabled\t0x%x\n", tp->ring_lib_enabled); + seq_printf(m, "HwSuppIsrVer\t0x%x\n", tp->HwSuppIsrVer); + seq_printf(m, "HwCurrIsrVer\t0x%x\n", tp->HwCurrIsrVer); +#ifdef ENABLE_PTP_SUPPORT + seq_printf(m, "tx_hwtstamp_timeouts\t0x%x\n", tp->tx_hwtstamp_timeouts); + seq_printf(m, "tx_hwtstamp_skipped\t0x%x\n", tp->tx_hwtstamp_skipped); +#endif + seq_printf(m, "random_mac\t0x%x\n", tp->random_mac); + seq_printf(m, "org_mac_addr\t%pM\n", tp->org_mac_addr); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + seq_printf(m, "perm_addr\t%pM\n", dev->perm_addr); +#endif + seq_printf(m, "dev_addr\t%pM\n", dev->dev_addr); + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_tally_counter(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct rtl8125_private *tp = netdev_priv(dev); + struct rtl8125_counters *counters; + dma_addr_t paddr; + + seq_puts(m, "\nDump Tally Counter\n"); + + rtnl_lock(); + + counters = tp->tally_vaddr; + paddr = tp->tally_paddr; + if (!counters) { + seq_puts(m, "\nDump Tally Counter Fail\n"); + goto out_unlock; + } + + rtl8125_dump_tally_counter(tp, paddr); + + seq_puts(m, "Statistics\tValue\n----------\t-----\n"); + seq_printf(m, "tx_packets\t%lld\n", le64_to_cpu(counters->tx_packets)); + seq_printf(m, "rx_packets\t%lld\n", le64_to_cpu(counters->rx_packets)); + seq_printf(m, "tx_errors\t%lld\n", le64_to_cpu(counters->tx_errors)); + seq_printf(m, "rx_errors\t%d\n", le32_to_cpu(counters->rx_errors)); + seq_printf(m, "rx_missed\t%d\n", le16_to_cpu(counters->rx_missed)); + seq_printf(m, "align_errors\t%d\n", le16_to_cpu(counters->align_errors)); + seq_printf(m, "tx_one_collision\t%d\n", le32_to_cpu(counters->tx_one_collision)); + seq_printf(m, "tx_multi_collision\t%d\n", le32_to_cpu(counters->tx_multi_collision)); + seq_printf(m, "rx_unicast\t%lld\n", le64_to_cpu(counters->rx_unicast)); + seq_printf(m, "rx_broadcast\t%lld\n", le64_to_cpu(counters->rx_broadcast)); + seq_printf(m, "rx_multicast\t%d\n", le32_to_cpu(counters->rx_multicast)); + seq_printf(m, "tx_aborted\t%d\n", le16_to_cpu(counters->tx_aborted)); + seq_printf(m, "tx_underrun\t%d\n", le16_to_cpu(counters->tx_underrun)); + + seq_printf(m, "tx_octets\t%lld\n", le64_to_cpu(counters->tx_octets)); + seq_printf(m, "rx_octets\t%lld\n", le64_to_cpu(counters->rx_octets)); + seq_printf(m, "rx_multicast64\t%lld\n", le64_to_cpu(counters->rx_multicast64)); + seq_printf(m, "tx_unicast64\t%lld\n", le64_to_cpu(counters->tx_unicast64)); + seq_printf(m, "tx_broadcast64\t%lld\n", le64_to_cpu(counters->tx_broadcast64)); + seq_printf(m, "tx_multicast64\t%lld\n", le64_to_cpu(counters->tx_multicast64)); + seq_printf(m, "tx_pause_on\t%d\n", le32_to_cpu(counters->tx_pause_on)); + seq_printf(m, "tx_pause_off\t%d\n", le32_to_cpu(counters->tx_pause_off)); + seq_printf(m, "tx_pause_all\t%d\n", le32_to_cpu(counters->tx_pause_all)); + seq_printf(m, "tx_deferred\t%d\n", le32_to_cpu(counters->tx_deferred)); + seq_printf(m, "tx_late_collision\t%d\n", le32_to_cpu(counters->tx_late_collision)); + seq_printf(m, "tx_all_collision\t%d\n", le32_to_cpu(counters->tx_all_collision)); + seq_printf(m, "tx_aborted32\t%d\n", le32_to_cpu(counters->tx_aborted32)); + seq_printf(m, "align_errors32\t%d\n", le32_to_cpu(counters->align_errors32)); + seq_printf(m, "rx_frame_too_long\t%d\n", le32_to_cpu(counters->rx_frame_too_long)); + seq_printf(m, "rx_runt\t%d\n", le32_to_cpu(counters->rx_runt)); + seq_printf(m, "rx_pause_on\t%d\n", le32_to_cpu(counters->rx_pause_on)); + seq_printf(m, "rx_pause_off\t%d\n", le32_to_cpu(counters->rx_pause_off)); + seq_printf(m, "rx_pause_all\t%d\n", le32_to_cpu(counters->rx_pause_all)); + seq_printf(m, "rx_unknown_opcode\t%d\n", le32_to_cpu(counters->rx_unknown_opcode)); + seq_printf(m, "rx_mac_error\t%d\n", le32_to_cpu(counters->rx_mac_error)); + seq_printf(m, "tx_underrun32\t%d\n", le32_to_cpu(counters->tx_underrun32)); + seq_printf(m, "rx_mac_missed\t%d\n", le32_to_cpu(counters->rx_mac_missed)); + seq_printf(m, "rx_tcam_dropped\t%d\n", le32_to_cpu(counters->rx_tcam_dropped)); + seq_printf(m, "tdu\t%d\n", le32_to_cpu(counters->tdu)); + seq_printf(m, "rdu\t%d\n", le32_to_cpu(counters->rdu)); + + seq_putc(m, '\n'); + +out_unlock: + rtnl_unlock(); + + return 0; +} + +static int proc_get_registers(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_MAC_REGS_SIZE; + u8 byte_rd; + struct rtl8125_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + + seq_puts(m, "\nDump MAC Registers\n"); + seq_puts(m, "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + seq_printf(m, "\n0x%02x:\t", n); + + for (i = 0; i < 16 && n < max; i++, n++) { + byte_rd = readb(ioaddr + n); + seq_printf(m, "%02x ", byte_rd); + } + } + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_pcie_phy(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_EPHY_REGS_SIZE/2; + u16 word_rd; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump PCIE PHY\n"); + seq_puts(m, "\nOffset\tValue\n------\t-----\n "); + + rtnl_lock(); + + for (n = 0; n < max;) { + seq_printf(m, "\n0x%02x:\t", n); + + for (i = 0; i < 8 && n < max; i++, n++) { + word_rd = rtl8125_ephy_read(tp, n); + seq_printf(m, "%04x ", word_rd); + } + } + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_eth_phy(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_PHY_REGS_SIZE/2; + u16 word_rd; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump Ethernet PHY\n"); + seq_puts(m, "\nOffset\tValue\n------\t-----\n "); + + rtnl_lock(); + + seq_puts(m, "\n####################page 0##################\n "); + rtl8125_mdio_write(tp, 0x1f, 0x0000); + for (n = 0; n < max;) { + seq_printf(m, "\n0x%02x:\t", n); + + for (i = 0; i < 8 && n < max; i++, n++) { + word_rd = rtl8125_mdio_read(tp, n); + seq_printf(m, "%04x ", word_rd); + } + } + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_extended_registers(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_ERI_REGS_SIZE; + u32 dword_rd; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump Extended Registers\n"); + seq_puts(m, "\nOffset\tValue\n------\t-----\n "); + + rtnl_lock(); + + for (n = 0; n < max;) { + seq_printf(m, "\n0x%02x:\t", n); + + for (i = 0; i < 4 && n < max; i++, n+=4) { + dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); + seq_printf(m, "%08x ", dword_rd); + } + } + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_pci_registers(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i, n, max = R8125_PCI_REGS_SIZE; + u32 dword_rd; + struct rtl8125_private *tp = netdev_priv(dev); + + seq_puts(m, "\nDump PCI Registers\n"); + seq_puts(m, "\nOffset\tValue\n------\t-----\n "); + + rtnl_lock(); + + for (n = 0; n < max;) { + seq_printf(m, "\n0x%03x:\t", n); + + for (i = 0; i < 4 && n < max; i++, n+=4) { + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + seq_printf(m, "%08x ", dword_rd); + } + } + + n = 0x110; + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); + n = 0x70c; + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); + + rtnl_unlock(); + + seq_putc(m, '\n'); + return 0; +} + +static int proc_get_temperature(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct rtl8125_private *tp = netdev_priv(dev); + u16 ts_digout, tj, fah; + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + seq_puts(m, "\nChip Temperature\n"); + break; + default: + seq_puts(m, "\nThis Chip Does Not Support Dump Temperature\n"); + break; + } + + rtnl_lock(); + ts_digout = rtl8125_read_thermal_sensor(tp); + rtnl_unlock(); + + tj = ts_digout / 2; + if (ts_digout <= 512) { + tj = ts_digout / 2; + seq_printf(m, "Cel:%d\n", tj); + fah = tj * (9/5) + 32; + seq_printf(m, "Fah:%d\n", fah); + } else { + tj = (512 - ((ts_digout / 2) - 512)) / 2; + seq_printf(m, "Cel:-%d\n", tj); + fah = tj * (9/5) + 32; + seq_printf(m, "Fah:-%d\n", fah); + } + + seq_putc(m, '\n'); + return 0; +} +#else + +static int proc_get_driver_variable(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump Driver Driver\n"); + + rtnl_lock(); + + len += snprintf(page + len, count - len, + "Variable\tValue\n----------\t-----\n"); + + len += snprintf(page + len, count - len, + "MODULENAME\t%s\n" + "driver version\t%s\n" + "mcfg\t%d\n" + "chipset\t%d\n" + "chipset_name\t%s\n" + "mtu\t%d\n" + "NUM_RX_DESC\t0x%x\n" + "cur_rx0\t0x%x\n" + "dirty_rx0\t0x%x\n" + "cur_rx1\t0x%x\n" + "dirty_rx1\t0x%x\n" + "cur_rx2\t0x%x\n" + "dirty_rx2\t0x%x\n" + "cur_rx3\t0x%x\n" + "dirty_rx3\t0x%x\n" + "NUM_TX_DESC\t0x%x\n" + "cur_tx0\t0x%x\n" + "dirty_tx0\t0x%x\n" + "cur_tx1\t0x%x\n" + "dirty_tx1\t0x%x\n" + "rx_buf_sz\t0x%x\n" + "esd_flag\t0x%x\n" + "pci_cfg_is_read\t0x%x\n" + "rtl8125_rx_config\t0x%x\n" + "cp_cmd\t0x%x\n" + "intr_mask\t0x%x\n" + "timer_intr_mask\t0x%x\n" + "wol_enabled\t0x%x\n" + "wol_opts\t0x%x\n" + "efuse_ver\t0x%x\n" + "eeprom_type\t0x%x\n" + "autoneg\t0x%x\n" + "duplex\t0x%x\n" + "speed\t%d\n" + "advertising\t0x%x\n" + "eeprom_len\t0x%x\n" + "cur_page\t0x%x\n" + "bios_setting\t0x%x\n" + "features\t0x%x\n" + "org_pci_offset_99\t0x%x\n" + "org_pci_offset_180\t0x%x\n" + "issue_offset_99_event\t0x%x\n" + "org_pci_offset_80\t0x%x\n" + "org_pci_offset_81\t0x%x\n" + "use_timer_interrrupt\t0x%x\n" + "HwIcVerUnknown\t0x%x\n" + "NotWrRamCodeToMicroP\t0x%x\n" + "NotWrMcuPatchCode\t0x%x\n" + "HwHasWrRamCodeToMicroP\t0x%x\n" + "sw_ram_code_ver\t0x%x\n" + "hw_ram_code_ver\t0x%x\n" + "rtk_enable_diag\t0x%x\n" + "ShortPacketSwChecksum\t0x%x\n" + "UseSwPaddingShortPkt\t0x%x\n" + "RequireAdcBiasPatch\t0x%x\n" + "AdcBiasPatchIoffset\t0x%x\n" + "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n" + "SwrCnt1msIni\t0x%x\n" + "HwSuppNowIsOobVer\t0x%x\n" + "HwFiberModeVer\t0x%x\n" + "HwFiberStat\t0x%x\n" + "HwSwitchMdiToFiber\t0x%x\n" + "NicCustLedValue\t0x%x\n" + "RequiredSecLanDonglePatch\t0x%x\n" + "HwSuppDashVer\t0x%x\n" + "DASH\t0x%x\n" + "dash_printer_enabled\t0x%x\n" + "HwSuppKCPOffloadVer\t0x%x\n" + "speed_mode\t0x%x\n" + "duplex_mode\t0x%x\n" + "autoneg_mode\t0x%x\n" + "advertising_mode\t0x%x\n" + "aspm\t0x%x\n" + "s5wol\t0x%x\n" + "s5_keep_curr_mac\t0x%x\n" + "eee_enable\t0x%x\n" + "hwoptimize\t0x%lx\n" + "proc_init_num\t0x%x\n" + "s0_magic_packet\t0x%x\n" + "HwSuppMagicPktVer\t0x%x\n" + "HwSuppLinkChgWakeUpVer\t0x%x\n" + "HwSuppD0SpeedUpVer\t0x%x\n" + "D0SpeedUpSpeed\t0x%x\n" + "HwSuppCheckPhyDisableModeVer\t0x%x\n" + "HwPkgDet\t0x%x\n" + "HwSuppTxNoCloseVer\t0x%x\n" + "EnableTxNoClose\t0x%x\n" + "NextHwDesCloPtr0\t0x%x\n" + "BeginHwDesCloPtr0\t0x%x\n" + "NextHwDesCloPtr1\t0x%x\n" + "BeginHwDesCloPtr1\t0x%x\n" + "InitRxDescType\t0x%x\n" + "RxDescLength\t0x%x\n" + "num_rx_rings\t0x%x\n" + "num_tx_rings\t0x%x\n" + "tot_rx_rings\t0x%x\n" + "tot_tx_rings\t0x%x\n" + "EnableRss\t0x%x\n" + "EnablePtp\t0x%x\n" + "ptp_master_mode\t0x%x\n" + "min_irq_nvecs\t0x%x\n" + "irq_nvecs\t0x%x\n" + "ring_lib_enabled\t0x%x\n" + "HwSuppIsrVer\t0x%x\n" + "HwCurrIsrVer\t0x%x\n" +#ifdef ENABLE_PTP_SUPPORT + "tx_hwtstamp_timeouts\t0x%x\n" + "tx_hwtstamp_skipped\t0x%x\n" +#endif + "random_mac\t0x%x\n" + "org_mac_addr\t%pM\n" +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + "perm_addr\t%pM\n" +#endif + "dev_addr\t%pM\n", + MODULENAME, + RTL8125_VERSION, + tp->mcfg, + tp->chipset, + rtl_chip_info[tp->chipset].name, + dev->mtu, + NUM_RX_DESC, + tp->rx_ring[0].cur_rx, + tp->rx_ring[0].dirty_rx, + tp->rx_ring[1].cur_rx, + tp->rx_ring[1].dirty_rx, + tp->rx_ring[2].cur_rx, + tp->rx_ring[2].dirty_rx, + tp->rx_ring[3].cur_rx, + tp->rx_ring[3].dirty_rx, + NUM_TX_DESC, + tp->tx_ring[0].cur_tx, + tp->tx_ring[0].dirty_tx, + tp->tx_ring[1].cur_tx, + tp->tx_ring[1].dirty_tx, + tp->rx_buf_sz, + tp->esd_flag, + tp->pci_cfg_is_read, + tp->rtl8125_rx_config, + tp->cp_cmd, + tp->intr_mask, + tp->timer_intr_mask, + tp->wol_enabled, + tp->wol_opts, + tp->efuse_ver, + tp->eeprom_type, + tp->autoneg, + tp->duplex, + tp->speed, + tp->advertising, + tp->eeprom_len, + tp->cur_page, + tp->bios_setting, + tp->features, + tp->org_pci_offset_99, + tp->org_pci_offset_180, + tp->issue_offset_99_event, + tp->org_pci_offset_80, + tp->org_pci_offset_81, + tp->use_timer_interrrupt, + tp->HwIcVerUnknown, + tp->NotWrRamCodeToMicroP, + tp->NotWrMcuPatchCode, + tp->HwHasWrRamCodeToMicroP, + tp->sw_ram_code_ver, + tp->hw_ram_code_ver, + tp->rtk_enable_diag, + tp->ShortPacketSwChecksum, + tp->UseSwPaddingShortPkt, + tp->RequireAdcBiasPatch, + tp->AdcBiasPatchIoffset, + tp->RequireAdjustUpsTxLinkPulseTiming, + tp->SwrCnt1msIni, + tp->HwSuppNowIsOobVer, + tp->HwFiberModeVer, + tp->HwFiberStat, + tp->HwSwitchMdiToFiber, + tp->NicCustLedValue, + tp->RequiredSecLanDonglePatch, + tp->HwSuppDashVer, + tp->DASH, + tp->dash_printer_enabled, + tp->HwSuppKCPOffloadVer, + speed_mode, + duplex_mode, + autoneg_mode, + advertising_mode, + aspm, + s5wol, + s5_keep_curr_mac, + tp->eee.eee_enabled, + hwoptimize, + proc_init_num, + s0_magic_packet, + tp->HwSuppMagicPktVer, + tp->HwSuppLinkChgWakeUpVer, + tp->HwSuppD0SpeedUpVer, + tp->D0SpeedUpSpeed, + tp->HwSuppCheckPhyDisableModeVer, + tp->HwPkgDet, + tp->HwSuppTxNoCloseVer, + tp->EnableTxNoClose, + tp->tx_ring[0].NextHwDesCloPtr, + tp->tx_ring[0].BeginHwDesCloPtr, + tp->tx_ring[1].NextHwDesCloPtr, + tp->tx_ring[1].BeginHwDesCloPtr, + tp->InitRxDescType, + tp->RxDescLength, + tp->num_rx_rings, + tp->num_tx_rings, + tp->tot_rx_rings, + tp->tot_tx_rings, + tp->EnableRss, + tp->EnablePtp, + tp->ptp_master_mode, + tp->min_irq_nvecs, + tp->irq_nvecs, + tp->ring_lib_enabled, + tp->HwSuppIsrVer, + tp->HwCurrIsrVer, +#ifdef ENABLE_PTP_SUPPORT + tp->tx_hwtstamp_timeouts, + tp->tx_hwtstamp_skipped, +#endif + tp->random_mac, + tp->org_mac_addr, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + dev->perm_addr, +#endif + dev->dev_addr + ); + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_tally_counter(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct rtl8125_private *tp = netdev_priv(dev); + struct rtl8125_counters *counters; + dma_addr_t paddr; + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump Tally Counter\n"); + + rtnl_lock(); + + counters = tp->tally_vaddr; + paddr = tp->tally_paddr; + if (!counters) { + len += snprintf(page + len, count - len, + "\nDump Tally Counter Fail\n"); + goto out_unlock; + } + + rtl8125_dump_tally_counter(tp, paddr); + + len += snprintf(page + len, count - len, + "Statistics\tValue\n----------\t-----\n"); + + len += snprintf(page + len, count - len, + "tx_packets\t%lld\n" + "rx_packets\t%lld\n" + "tx_errors\t%lld\n" + "rx_errors\t%d\n" + "rx_missed\t%d\n" + "align_errors\t%d\n" + "tx_one_collision\t%d\n" + "tx_multi_collision\t%d\n" + "rx_unicast\t%lld\n" + "rx_broadcast\t%lld\n" + "rx_multicast\t%d\n" + "tx_aborted\t%d\n" + "tx_underrun\t%d\n", + + "tx_octets\t%lld\n", + "rx_octets\t%lld\n", + "rx_multicast64\t%lld\n", + "tx_unicast64\t%lld\n", + "tx_broadcast64\t%lld\n", + "tx_multicast64\t%lld\n", + "tx_pause_on\t%d\n", + "tx_pause_off\t%d\n", + "tx_pause_all\t%d\n", + "tx_deferred\t%d\n", + "tx_late_collision\t%d\n", + "tx_all_collision\t%d\n", + "tx_aborted32\t%d\n", + "align_errors32\t%d\n", + "rx_frame_too_long\t%d\n", + "rx_runt\t%d\n", + "rx_pause_on\t%d\n", + "rx_pause_off\t%d\n", + "rx_pause_all\t%d\n", + "rx_unknown_opcode\t%d\n", + "rx_mac_error\t%d\n", + "tx_underrun32\t%d\n", + "rx_mac_missed\t%d\n", + "rx_tcam_dropped\t%d\n", + "tdu\t%d\n", + "rdu\t%d\n", + le64_to_cpu(counters->tx_packets), + le64_to_cpu(counters->rx_packets), + le64_to_cpu(counters->tx_errors), + le32_to_cpu(counters->rx_errors), + le16_to_cpu(counters->rx_missed), + le16_to_cpu(counters->align_errors), + le32_to_cpu(counters->tx_one_collision), + le32_to_cpu(counters->tx_multi_collision), + le64_to_cpu(counters->rx_unicast), + le64_to_cpu(counters->rx_broadcast), + le32_to_cpu(counters->rx_multicast), + le16_to_cpu(counters->tx_aborted), + le16_to_cpu(counters->tx_underrun), + + le64_to_cpu(counters->tx_octets), + le64_to_cpu(counters->rx_octets), + le64_to_cpu(counters->rx_multicast64), + le64_to_cpu(counters->tx_unicast64), + le64_to_cpu(counters->tx_broadcast64), + le64_to_cpu(counters->tx_multicast64), + le32_to_cpu(counters->tx_pause_on), + le32_to_cpu(counters->tx_pause_off), + le32_to_cpu(counters->tx_pause_all), + le32_to_cpu(counters->tx_deferred), + le32_to_cpu(counters->tx_late_collision), + le32_to_cpu(counters->tx_all_collision), + le32_to_cpu(counters->tx_aborted32), + le32_to_cpu(counters->align_errors32), + le32_to_cpu(counters->rx_frame_too_long), + le32_to_cpu(counters->rx_runt), + le32_to_cpu(counters->rx_pause_on), + le32_to_cpu(counters->rx_pause_off), + le32_to_cpu(counters->rx_pause_all), + le32_to_cpu(counters->rx_unknown_opcode), + le32_to_cpu(counters->rx_mac_error), + le32_to_cpu(counters->tx_underrun32), + le32_to_cpu(counters->rx_mac_missed), + le32_to_cpu(counters->rx_tcam_dropped), + le32_to_cpu(counters->tdu), + le32_to_cpu(counters->rdu), + ); + + len += snprintf(page + len, count - len, "\n"); +out_unlock: + rtnl_unlock(); + + *eof = 1; + return len; +} + +static int proc_get_registers(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_MAC_REGS_SIZE; + u8 byte_rd; + struct rtl8125_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump MAC Registers\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%02x:\t", + n); + + for (i = 0; i < 16 && n < max; i++, n++) { + byte_rd = readb(ioaddr + n); + len += snprintf(page + len, count - len, + "%02x ", + byte_rd); + } + } + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_pcie_phy(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_EPHY_REGS_SIZE/2; + u16 word_rd; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump PCIE PHY\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%02x:\t", + n); + + for (i = 0; i < 8 && n < max; i++, n++) { + word_rd = rtl8125_ephy_read(tp, n); + len += snprintf(page + len, count - len, + "%04x ", + word_rd); + } + } + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_eth_phy(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_PHY_REGS_SIZE/2; + u16 word_rd; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump Ethernet PHY\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + len += snprintf(page + len, count - len, + "\n####################page 0##################\n"); + rtl8125_mdio_write(tp, 0x1f, 0x0000); + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%02x:\t", + n); + + for (i = 0; i < 8 && n < max; i++, n++) { + word_rd = rtl8125_mdio_read(tp, n); + len += snprintf(page + len, count - len, + "%04x ", + word_rd); + } + } + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_extended_registers(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_ERI_REGS_SIZE; + u32 dword_rd; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump Extended Registers\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%02x:\t", + n); + + for (i = 0; i < 4 && n < max; i++, n+=4) { + dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); + len += snprintf(page + len, count - len, + "%08x ", + dword_rd); + } + } + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_pci_registers(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + int i, n, max = R8125_PCI_REGS_SIZE; + u32 dword_rd; + struct rtl8125_private *tp = netdev_priv(dev); + int len = 0; + + len += snprintf(page + len, count - len, + "\nDump PCI Registers\n" + "Offset\tValue\n------\t-----\n"); + + rtnl_lock(); + + for (n = 0; n < max;) { + len += snprintf(page + len, count - len, + "\n0x%03x:\t", + n); + + for (i = 0; i < 4 && n < max; i++, n+=4) { + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + len += snprintf(page + len, count - len, + "%08x ", + dword_rd); + } + } + + n = 0x110; + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + len += snprintf(page + len, count - len, + "\n0x%03x:\t%08x ", + n, + dword_rd); + n = 0x70c; + pci_read_config_dword(tp->pci_dev, n, &dword_rd); + len += snprintf(page + len, count - len, + "\n0x%03x:\t%08x ", + n, + dword_rd); + + rtnl_unlock(); + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} + +static int proc_get_temperature(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct rtl8125_private *tp = netdev_priv(dev); + u16 ts_digout, tj, fah; + int len = 0; + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + len += snprintf(page + len, count - len, + "\nChip Temperature\n"); + break; + default: + len += snprintf(page + len, count - len, + "\nThis Chip Does Not Support Dump Temperature\n"); + break; + } + + rtnl_lock(); + ts_digout = rtl8125_read_thermal_sensor(tp); + rtnl_unlock(); + + tj = ts_digout / 2; + if (ts_digout <= 512) { + tj = ts_digout / 2; + len += snprintf(page + len, count - len, + "Cel:%d\n", + tj); + fah = tj * (9/5) + 32; + len += snprintf(page + len, count - len, + "Fah:%d\n", + fah); + + } else { + tj = (512 - ((ts_digout / 2) - 512)) / 2; + len += snprintf(page + len, count - len, + "Cel:-%d\n", + tj); + fah = tj * (9/5) + 32; + len += snprintf(page + len, count - len, + "Fah:-%d\n", + fah); + } + + len += snprintf(page + len, count - len, "\n"); + + *eof = 1; + return len; +} +#endif +static void rtl8125_proc_module_init(void) +{ + //create /proc/net/r8125 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) + rtl8125_proc = proc_mkdir(MODULENAME, init_net.proc_net); +#else + rtl8125_proc = proc_mkdir(MODULENAME, proc_net); +#endif + if (!rtl8125_proc) + dprintk("cannot create %s proc entry \n", MODULENAME); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +/* + * seq_file wrappers for procfile show routines. + */ +static int rtl8125_proc_open(struct inode *inode, struct file *file) +{ + struct net_device *dev = proc_get_parent_data(inode); + int (*show)(struct seq_file *, void *) = PDE_DATA(inode); + + return single_open(file, show, dev); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +static const struct proc_ops rtl8125_proc_fops = { + .proc_open = rtl8125_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; +#else +static const struct file_operations rtl8125_proc_fops = { + .open = rtl8125_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +#endif + +/* + * Table of proc files we need to create. + */ +struct rtl8125_proc_file { + char name[12]; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + int (*show)(struct seq_file *, void *); +#else + int (*show)(char *, char **, off_t, int, int *, void *); +#endif +}; + +static const struct rtl8125_proc_file rtl8125_proc_files[] = { + { "driver_var", &proc_get_driver_variable }, + { "tally", &proc_get_tally_counter }, + { "registers", &proc_get_registers }, + { "pcie_phy", &proc_get_pcie_phy }, + { "eth_phy", &proc_get_eth_phy }, + { "ext_regs", &proc_get_extended_registers }, + { "pci_regs", &proc_get_pci_registers }, + { "temp", &proc_get_temperature }, + { "", NULL } +}; + +static void rtl8125_proc_init(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + const struct rtl8125_proc_file *f; + struct proc_dir_entry *dir; + + if (rtl8125_proc && !tp->proc_dir) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + dir = proc_mkdir_data(dev->name, 0, rtl8125_proc, dev); + if (!dir) { + printk("Unable to initialize /proc/net/%s/%s\n", + MODULENAME, dev->name); + return; + } + + tp->proc_dir = dir; + proc_init_num++; + + for (f = rtl8125_proc_files; f->name[0]; f++) { + if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir, + &rtl8125_proc_fops, f->show)) { + printk("Unable to initialize " + "/proc/net/%s/%s/%s\n", + MODULENAME, dev->name, f->name); + return; + } + } +#else + dir = proc_mkdir(dev->name, rtl8125_proc); + if (!dir) { + printk("Unable to initialize /proc/net/%s/%s\n", + MODULENAME, dev->name); + return; + } + + tp->proc_dir = dir; + proc_init_num++; + + for (f = rtl8125_proc_files; f->name[0]; f++) { + if (!create_proc_read_entry(f->name, S_IFREG | S_IRUGO, + dir, f->show, dev)) { + printk("Unable to initialize " + "/proc/net/%s/%s/%s\n", + MODULENAME, dev->name, f->name); + return; + } + } +#endif + } +} + +static void rtl8125_proc_remove(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->proc_dir) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + remove_proc_subtree(dev->name, rtl8125_proc); + proc_init_num--; + +#else + const struct rtl8125_proc_file *f; + struct rtl8125_private *tp = netdev_priv(dev); + + for (f = rtl8125_proc_files; f->name[0]; f++) + remove_proc_entry(f->name, tp->proc_dir); + + remove_proc_entry(dev->name, rtl8125_proc); + proc_init_num--; +#endif + tp->proc_dir = NULL; + } +} + +#endif //ENABLE_R8125_PROCFS + +static inline u16 map_phy_ocp_addr(u16 PageNum, u8 RegNum) +{ + u16 OcpPageNum = 0; + u8 OcpRegNum = 0; + u16 OcpPhyAddress = 0; + + if ( PageNum == 0 ) { + OcpPageNum = OCP_STD_PHY_BASE_PAGE + ( RegNum / 8 ); + OcpRegNum = 0x10 + ( RegNum % 8 ); + } else { + OcpPageNum = PageNum; + OcpRegNum = RegNum; + } + + OcpPageNum <<= 4; + + if ( OcpRegNum < 16 ) { + OcpPhyAddress = 0; + } else { + OcpRegNum -= 16; + OcpRegNum <<= 1; + + OcpPhyAddress = OcpPageNum + OcpRegNum; + } + + + return OcpPhyAddress; +} + +static void mdio_real_direct_write_phy_ocp(struct rtl8125_private *tp, + u16 RegAddr, + u16 value) +{ + u32 data32; + int i; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(RegAddr % 2); +#endif + data32 = RegAddr/2; + data32 <<= OCPR_Addr_Reg_shift; + data32 |= OCPR_Write | value; + + RTL_W32(tp, PHYOCP, data32); + for (i = 0; i < 100; i++) { + udelay(1); + + if (!(RTL_R32(tp, PHYOCP) & OCPR_Flag)) + break; + } +} + +static void mdio_direct_write_phy_ocp(struct rtl8125_private *tp, + u16 RegAddr, + u16 value) +{ + if (tp->rtk_enable_diag) return; + + mdio_real_direct_write_phy_ocp(tp, RegAddr, value); +} + +/* +static void rtl8125_mdio_write_phy_ocp(struct rtl8125_private *tp, + u16 PageNum, + u32 RegAddr, + u32 value) +{ + u16 ocp_addr; + + ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); + + mdio_direct_write_phy_ocp(tp, ocp_addr, value); +} +*/ + +static void rtl8125_mdio_real_write_phy_ocp(struct rtl8125_private *tp, + u16 PageNum, + u32 RegAddr, + u32 value) +{ + u16 ocp_addr; + + ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); + + mdio_real_direct_write_phy_ocp(tp, ocp_addr, value); +} + +static void mdio_real_write(struct rtl8125_private *tp, + u16 RegAddr, + u16 value) +{ + if (RegAddr == 0x1F) { + tp->cur_page = value; + return; + } + rtl8125_mdio_real_write_phy_ocp(tp, tp->cur_page, RegAddr, value); +} + +void rtl8125_mdio_write(struct rtl8125_private *tp, + u16 RegAddr, + u16 value) +{ + if (tp->rtk_enable_diag) return; + + mdio_real_write(tp, RegAddr, value); +} + +void rtl8125_mdio_prot_write(struct rtl8125_private *tp, + u32 RegAddr, + u32 value) +{ + mdio_real_write(tp, RegAddr, value); +} + +void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, + u32 RegAddr, + u32 value) +{ + mdio_real_direct_write_phy_ocp(tp, RegAddr, value); +} + +static u32 mdio_real_direct_read_phy_ocp(struct rtl8125_private *tp, + u16 RegAddr) +{ + u32 data32; + int i, value = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(RegAddr % 2); +#endif + data32 = RegAddr/2; + data32 <<= OCPR_Addr_Reg_shift; + + RTL_W32(tp, PHYOCP, data32); + for (i = 0; i < 100; i++) { + udelay(1); + + if (RTL_R32(tp, PHYOCP) & OCPR_Flag) + break; + } + value = RTL_R32(tp, PHYOCP) & OCPDR_Data_Mask; + + return value; +} + +static u32 mdio_direct_read_phy_ocp(struct rtl8125_private *tp, + u16 RegAddr) +{ + if (tp->rtk_enable_diag) return 0xffffffff; + + return mdio_real_direct_read_phy_ocp(tp, RegAddr); +} + +/* +static u32 rtl8125_mdio_read_phy_ocp(struct rtl8125_private *tp, + u16 PageNum, + u32 RegAddr) +{ + u16 ocp_addr; + + ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); + + return mdio_direct_read_phy_ocp(tp, ocp_addr); +} +*/ + +static u32 rtl8125_mdio_real_read_phy_ocp(struct rtl8125_private *tp, + u16 PageNum, + u32 RegAddr) +{ + u16 ocp_addr; + + ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); + + return mdio_real_direct_read_phy_ocp(tp, ocp_addr); +} + +static u32 mdio_real_read(struct rtl8125_private *tp, + u16 RegAddr) +{ + return rtl8125_mdio_real_read_phy_ocp(tp, tp->cur_page, RegAddr); +} + +u32 rtl8125_mdio_read(struct rtl8125_private *tp, + u16 RegAddr) +{ + if (tp->rtk_enable_diag) return 0xffffffff; + + return mdio_real_read(tp, RegAddr); +} + +u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, + u32 RegAddr) +{ + return mdio_real_read(tp, RegAddr); +} + +u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, + u32 RegAddr) +{ + return mdio_real_direct_read_phy_ocp(tp, RegAddr); +} + +static void ClearAndSetEthPhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) +{ + u16 PhyRegValue; + + PhyRegValue = rtl8125_mdio_read(tp, addr); + PhyRegValue &= ~clearmask; + PhyRegValue |= setmask; + rtl8125_mdio_write(tp, addr, PhyRegValue); +} + +void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) +{ + ClearAndSetEthPhyBit(tp, + addr, + mask, + 0 + ); +} + +void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) +{ + ClearAndSetEthPhyBit(tp, + addr, + 0, + mask + ); +} + +static void ClearAndSetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 clearmask, u16 setmask) +{ + u16 PhyRegValue; + + PhyRegValue = mdio_direct_read_phy_ocp(tp, addr); + PhyRegValue &= ~clearmask; + PhyRegValue |= setmask; + mdio_direct_write_phy_ocp(tp, addr, PhyRegValue); +} + +void ClearEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) +{ + ClearAndSetEthPhyOcpBit(tp, + addr, + mask, + 0 + ); +} + +void SetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) +{ + ClearAndSetEthPhyOcpBit(tp, + addr, + 0, + mask + ); +} + +void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value) +{ + u32 data32; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(reg_addr % 2); +#endif + + data32 = reg_addr/2; + data32 <<= OCPR_Addr_Reg_shift; + data32 += value; + data32 |= OCPR_Write; + + RTL_W32(tp, MACOCP, data32); +} + +u32 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr) +{ + u32 data32; + u16 data16 = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(reg_addr % 2); +#endif + + data32 = reg_addr/2; + data32 <<= OCPR_Addr_Reg_shift; + + RTL_W32(tp, MACOCP, data32); + data16 = (u16)RTL_R32(tp, MACOCP); + + return data16; +} + +#ifdef ENABLE_USE_FIRMWARE_FILE +static void mac_mcu_write(struct rtl8125_private *tp, u16 reg, u16 value) +{ + if (reg == 0x1f) { + tp->ocp_base = value << 4; + return; + } + + rtl8125_mac_ocp_write(tp, tp->ocp_base + reg, value); +} + +static u32 mac_mcu_read(struct rtl8125_private *tp, u16 reg) +{ + return rtl8125_mac_ocp_read(tp, tp->ocp_base + reg); +} +#endif + +static void +ClearAndSetMcuAccessRegBit( + struct rtl8125_private *tp, + u16 addr, + u16 clearmask, + u16 setmask +) +{ + u16 PhyRegValue; + + PhyRegValue = rtl8125_mac_ocp_read(tp, addr); + PhyRegValue &= ~clearmask; + PhyRegValue |= setmask; + rtl8125_mac_ocp_write(tp, addr, PhyRegValue); +} + +static void +ClearMcuAccessRegBit( + struct rtl8125_private *tp, + u16 addr, + u16 mask +) +{ + ClearAndSetMcuAccessRegBit(tp, + addr, + mask, + 0 + ); +} + +static void +SetMcuAccessRegBit( + struct rtl8125_private *tp, + u16 addr, + u16 mask +) +{ + ClearAndSetMcuAccessRegBit(tp, + addr, + 0, + mask + ); +} + +u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, const u32 base_address) +{ + return rtl8125_eri_read_with_oob_base_address(tp, addr, len, ERIAR_OOB, base_address); +} + +u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len) +{ + u32 value = 0; + + if (HW_DASH_SUPPORT_TYPE_2(tp)) + value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, NO_BASE_ADDRESS); + else if (HW_DASH_SUPPORT_TYPE_3(tp)) + value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, RTL8168FP_OOBMAC_BASE); + + return value; +} + +u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, const u32 base_address) +{ + return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, ERIAR_OOB, base_address); +} + +void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 value) +{ + if (HW_DASH_SUPPORT_TYPE_2(tp)) + rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, NO_BASE_ADDRESS); + else if (HW_DASH_SUPPORT_TYPE_3(tp)) + rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, RTL8168FP_OOBMAC_BASE); +} + +void rtl8125_oob_mutex_lock(struct rtl8125_private *tp) +{ + u8 reg_16, reg_a0; + u32 wait_cnt_0, wait_Cnt_1; + u16 ocp_reg_mutex_ib; + u16 ocp_reg_mutex_oob; + u16 ocp_reg_mutex_prio; + + if (!tp->DASH) return; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + ocp_reg_mutex_oob = 0x110; + ocp_reg_mutex_ib = 0x114; + ocp_reg_mutex_prio = 0x11C; + break; + } + + rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); + reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); + wait_cnt_0 = 0; + while(reg_16) { + reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); + if (reg_a0) { + rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); + reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); + wait_Cnt_1 = 0; + while(reg_a0) { + reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); + + wait_Cnt_1++; + + if (wait_Cnt_1 > 2000) + break; + }; + rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); + + } + reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); + + wait_cnt_0++; + + if (wait_cnt_0 > 2000) + break; + }; +} + +void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp) +{ + u16 ocp_reg_mutex_ib; + u16 ocp_reg_mutex_oob; + u16 ocp_reg_mutex_prio; + + if (!tp->DASH) return; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + ocp_reg_mutex_oob = 0x110; + ocp_reg_mutex_ib = 0x114; + ocp_reg_mutex_prio = 0x11C; + break; + } + + rtl8125_ocp_write(tp, ocp_reg_mutex_prio, 1, BIT_0); + rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); +} + +void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd) +{ + rtl8125_eri_write(tp, 0xE8, 1, cmd, ERIAR_ExGMAC); + + rtl8125_ocp_write(tp, 0x30, 1, 0x01); +} + +static int rtl8125_check_dash(struct rtl8125_private *tp) +{ + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + if (rtl8125_ocp_read(tp, 0x128, 1) & BIT_0) + return 1; + } + + return 0; +} + +void rtl8125_dash2_disable_tx(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + u16 WaitCnt; + u8 TmpUchar; + + //Disable oob Tx + RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) & ~( BIT_0 )); + WaitCnt = 0; + + //wait oob tx disable + do { + TmpUchar = RTL_CMAC_R8(tp, CMAC_IBISR0); + + if ( TmpUchar & ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE ) { + break; + } + + udelay( 50 ); + WaitCnt++; + } while(WaitCnt < 2000); + + //Clear ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE + RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0) | ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE); + } +} + +void rtl8125_dash2_enable_tx(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) | BIT_0); + } +} + +void rtl8125_dash2_disable_rx(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) & ~( BIT_0 )); + } +} + +void rtl8125_dash2_enable_rx(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) | BIT_0); + } +} + +static void rtl8125_dash2_disable_txrx(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + rtl8125_dash2_disable_tx( tp ); + rtl8125_dash2_disable_rx( tp ); + } +} + +static void rtl8125_driver_start(struct rtl8125_private *tp) +{ + if (!tp->DASH) + return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + int timeout; + u32 tmp_value; + + rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_START); + tmp_value = rtl8125_ocp_read(tp, 0x30, 1); + tmp_value |= BIT_0; + rtl8125_ocp_write(tp, 0x30, 1, tmp_value); + + for (timeout = 0; timeout < 10; timeout++) { + mdelay(10); + if (rtl8125_ocp_read(tp, 0x124, 1) & BIT_0) + break; + } + } +} + +static void rtl8125_driver_stop(struct rtl8125_private *tp) +{ + if (!tp->DASH) + return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + struct net_device *dev = tp->dev; + int timeout; + u32 tmp_value; + + rtl8125_dash2_disable_txrx(dev); + + rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_STOP); + tmp_value = rtl8125_ocp_read(tp, 0x30, 1); + tmp_value |= BIT_0; + rtl8125_ocp_write(tp, 0x30, 1, tmp_value); + + for (timeout = 0; timeout < 10; timeout++) { + mdelay(10); + if (!(rtl8125_ocp_read(tp, 0x124, 1) & BIT_0)) + break; + } + } +} + +void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value) +{ + int i; + + RTL_W32(tp, EPHYAR, + EPHYAR_Write | + (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift | + (value & EPHYAR_Data_Mask)); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed EPHY write */ + if (!(RTL_R32(tp, EPHYAR) & EPHYAR_Flag)) + break; + } + + udelay(20); +} + +u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr) +{ + int i; + u16 value = 0xffff; + + RTL_W32(tp, EPHYAR, + EPHYAR_Read | (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed EPHY read */ + if (RTL_R32(tp, EPHYAR) & EPHYAR_Flag) { + value = (u16) (RTL_R32(tp, EPHYAR) & EPHYAR_Data_Mask); + break; + } + } + + udelay(20); + + return value; +} + +static void ClearAndSetPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) +{ + u16 EphyValue; + + EphyValue = rtl8125_ephy_read(tp, addr); + EphyValue &= ~clearmask; + EphyValue |= setmask; + rtl8125_ephy_write(tp, addr, EphyValue); +} + +static void ClearPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 mask) +{ + ClearAndSetPCIePhyBit( tp, + addr, + mask, + 0 + ); +} + +static void SetPCIePhyBit( struct rtl8125_private *tp, u8 addr, u16 mask) +{ + ClearAndSetPCIePhyBit( tp, + addr, + 0, + mask + ); +} + +static u32 +rtl8125_csi_other_fun_read(struct rtl8125_private *tp, + u8 multi_fun_sel_bit, + u32 addr) +{ + u32 cmd; + int i; + u32 value = 0; + + cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); + + if (tp->mcfg == CFG_METHOD_DEFAULT) + multi_fun_sel_bit = 0; + + if (multi_fun_sel_bit > 7) + return 0xffffffff; + + cmd |= multi_fun_sel_bit << 16; + + RTL_W32(tp, CSIAR, cmd); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed CSI read */ + if (RTL_R32(tp, CSIAR) & CSIAR_Flag) { + value = (u32)RTL_R32(tp, CSIDR); + break; + } + } + + udelay(20); + + return value; +} + +static void +rtl8125_csi_other_fun_write(struct rtl8125_private *tp, + u8 multi_fun_sel_bit, + u32 addr, + u32 value) +{ + u32 cmd; + int i; + + RTL_W32(tp, CSIDR, value); + cmd = CSIAR_Write | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); + if (tp->mcfg == CFG_METHOD_DEFAULT) + multi_fun_sel_bit = 0; + + if ( multi_fun_sel_bit > 7 ) + return; + + cmd |= multi_fun_sel_bit << 16; + + RTL_W32(tp, CSIAR, cmd); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed CSI write */ + if (!(RTL_R32(tp, CSIAR) & CSIAR_Flag)) + break; + } + + udelay(20); +} + +static u32 +rtl8125_csi_read(struct rtl8125_private *tp, + u32 addr) +{ + u8 multi_fun_sel_bit; + + multi_fun_sel_bit = 0; + + return rtl8125_csi_other_fun_read(tp, multi_fun_sel_bit, addr); +} + +static void +rtl8125_csi_write(struct rtl8125_private *tp, + u32 addr, + u32 value) +{ + u8 multi_fun_sel_bit; + + multi_fun_sel_bit = 0; + + rtl8125_csi_other_fun_write(tp, multi_fun_sel_bit, addr, value); +} + +static u8 +rtl8125_csi_fun0_read_byte(struct rtl8125_private *tp, + u32 addr) +{ + u8 RetVal = 0; + + if (tp->mcfg == CFG_METHOD_DEFAULT) { + struct pci_dev *pdev = tp->pci_dev; + + pci_read_config_byte(pdev, addr, &RetVal); + } else { + u32 TmpUlong; + u16 RegAlignAddr; + u8 ShiftByte; + + RegAlignAddr = addr & ~(0x3); + ShiftByte = addr & (0x3); + TmpUlong = rtl8125_csi_other_fun_read(tp, 0, addr); + TmpUlong >>= (8*ShiftByte); + RetVal = (u8)TmpUlong; + } + + udelay(20); + + return RetVal; +} + +static void +rtl8125_csi_fun0_write_byte(struct rtl8125_private *tp, + u32 addr, + u8 value) +{ + if (tp->mcfg == CFG_METHOD_DEFAULT) { + struct pci_dev *pdev = tp->pci_dev; + + pci_write_config_byte(pdev, addr, value); + } else { + u32 TmpUlong; + u16 RegAlignAddr; + u8 ShiftByte; + + RegAlignAddr = addr & ~(0x3); + ShiftByte = addr & (0x3); + TmpUlong = rtl8125_csi_other_fun_read(tp, 0, RegAlignAddr); + TmpUlong &= ~(0xFF << (8*ShiftByte)); + TmpUlong |= (value << (8*ShiftByte)); + rtl8125_csi_other_fun_write( tp, 0, RegAlignAddr, TmpUlong ); + } + + udelay(20); +} + +u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, const u32 base_address) +{ + int i, val_shift, shift = 0; + u32 value1 = 0, value2 = 0, mask; + u32 eri_cmd; + const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); + + if (len > 4 || len <= 0) + return -1; + + while (len > 0) { + val_shift = addr % ERIAR_Addr_Align; + addr = addr & ~0x3; + + eri_cmd = ERIAR_Read | + transformed_base_address | + type << ERIAR_Type_shift | + ERIAR_ByteEn << ERIAR_ByteEn_shift | + (addr & 0x0FFF); + if (addr & 0xF000) { + u32 tmp; + + tmp = addr & 0xF000; + tmp >>= 12; + eri_cmd |= (tmp << 20) & 0x00F00000; + } + + RTL_W32(tp, ERIAR, eri_cmd); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed ERI read */ + if (RTL_R32(tp, ERIAR) & ERIAR_Flag) + break; + } + + if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; + else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; + else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; + else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; + + value1 = RTL_R32(tp, ERIDR) & mask; + value2 |= (value1 >> val_shift * 8) << shift * 8; + + if (len <= 4 - val_shift) { + len = 0; + } else { + len -= (4 - val_shift); + shift = 4 - val_shift; + addr += 4; + } + } + + udelay(20); + + return value2; +} + +u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type) +{ + return rtl8125_eri_read_with_oob_base_address(tp, addr, len, type, 0); +} + +int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, const u32 base_address) +{ + int i, val_shift, shift = 0; + u32 value1 = 0, mask; + u32 eri_cmd; + const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); + + if (len > 4 || len <= 0) + return -1; + + while (len > 0) { + val_shift = addr % ERIAR_Addr_Align; + addr = addr & ~0x3; + + if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; + else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; + else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; + else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; + + value1 = rtl8125_eri_read_with_oob_base_address(tp, addr, 4, type, base_address) & ~mask; + value1 |= ((value << val_shift * 8) >> shift * 8); + + RTL_W32(tp, ERIDR, value1); + + eri_cmd = ERIAR_Write | + transformed_base_address | + type << ERIAR_Type_shift | + ERIAR_ByteEn << ERIAR_ByteEn_shift | + (addr & 0x0FFF); + if (addr & 0xF000) { + u32 tmp; + + tmp = addr & 0xF000; + tmp >>= 12; + eri_cmd |= (tmp << 20) & 0x00F00000; + } + + RTL_W32(tp, ERIAR, eri_cmd); + + for (i = 0; i < 10; i++) { + udelay(100); + + /* Check if the RTL8125 has completed ERI write */ + if (!(RTL_R32(tp, ERIAR) & ERIAR_Flag)) + break; + } + + if (len <= 4 - val_shift) { + len = 0; + } else { + len -= (4 - val_shift); + shift = 4 - val_shift; + addr += 4; + } + } + + udelay(20); + + return 0; +} + +int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type) +{ + return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, type, NO_BASE_ADDRESS); +} + +static void +rtl8125_enable_rxdvgate(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_3); + mdelay(2); + break; + } +} + +static void +rtl8125_disable_rxdvgate(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_3); + mdelay(2); + break; + } +} + +static u8 +rtl8125_is_gpio_low(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u8 gpio_low = FALSE; + + switch (tp->HwSuppCheckPhyDisableModeVer) { + case 3: + if (!(rtl8125_mac_ocp_read(tp, 0xDC04) & BIT_13)) + gpio_low = TRUE; + break; + } + + if (gpio_low) + dprintk("gpio is low.\n"); + + return gpio_low; +} + +static u8 +rtl8125_is_phy_disable_mode_enabled(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u8 phy_disable_mode_enabled = FALSE; + + switch (tp->HwSuppCheckPhyDisableModeVer) { + case 3: + if (RTL_R8(tp, 0xF2) & BIT_5) + phy_disable_mode_enabled = TRUE; + break; + } + + if (phy_disable_mode_enabled) + dprintk("phy disable mode enabled.\n"); + + return phy_disable_mode_enabled; +} + +static u8 +rtl8125_is_in_phy_disable_mode(struct net_device *dev) +{ + u8 in_phy_disable_mode = FALSE; + + if (rtl8125_is_phy_disable_mode_enabled(dev) && rtl8125_is_gpio_low(dev)) + in_phy_disable_mode = TRUE; + + if (in_phy_disable_mode) + dprintk("Hardware is in phy disable mode.\n"); + + return in_phy_disable_mode; +} + +static bool +rtl8125_stop_all_request(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + for (i = 0; i < 20; i++) { + udelay(10); + if (!(RTL_R8(tp, ChipCmd) & StopReq)) break; + } + + if (i == 20) + return 0; + break; + } + + return 1; +} + +void +rtl8125_wait_txrx_fifo_empty(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_stop_all_request(dev); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + for (i = 0; i < 3000; i++) { + udelay(50); + if ((RTL_R8(tp, MCUCmd_reg) & (Txfifo_empty | Rxfifo_empty)) == (Txfifo_empty | Rxfifo_empty)) + break; + } + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + for (i = 0; i < 3000; i++) { + udelay(50); + if ((RTL_R16(tp, IntrMitigate) & (BIT_0 | BIT_1 | BIT_8)) == (BIT_0 | BIT_1 | BIT_8)) + break; + } + break; + } +} + +#ifdef ENABLE_DASH_SUPPORT + +static inline void +rtl8125_enable_dash2_interrupt(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBIMR0, ( ISRIMR_DASH_TYPE2_ROK | ISRIMR_DASH_TYPE2_TOK | ISRIMR_DASH_TYPE2_TDU | ISRIMR_DASH_TYPE2_RDU | ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE )); + } +} + +static inline void +rtl8125_disable_dash2_interrupt(struct rtl8125_private *tp) +{ + if (!tp->DASH) return; + + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBIMR0, 0); + } +} +#endif + +void +rtl8125_enable_hw_linkchg_interrupt(struct rtl8125_private *tp) +{ + switch (tp->HwCurrIsrVer) { + case 2: + RTL_W32(tp, IMR_V2_SET_REG_8125, ISRIMR_V2_LINKCHG); + break; + case 1: + RTL_W32(tp, tp->imr_reg[0], LinkChg | RTL_R32(tp, tp->imr_reg[0])); + break; + } + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + rtl8125_enable_dash2_interrupt(tp); +#endif +} + +static inline void +rtl8125_enable_hw_interrupt(struct rtl8125_private *tp) +{ + switch (tp->HwCurrIsrVer) { + case 2: + RTL_W32(tp, IMR_V2_SET_REG_8125, tp->intr_mask); + break; + case 1: + RTL_W32(tp, tp->imr_reg[0], tp->intr_mask); + + if (R8125_MULTI_RX_Q(tp)) { + int i; + for (i=1; inum_rx_rings; i++) + RTL_W16(tp, tp->imr_reg[i], other_q_intr_mask); + } + break; + } + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + rtl8125_enable_dash2_interrupt(tp); +#endif +} + +static inline void rtl8125_clear_hw_isr_v2(struct rtl8125_private *tp, + u32 message_id) +{ + RTL_W32(tp, ISR_V2_8125, BIT(message_id)); +} + +static inline void +rtl8125_disable_hw_interrupt(struct rtl8125_private *tp) +{ + if (tp->HwCurrIsrVer == 2) { + RTL_W32(tp, IMR_V2_CLEAR_REG_8125, 0xFFFFFFFF); + } else { + RTL_W32(tp, tp->imr_reg[0], 0x0000); + + if (R8125_MULTI_RX_Q(tp)) { + int i; + for (i=1; inum_rx_rings; i++) + RTL_W16(tp, tp->imr_reg[i], 0); + } + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + rtl8125_disable_dash2_interrupt(tp); +#endif + } +} + +static inline void +rtl8125_switch_to_hw_interrupt(struct rtl8125_private *tp) +{ + RTL_W32(tp, TIMER_INT0_8125, 0x0000); + + rtl8125_enable_hw_interrupt(tp); +} + +static inline void +rtl8125_switch_to_timer_interrupt(struct rtl8125_private *tp) +{ + if (tp->use_timer_interrrupt) { + RTL_W32(tp, TIMER_INT0_8125, timer_count); + RTL_W32(tp, TCTR0_8125, timer_count); + RTL_W32(tp, tp->imr_reg[0], tp->timer_intr_mask); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + rtl8125_enable_dash2_interrupt(tp); +#endif + } else { + rtl8125_switch_to_hw_interrupt(tp); + } +} + +static void +rtl8125_irq_mask_and_ack(struct rtl8125_private *tp) +{ + rtl8125_disable_hw_interrupt(tp); + + if (tp->HwCurrIsrVer == 2) { + RTL_W32(tp, ISR_V2_8125, 0xFFFFFFFF); + } else { +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + if (tp->dash_printer_enabled) { + RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0]) & + ~(ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); + } else { + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0)); + } + } + } else { + RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); + } +#else + RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); +#endif + if (R8125_MULTI_RX_Q(tp)) { + int i; + for (i=1; inum_rx_rings; i++) + RTL_W16(tp, tp->isr_reg[i], RTL_R16(tp, tp->isr_reg[i])); + } + } +} + +static void +rtl8125_nic_reset(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); + + rtl8125_enable_rxdvgate(dev); + + rtl8125_stop_all_request(dev); + + rtl8125_wait_txrx_fifo_empty(dev); + + mdelay(2); + + /* Soft reset the chip. */ + RTL_W8(tp, ChipCmd, CmdReset); + + /* Check that the chip has finished the reset. */ + for (i = 100; i > 0; i--) { + udelay(100); + if ((RTL_R8(tp, ChipCmd) & CmdReset) == 0) + break; + } +} + +static void +rtl8125_hw_set_interrupt_type(struct rtl8125_private *tp, u8 isr_ver) +{ + u8 tmp; + + switch (tp->HwSuppIsrVer) { + case 2: + tmp = RTL_R8(tp, INT_CFG0_8125); + tmp &= ~(INT_CFG0_ENABLE_8125); + if (isr_ver == 2) + tmp |= INT_CFG0_ENABLE_8125; + RTL_W8(tp, INT_CFG0_8125, tmp); + break; + } +} + +static void +rtl8125_hw_clear_timer_int(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W32(tp, TIMER_INT0_8125, 0x0000); + RTL_W32(tp, TIMER_INT1_8125, 0x0000); + RTL_W32(tp, TIMER_INT2_8125, 0x0000); + RTL_W32(tp, TIMER_INT3_8125, 0x0000); + break; + } +} + +static void +rtl8125_hw_clear_int_miti(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + switch (tp->HwSuppIntMitiVer) { + case 3: + //IntMITI_0-IntMITI_31 + for (i=0xA00; i<0xB00; i+=4) + RTL_W32(tp, i, 0x0000); + break; + case 4: + //IntMITI_0-IntMITI_15 + for (i = 0xA00; i < 0xA80; i += 4) + RTL_W32(tp, i, 0x0000); + + RTL_W8(tp, INT_CFG0_8125, RTL_R8(tp, INT_CFG0_8125) & + ~(INT_CFG0_TIMEOUT0_BYPASS_8125 | INT_CFG0_MITIGATION_BYPASS_8125)); + + RTL_W16(tp, INT_CFG1_8125, 0x0000); + break; + } +} + +void +rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, + u32 message_id, + u8 timer_intmiti_val) +{ + switch (tp->HwSuppIntMitiVer) { + case 4: + if (message_id < R8125_MAX_RX_QUEUES_VEC_V3) //ROK + RTL_W8(tp,INT_MITI_V2_0_RX + 8 * message_id, timer_intmiti_val); + else if (message_id == 16) //TOK + RTL_W8(tp,INT_MITI_V2_0_TX, timer_intmiti_val); + else if (message_id == 18) //TOK + RTL_W8(tp,INT_MITI_V2_1_TX, timer_intmiti_val); + break; + } +} + +void +rtl8125_hw_reset(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_lib_reset_prepare(tp); + + /* Disable interrupts */ + rtl8125_irq_mask_and_ack(tp); + + rtl8125_hw_clear_timer_int(dev); + + rtl8125_nic_reset(dev); +} + +static unsigned int +rtl8125_xmii_reset_pending(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + unsigned int retval; + + rtl8125_mdio_write(tp, 0x1f, 0x0000); + retval = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; + + return retval; +} + +static unsigned int +rtl8125_xmii_link_ok(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + unsigned int retval; + + retval = (RTL_R16(tp, PHYstatus) & LinkStatus) ? 1 : 0; + + return retval; +} + +static int +rtl8125_wait_phy_reset_complete(struct rtl8125_private *tp) +{ + int i, val; + + for (i = 0; i < 2500; i++) { + val = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; + if (!val) + return 0; + + mdelay(1); + } + + return -1; +} + +static void +rtl8125_xmii_reset_enable(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (rtl8125_is_in_phy_disable_mode(dev)) { + return; + } + + rtl8125_mdio_write(tp, 0x1f, 0x0000); + rtl8125_mdio_write(tp, MII_ADVERTISE, rtl8125_mdio_read(tp, MII_ADVERTISE) & + ~(ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL)); + rtl8125_mdio_write(tp, MII_CTRL1000, rtl8125_mdio_read(tp, MII_CTRL1000) & + ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL)); + mdio_direct_write_phy_ocp(tp, 0xA5D4, mdio_direct_read_phy_ocp(tp, 0xA5D4) & ~(RTK_ADVERTISE_2500FULL)); + rtl8125_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); + + if (rtl8125_wait_phy_reset_complete(tp) == 0) return; + + if (netif_msg_link(tp)) + printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); +} + +void +rtl8125_init_ring_indexes(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->HwSuppNumTxQueues; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + ring->dirty_tx = ring->cur_tx = 0; + ring->NextHwDesCloPtr = 0; + ring->BeginHwDesCloPtr = 0; + ring->index = i; + ring->priv = tp; + } + + for (i = 0; i < tp->HwSuppNumRxQueues; i++) { + struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; + ring->dirty_rx = ring->cur_rx = 0; + ring->index = i; + ring->priv = tp; + } + +#ifdef ENABLE_LIB_SUPPORT + for (i = 0; i < tp->HwSuppNumTxQueues; i++) { + struct rtl8125_ring *ring = &tp->lib_tx_ring[i]; + ring->direction = RTL8125_CH_DIR_TX; + ring->queue_num = i; + ring->private = tp; + } + + for (i = 0; i < tp->HwSuppNumRxQueues; i++) { + struct rtl8125_ring *ring = &tp->lib_rx_ring[i]; + ring->direction = RTL8125_CH_DIR_RX; + ring->queue_num = i; + ring->private = tp; + } +#endif +} + +static void +rtl8125_issue_offset_99_event(struct rtl8125_private *tp) +{ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE09A, rtl8125_mac_ocp_read(tp, 0xE09A) | BIT_0); + break; + } +} + +#ifdef ENABLE_DASH_SUPPORT +static void +NICChkTypeEnableDashInterrupt(struct rtl8125_private *tp) +{ + if (tp->DASH) { + // + // even disconnected, enable 3 dash interrupt mask bits for in-band/out-band communication + // + if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { + rtl8125_enable_dash2_interrupt(tp); + RTL_W16(tp, IntrMask, (ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); + } + } +} +#endif + +static int rtl8125_enable_eee_plus(struct rtl8125_private *tp) +{ + int ret; + + ret = 0; + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)|BIT_1); + break; + + default: +// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEEPlus\n"); + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static int rtl8125_disable_eee_plus(struct rtl8125_private *tp) +{ + int ret; + + ret = 0; + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)&~BIT_1); + break; + + default: +// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEEPlus\n"); + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static void +rtl8125_link_on_patch(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_hw_config(dev); + + if ((tp->mcfg == CFG_METHOD_2) && + netif_running(dev)) { + if (RTL_R16(tp, PHYstatus)&FullDup) + RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | (BIT_24 | BIT_25)) & ~BIT_19); + else + RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_25) & ~(BIT_19 | BIT_24)); + } + + if ((tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) && + (RTL_R8(tp, PHYstatus) & _10bps)) + rtl8125_enable_eee_plus(tp); + + rtl8125_hw_start(dev); + + netif_carrier_on(dev); + + netif_tx_wake_all_queues(dev); + + tp->phy_reg_aner = rtl8125_mdio_read(tp, MII_EXPANSION); + tp->phy_reg_anlpar = rtl8125_mdio_read(tp, MII_LPA); + tp->phy_reg_gbsr = rtl8125_mdio_read(tp, MII_STAT1000); + tp->phy_reg_status_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D6); +} + +static void +rtl8125_link_down_patch(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->phy_reg_aner = 0; + tp->phy_reg_anlpar = 0; + tp->phy_reg_gbsr = 0; + tp->phy_reg_status_2500 = 0; + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + rtl8125_disable_eee_plus(tp); + + netif_tx_stop_all_queues(dev); + + netif_carrier_off(dev); + + rtl8125_hw_reset(dev); + + rtl8125_tx_clear(tp); + + rtl8125_rx_clear(tp); + + rtl8125_init_ring(dev); + + rtl8125_enable_hw_linkchg_interrupt(tp); + + //rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + NICChkTypeEnableDashInterrupt(tp); + } +#endif +} + +static void +_rtl8125_check_link_status(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->link_ok(dev)) { + rtl8125_link_on_patch(dev); + + if (netif_msg_ifup(tp)) + printk(KERN_INFO PFX "%s: link up\n", dev->name); + } else { + if (netif_msg_ifdown(tp)) + printk(KERN_INFO PFX "%s: link down\n", dev->name); + + rtl8125_link_down_patch(dev); + } +} + +static void +rtl8125_check_link_status(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + _rtl8125_check_link_status(dev); + + tp->resume_not_chg_speed = 0; +} + +static void +rtl8125_link_option(u8 *aut, + u32 *spd, + u8 *dup, + u32 *adv) +{ + if ((*spd != SPEED_2500) && (*spd != SPEED_1000) && + (*spd != SPEED_100) && (*spd != SPEED_10)) + *spd = SPEED_2500; + + if ((*dup != DUPLEX_FULL) && (*dup != DUPLEX_HALF)) + *dup = DUPLEX_FULL; + + if ((*aut != AUTONEG_ENABLE) && (*aut != AUTONEG_DISABLE)) + *aut = AUTONEG_ENABLE; + + *adv &= (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_2500baseX_Full); + if (*adv == 0) + *adv = (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_2500baseX_Full); +} + +/* +static void +rtl8125_enable_ocp_phy_power_saving(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 val; + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + val = mdio_direct_read_phy_ocp(tp, 0xC416); + if (val != 0x0050) { + rtl8125_set_phy_mcu_patch_request(tp); + mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xC416, 0x0050); + rtl8125_clear_phy_mcu_patch_request(tp); + } + } +} +*/ + +static void +rtl8125_disable_ocp_phy_power_saving(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 val; + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + val = mdio_direct_read_phy_ocp(tp, 0xC416); + if (val != 0x0500) { + rtl8125_set_phy_mcu_patch_request(tp); + mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xC416, 0x0500); + rtl8125_clear_phy_mcu_patch_request(tp); + } + } +} + +static void +rtl8125_wait_ll_share_fifo_ready(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + for (i = 0; i < 10; i++) { + udelay(100); + if (RTL_R16(tp, 0xD2) & BIT_9) + break; + } +} + +static void +rtl8125_disable_pci_offset_99(struct rtl8125_private *tp) +{ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE032, rtl8125_mac_ocp_read(tp, 0xE032) & ~(BIT_0 | BIT_1)); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_csi_fun0_write_byte(tp, 0x99, 0x00); + break; + } +} + +static void +rtl8125_enable_pci_offset_99(struct rtl8125_private *tp) +{ + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_csi_fun0_write_byte(tp, 0x99, tp->org_pci_offset_99); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); + csi_tmp &= ~(BIT_0 | BIT_1); + if (tp->org_pci_offset_99 & (BIT_5 | BIT_6)) + csi_tmp |= BIT_1; + if (tp->org_pci_offset_99 & BIT_2) + csi_tmp |= BIT_0; + rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); + break; + } +} + +static void +rtl8125_init_pci_offset_99(struct rtl8125_private *tp) +{ + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xCDD0, 0x9003); + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE034); + csi_tmp |= (BIT_15 | BIT_14); + rtl8125_mac_ocp_write(tp, 0xE034, csi_tmp); + rtl8125_mac_ocp_write(tp, 0xCDD2, 0x889C); + rtl8125_mac_ocp_write(tp, 0xCDD8, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDD4, 0x8C30); + rtl8125_mac_ocp_write(tp, 0xCDDA, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDD6, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDDC, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDE8, 0x883E); + rtl8125_mac_ocp_write(tp, 0xCDEA, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDEC, 0x889C); + rtl8125_mac_ocp_write(tp, 0xCDEE, 0x9003); + rtl8125_mac_ocp_write(tp, 0xCDF0, 0x8C09); + rtl8125_mac_ocp_write(tp, 0xCDF2, 0x9003); + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); + csi_tmp |= (BIT_14); + rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE0A2); + csi_tmp |= (BIT_0); + rtl8125_mac_ocp_write(tp, 0xE0A2, csi_tmp); + break; + } + + rtl8125_enable_pci_offset_99(tp); +} + +static void +rtl8125_disable_pci_offset_180(struct rtl8125_private *tp) +{ + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); + csi_tmp &= 0xFF00; + rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); + break; + } +} + +static void +rtl8125_enable_pci_offset_180(struct rtl8125_private *tp) +{ + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE094); + csi_tmp &= 0x00FF; + rtl8125_mac_ocp_write(tp, 0xE094, csi_tmp); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); + csi_tmp &= 0xFF00; + csi_tmp |= BIT_2; + rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); + break; + } +} + +static void +rtl8125_init_pci_offset_180(struct rtl8125_private *tp) +{ + if (tp->org_pci_offset_180 & (BIT_0|BIT_1)) + rtl8125_enable_pci_offset_180(tp); + else + rtl8125_disable_pci_offset_180(tp); +} + +static void +rtl8125_set_pci_99_180_exit_driver_para(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_issue_offset_99_event(tp); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_disable_pci_offset_99(tp); + break; + } + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_disable_pci_offset_180(tp); + break; + } +} + +static void +rtl8125_enable_cfg9346_write(struct rtl8125_private *tp) +{ + RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) | Cfg9346_Unlock); +} + +static void +rtl8125_disable_cfg9346_write(struct rtl8125_private *tp) +{ + RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) & ~Cfg9346_Unlock); +} + +static void +rtl8125_enable_exit_l1_mask(struct rtl8125_private *tp) +{ + //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b111111, L1 Mask + SetMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); +} + +static void +rtl8125_disable_exit_l1_mask(struct rtl8125_private *tp) +{ + //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b000000, L1 Mask + ClearMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); +} + +static void +rtl8125_enable_extend_tally_couter(struct rtl8125_private *tp) +{ + switch (tp->HwSuppExtendTallyCounterVer) { + case 1: + SetMcuAccessRegBit(tp, 0xEA84, (BIT_1 | BIT_0)); + break; + } +} + +static void +rtl8125_disable_extend_tally_couter(struct rtl8125_private *tp) +{ + switch (tp->HwSuppExtendTallyCounterVer) { + case 1: + ClearMcuAccessRegBit(tp, 0xEA84, (BIT_1 | BIT_0)); + break; + } +} + +static void +rtl8125_hw_d3_para(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + RTL_W16(tp, RxMaxSize, RX_BUF_SIZE); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); + rtl8125_enable_cfg9346_write(tp); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + rtl8125_disable_cfg9346_write(tp); + break; + } + + rtl8125_disable_exit_l1_mask(tp); + +#ifdef ENABLE_REALWOW_SUPPORT + rtl8125_set_realwow_d3_para(dev); +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xEA18, 0x0064); + break; + } + + rtl8125_set_pci_99_180_exit_driver_para(dev); + + /*disable ocp phy power saving*/ + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + rtl8125_disable_ocp_phy_power_saving(dev); + + rtl8125_disable_rxdvgate(dev); + + rtl8125_disable_extend_tally_couter(tp); +} + +static void +rtl8125_enable_magic_packet(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppMagicPktVer) { + case WAKEUP_MAGIC_PACKET_V3: + rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) | BIT_0); + break; + } +} +static void +rtl8125_disable_magic_packet(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppMagicPktVer) { + case WAKEUP_MAGIC_PACKET_V3: + rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) & ~BIT_0); + break; + } +} + +static void +rtl8125_enable_linkchg_wakeup(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppLinkChgWakeUpVer) { + case 3: + RTL_W8(tp, Config3, RTL_R8(tp, Config3) | LinkUp); + ClearAndSetMcuAccessRegBit(tp, 0xE0C6, (BIT_5 | BIT_3 | BIT_2), (BIT_4 | BIT_1 | BIT_0)); + break; + } +} + +static void +rtl8125_disable_linkchg_wakeup(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppLinkChgWakeUpVer) { + case 3: + RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~LinkUp); + ClearMcuAccessRegBit(tp, 0xE0C6, (BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0)); + break; + } +} + +#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) + +static u32 +rtl8125_get_hw_wol(struct rtl8125_private *tp) +{ + u8 options; + u32 csi_tmp; + u32 wol_opts = 0; + + if (disable_pm_support) + goto out; + + options = RTL_R8(tp, Config1); + if (!(options & PMEnable)) + goto out; + + options = RTL_R8(tp, Config3); + if (options & LinkUp) + wol_opts |= WAKE_PHY; + + switch (tp->HwSuppMagicPktVer) { + case WAKEUP_MAGIC_PACKET_V3: + csi_tmp = rtl8125_mac_ocp_read(tp, 0xC0B6); + if (csi_tmp & BIT_0) + wol_opts |= WAKE_MAGIC; + break; + } + + options = RTL_R8(tp, Config5); + if (options & UWF) + wol_opts |= WAKE_UCAST; + if (options & BWF) + wol_opts |= WAKE_BCAST; + if (options & MWF) + wol_opts |= WAKE_MCAST; + +out: + return wol_opts; +} + +static void +rtl8125_enable_d0_speedup(struct rtl8125_private *tp) +{ + if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; + if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_DISABLE) return; + + if (tp->HwSuppD0SpeedUpVer == 1) { + u16 mac_ocp_data; + + RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_3); + + //speed up speed + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE10A); + mac_ocp_data &= ~(BIT_10 | BIT_9 | BIT_8 | BIT_7); + if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_2500) { + mac_ocp_data |= BIT_7; + } + rtl8125_mac_ocp_write(tp, 0xE10A, mac_ocp_data); + + //speed up flowcontrol + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE860); + mac_ocp_data |= (BIT_15 | BIT_14); + rtl8125_mac_ocp_write(tp, 0xE860, mac_ocp_data); + } +} + +static void +rtl8125_disable_d0_speedup(struct rtl8125_private *tp) +{ + if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; + + if (tp->HwSuppD0SpeedUpVer == 1) + RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_7); +} + +static void +rtl8125_set_hw_wol(struct net_device *dev, u32 wolopts) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i,tmp; + static struct { + u32 opt; + u16 reg; + u8 mask; + } cfg[] = { + { WAKE_PHY, Config3, LinkUp }, + { WAKE_UCAST, Config5, UWF }, + { WAKE_BCAST, Config5, BWF }, + { WAKE_MCAST, Config5, MWF }, + { WAKE_ANY, Config5, LanWake }, + { WAKE_MAGIC, Config3, MagicPacket }, + }; + + switch (tp->HwSuppMagicPktVer) { + case WAKEUP_MAGIC_PACKET_V3: + default: + tmp = ARRAY_SIZE(cfg) - 1; + + if (wolopts & WAKE_MAGIC) + rtl8125_enable_magic_packet(dev); + else + rtl8125_disable_magic_packet(dev); + break; + } + + rtl8125_enable_cfg9346_write(tp); + + for (i = 0; i < tmp; i++) { + u8 options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; + if (wolopts & cfg[i].opt) + options |= cfg[i].mask; + RTL_W8(tp, cfg[i].reg, options); + } + + switch (tp->HwSuppLinkChgWakeUpVer) { + case 3: + if (wolopts & WAKE_PHY) + rtl8125_enable_linkchg_wakeup(dev); + else + rtl8125_disable_linkchg_wakeup(dev); + break; + } + + rtl8125_disable_cfg9346_write(tp); +} + +static void +rtl8125_phy_restart_nway(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (rtl8125_is_in_phy_disable_mode(dev)) return; + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); +} + +static void +rtl8125_phy_setup_force_mode(struct net_device *dev, u32 speed, u8 duplex) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 bmcr_true_force = 0; + + if (rtl8125_is_in_phy_disable_mode(dev)) return; + + if ((speed == SPEED_10) && (duplex == DUPLEX_HALF)) { + bmcr_true_force = BMCR_SPEED10; + } else if ((speed == SPEED_10) && (duplex == DUPLEX_FULL)) { + bmcr_true_force = BMCR_SPEED10 | BMCR_FULLDPLX; + } else if ((speed == SPEED_100) && (duplex == DUPLEX_HALF)) { + bmcr_true_force = BMCR_SPEED100; + } else if ((speed == SPEED_100) && (duplex == DUPLEX_FULL)) { + bmcr_true_force = BMCR_SPEED100 | BMCR_FULLDPLX; + } else { + netif_err(tp, drv, dev, "Failed to set phy force mode!\n"); + return; + } + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, MII_BMCR, bmcr_true_force); +} + +static void +rtl8125_set_pci_pme(struct rtl8125_private *tp, int set) +{ + struct pci_dev *pdev = tp->pci_dev; + u16 pmc; + + if (!pdev->pm_cap) + return; + + pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmc); + pmc |= PCI_PM_CTRL_PME_STATUS; + if (set) + pmc |= PCI_PM_CTRL_PME_ENABLE; + else + pmc &= ~PCI_PM_CTRL_PME_ENABLE; + pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmc); +} + +static void +rtl8125_set_wol_link_speed(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int auto_nego; + int giga_ctrl; + int ctrl_2500; + u32 adv; + u16 anlpar; + u16 gbsr; + u16 status_2500; + u16 aner; + + if (tp->autoneg != AUTONEG_ENABLE) + goto exit; + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + + auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); + auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL + | ADVERTISE_100HALF | ADVERTISE_100FULL); + + giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000); + giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); + + ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); + ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); + + aner = anlpar = gbsr = status_2500 = 0; + if (tp->link_ok(dev)) { + aner = rtl8125_mdio_read(tp, MII_EXPANSION); + anlpar = rtl8125_mdio_read(tp, MII_LPA); + gbsr = rtl8125_mdio_read(tp, MII_STAT1000); + status_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D6); + } else { + if (netif_running(dev)) { + aner = tp->phy_reg_aner; + anlpar = tp->phy_reg_anlpar; + gbsr = tp->phy_reg_gbsr; + status_2500 = tp->phy_reg_status_2500; + } + } + + if ((aner | anlpar | gbsr | status_2500) == 0) { + int auto_nego_tmp = 0; + adv = tp->advertising; + if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) + auto_nego_tmp |= ADVERTISE_10HALF; + if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) + auto_nego_tmp |= ADVERTISE_10FULL; + if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) + auto_nego_tmp |= ADVERTISE_100HALF; + if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) + auto_nego_tmp |= ADVERTISE_100FULL; + + if (auto_nego_tmp == 0) goto exit; + + auto_nego |= auto_nego_tmp; + goto skip_check_lpa; + } + if (!(aner & EXPANSION_NWAY)) goto exit; + + adv = tp->advertising; + if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) + auto_nego |= ADVERTISE_10HALF; + else if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) + auto_nego |= ADVERTISE_10FULL; + else if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) + auto_nego |= ADVERTISE_100HALF; + else if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) + auto_nego |= ADVERTISE_100FULL; + else if (adv & ADVERTISED_1000baseT_Half && (gbsr & LPA_1000HALF)) + giga_ctrl |= ADVERTISE_1000HALF; + else if (adv & ADVERTISED_1000baseT_Full && (gbsr & LPA_1000FULL)) + giga_ctrl |= ADVERTISE_1000FULL; + else if (adv & ADVERTISED_2500baseX_Full && (status_2500 & RTK_LPA_ADVERTISE_2500FULL)) + ctrl_2500 |= RTK_ADVERTISE_2500FULL; + else + goto exit; + +skip_check_lpa: + if (tp->DASH) + auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); + +#ifdef CONFIG_DOWN_SPEED_100 + auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); +#endif + + rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); + rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); + mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); + + rtl8125_phy_restart_nway(dev); + +exit: + return; +} + +static bool +rtl8125_keep_wol_link_speed(struct net_device *dev, u8 from_suspend) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if ((from_suspend && !tp->link_ok(dev)) || + (!from_suspend && tp->resume_not_chg_speed)) + return 1; + + return 0; +} +static void +rtl8125_powerdown_pll(struct net_device *dev, u8 from_suspend) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->check_keep_link_speed = 0; + if (tp->wol_enabled == WOL_ENABLED || tp->DASH || tp->EnableKCPOffload) { + rtl8125_set_hw_wol(dev, tp->wol_opts); + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + rtl8125_enable_cfg9346_write(tp); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) | PMSTS_En); + rtl8125_disable_cfg9346_write(tp); + } + + /* Enable the PME and clear the status */ + rtl8125_set_pci_pme(tp, 1); + + if (rtl8125_keep_wol_link_speed(dev, from_suspend)) { + if (tp->wol_opts & WAKE_PHY) + tp->check_keep_link_speed = 1; + } else { + if (HW_SUPPORT_D0_SPEED_UP(tp)) { + rtl8125_enable_d0_speedup(tp); + tp->check_keep_link_speed = 1; + } + + rtl8125_set_wol_link_speed(dev); + } + + RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); + + return; + } + + if (tp->DASH) + return; + + rtl8125_phy_power_down(dev); + + if (!tp->HwIcVerUnknown) { + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~BIT_7); + break; + } + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_6); + break; + } +} + +static void rtl8125_powerup_pll(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | BIT_7 | BIT_6); + break; + } + + if (tp->resume_not_chg_speed) return; + + rtl8125_phy_power_up(dev); +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static void +rtl8125_get_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u8 options; + + wol->wolopts = 0; + + if (tp->mcfg == CFG_METHOD_DEFAULT || disable_pm_support) { + wol->supported = 0; + return; + } else { + wol->supported = WAKE_ANY; + } + + options = RTL_R8(tp, Config1); + if (!(options & PMEnable)) + return; + + wol->wolopts = tp->wol_opts; +} + +static int +rtl8125_set_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_DEFAULT || disable_pm_support) + return -EOPNOTSUPP; + + tp->wol_opts = wol->wolopts; + + tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; + + device_set_wakeup_enable(tp_to_dev(tp), wol->wolopts); + + return 0; +} + +static void +rtl8125_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct rtl8125_fw *rtl_fw = tp->rtl_fw; + + strcpy(info->driver, MODULENAME); + strcpy(info->version, RTL8125_VERSION); + strcpy(info->bus_info, pci_name(tp->pci_dev)); + info->regdump_len = R8125_REGS_DUMP_SIZE; + info->eedump_len = tp->eeprom_len; + BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); + if (rtl_fw) + strlcpy(info->fw_version, rtl_fw->version, + sizeof(info->fw_version)); +} + +static int +rtl8125_get_regs_len(struct net_device *dev) +{ + return R8125_REGS_DUMP_SIZE; +} +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +static void +rtl8125_set_d0_speedup_speed(struct rtl8125_private *tp) +{ + if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; + + tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_DISABLE; + if (tp->autoneg == AUTONEG_ENABLE) { + if (tp->speed == SPEED_2500) + tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_2500; + else if(tp->speed == SPEED_1000) + tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_1000; + } +} + +static int +rtl8125_set_speed_xmii(struct net_device *dev, + u8 autoneg, + u32 speed, + u8 duplex, + u32 adv) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int auto_nego = 0; + int giga_ctrl = 0; + int ctrl_2500 = 0; + int rc = -EINVAL; + + //Disable Giga Lite + ClearEthPhyOcpBit(tp, 0xA428, BIT_9); + ClearEthPhyOcpBit(tp, 0xA5EA, BIT_0); + + if (speed != SPEED_2500 && + (speed != SPEED_1000) && + (speed != SPEED_100) && + (speed != SPEED_10)) { + speed = SPEED_2500; + duplex = DUPLEX_FULL; + } + + giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000); + giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); + ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); + ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); + + if (autoneg == AUTONEG_ENABLE) { + /*n-way force*/ + auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); + auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL | + ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + + if (adv & ADVERTISED_10baseT_Half) + auto_nego |= ADVERTISE_10HALF; + if (adv & ADVERTISED_10baseT_Full) + auto_nego |= ADVERTISE_10FULL; + if (adv & ADVERTISED_100baseT_Half) + auto_nego |= ADVERTISE_100HALF; + if (adv & ADVERTISED_100baseT_Full) + auto_nego |= ADVERTISE_100FULL; + if (adv & ADVERTISED_1000baseT_Half) + giga_ctrl |= ADVERTISE_1000HALF; + if (adv & ADVERTISED_1000baseT_Full) + giga_ctrl |= ADVERTISE_1000FULL; + if (adv & ADVERTISED_2500baseX_Full) + ctrl_2500 |= RTK_ADVERTISE_2500FULL; + + //flow control + if (dev->mtu <= ETH_DATA_LEN && tp->fcpause == rtl8125_fc_full) + auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + + tp->phy_auto_nego_reg = auto_nego; + tp->phy_1000_ctrl_reg = giga_ctrl; + + tp->phy_2500_ctrl_reg = ctrl_2500; + + rtl8125_mdio_write(tp, 0x1f, 0x0000); + rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); + rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); + mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); + rtl8125_phy_restart_nway(dev); + mdelay(20); + } else { + /*true force*/ + if (speed == SPEED_10 || speed == SPEED_100) + rtl8125_phy_setup_force_mode(dev, speed, duplex); + else + goto out; + } + + tp->autoneg = autoneg; + tp->speed = speed; + tp->duplex = duplex; + tp->advertising = adv; + + rtl8125_set_d0_speedup_speed(tp); + + rc = 0; +out: + return rc; +} + +static int +rtl8125_set_speed(struct net_device *dev, + u8 autoneg, + u32 speed, + u8 duplex, + u32 adv) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret; + + if (tp->resume_not_chg_speed) return 0; + + ret = tp->set_speed(dev, autoneg, speed, duplex, adv); + + return ret; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static int +rtl8125_set_settings(struct net_device *dev, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + struct ethtool_cmd *cmd +#else + const struct ethtool_link_ksettings *cmd +#endif + ) +{ + int ret; + u8 autoneg; + u32 speed; + u8 duplex; + u32 supported, advertising; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + autoneg = cmd->autoneg; + speed = cmd->speed; + duplex = cmd->duplex; + supported = cmd->supported; + advertising = cmd->advertising; +#else + const struct ethtool_link_settings *base = &cmd->base; + autoneg = base->autoneg; + speed = base->speed; + duplex = base->duplex; + ethtool_convert_link_mode_to_legacy_u32(&supported, + cmd->link_modes.supported); + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.supported)) + supported |= ADVERTISED_2500baseX_Full; + if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.advertising)) + advertising |= ADVERTISED_2500baseX_Full; +#endif + if (advertising & ~supported) + return -EINVAL; + + ret = rtl8125_set_speed(dev, autoneg, speed, duplex, advertising); + + return ret; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) +static u32 +rtl8125_get_tx_csum(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 ret; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + ret = ((dev->features & NETIF_F_IP_CSUM) != 0); +#else + ret = ((dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) != 0); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + + return ret; +} + +static u32 +rtl8125_get_rx_csum(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 ret; + + ret = tp->cp_cmd & RxChkSum; + + return ret; +} + +static int +rtl8125_set_tx_csum(struct net_device *dev, + u32 data) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_DEFAULT) + return -EOPNOTSUPP; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + if (data) + dev->features |= NETIF_F_IP_CSUM; + else + dev->features &= ~NETIF_F_IP_CSUM; +#else + if (data) + dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + else + dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + + return 0; +} + +static int +rtl8125_set_rx_csum(struct net_device *dev, + u32 data) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_DEFAULT) + return -EOPNOTSUPP; + + if (data) + tp->cp_cmd |= RxChkSum; + else + tp->cp_cmd &= ~RxChkSum; + + RTL_W16(tp, CPlusCmd, tp->cp_cmd); + + return 0; +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +static u32 +rtl8125_rx_desc_opts1(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1; + else + return desc->opts1; +} + +static u32 +rtl8125_rx_desc_opts2(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2; + else + return desc->opts2; +} + +static void +rtl8125_clear_rx_desc_opts2(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2 = 0; + else + desc->opts2 = 0; +} + +#ifdef CONFIG_R8125_VLAN + +static inline u32 +rtl8125_tx_vlan_tag(struct rtl8125_private *tp, + struct sk_buff *skb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + return (tp->vlgrp && vlan_tx_tag_present(skb)) ? + TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) + return (vlan_tx_tag_present(skb)) ? + TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; +#else + return (skb_vlan_tag_present(skb)) ? + TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00; +#endif + + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + +static void +rtl8125_vlan_rx_register(struct net_device *dev, + struct vlan_group *grp) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->vlgrp = grp; + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + if (tp->vlgrp) { + tp->rtl8125_rx_config |= (EnableInnerVlan | EnableOuterVlan); + RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | (EnableInnerVlan | EnableOuterVlan)) + } else { + tp->rtl8125_rx_config &= ~(EnableInnerVlan | EnableOuterVlan); + RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(EnableInnerVlan | EnableOuterVlan)) + } + } +} + +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +static void +rtl8125_vlan_rx_kill_vid(struct net_device *dev, + unsigned short vid) +{ + struct rtl8125_private *tp = netdev_priv(dev); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) + if (tp->vlgrp) + tp->vlgrp->vlan_devices[vid] = NULL; +#else + vlan_group_set_device(tp->vlgrp, vid, NULL); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) +} +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + +static int +rtl8125_rx_vlan_skb(struct rtl8125_private *tp, + struct RxDesc *desc, + struct sk_buff *skb) +{ + u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); + int ret = -1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + if (tp->vlgrp && (opts2 & RxVlanTag)) { + rtl8125_rx_hwaccel_skb(skb, tp->vlgrp, + swab16(opts2 & 0xffff)); + ret = 0; + } +#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + if (opts2 & RxVlanTag) + __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); +#else + if (opts2 & RxVlanTag) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); +#endif + + rtl8125_clear_rx_desc_opts2(tp, desc); + return ret; +} + +#else /* !CONFIG_R8125_VLAN */ + +static inline u32 +rtl8125_tx_vlan_tag(struct rtl8125_private *tp, + struct sk_buff *skb) +{ + return 0; +} + +static int +rtl8125_rx_vlan_skb(struct rtl8125_private *tp, + struct RxDesc *desc, + struct sk_buff *skb) +{ + return -1; +} + +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) + +static netdev_features_t rtl8125_fix_features(struct net_device *dev, + netdev_features_t features) +{ + if (dev->mtu > MSS_MAX) + features &= ~NETIF_F_ALL_TSO; + if (dev->mtu > ETH_DATA_LEN) { + features &= ~NETIF_F_ALL_TSO; + features &= ~NETIF_F_ALL_CSUM; + } +#ifndef CONFIG_R8125_VLAN + features &= ~NETIF_F_ALL_CSUM; +#endif + + return features; +} + +static int rtl8125_hw_set_features(struct net_device *dev, + netdev_features_t features) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 rx_config; + + rx_config = RTL_R32(tp, RxConfig); + if (features & NETIF_F_RXALL) { + tp->rtl8125_rx_config |= (AcceptErr | AcceptRunt); + rx_config |= (AcceptErr | AcceptRunt); + } else { + tp->rtl8125_rx_config &= ~(AcceptErr | AcceptRunt); + rx_config &= ~(AcceptErr | AcceptRunt); + } + + if (features & NETIF_F_HW_VLAN_RX) { + tp->rtl8125_rx_config |= (EnableInnerVlan | EnableOuterVlan); + rx_config |= (EnableInnerVlan | EnableOuterVlan); + } else { + tp->rtl8125_rx_config &= ~(EnableInnerVlan | EnableOuterVlan); + rx_config &= ~(EnableInnerVlan | EnableOuterVlan); + } + + RTL_W32(tp, RxConfig, rx_config); + + if (features & NETIF_F_RXCSUM) + tp->cp_cmd |= RxChkSum; + else + tp->cp_cmd &= ~RxChkSum; + + RTL_W16(tp, CPlusCmd, tp->cp_cmd); + RTL_R16(tp, CPlusCmd); + + return 0; +} + +static int rtl8125_set_features(struct net_device *dev, + netdev_features_t features) +{ + features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX; + + rtl8125_hw_set_features(dev, features); + + return 0; +} + +#endif + +static void rtl8125_gset_xmii(struct net_device *dev, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + struct ethtool_cmd *cmd +#else + struct ethtool_link_ksettings *cmd +#endif + ) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 aner = tp->phy_reg_aner; + u16 anlpar = tp->phy_reg_anlpar; + u16 gbsr = tp->phy_reg_gbsr; + u16 status_2500 = tp->phy_reg_status_2500; + u32 lpa_adv = 0; + u16 status; + u8 autoneg, duplex; + u32 speed = 0; + u16 bmcr; + u32 supported, advertising; + u8 report_lpa = 0; + + supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_2500baseX_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause; + + advertising = ADVERTISED_TP; + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + bmcr = rtl8125_mdio_read(tp, MII_BMCR); + + if (bmcr & BMCR_ANENABLE) { + advertising |= ADVERTISED_Autoneg; + autoneg = AUTONEG_ENABLE; + + if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) + advertising |= ADVERTISED_10baseT_Half; + if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) + advertising |= ADVERTISED_10baseT_Full; + if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) + advertising |= ADVERTISED_100baseT_Half; + if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) + advertising |= ADVERTISED_100baseT_Full; + if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) + advertising |= ADVERTISED_1000baseT_Full; + if (tp->phy_2500_ctrl_reg & RTK_ADVERTISE_2500FULL) + advertising |= ADVERTISED_2500baseX_Full; + } else { + autoneg = AUTONEG_DISABLE; + } + + status = RTL_R16(tp, PHYstatus); + if (netif_running(dev) && (status & LinkStatus)) + report_lpa = 1; + + if (report_lpa) { + /*link on*/ + if (status & _2500bpsF) + speed = SPEED_2500; + else if (status & _1000bpsF) + speed = SPEED_1000; + else if (status & _100bps) + speed = SPEED_100; + else if (status & _10bps) + speed = SPEED_10; + + if (status & TxFlowCtrl) + advertising |= ADVERTISED_Asym_Pause; + + if (status & RxFlowCtrl) + advertising |= ADVERTISED_Pause; + + duplex = ((status & (_1000bpsF | _2500bpsF)) || (status & FullDup)) ? + DUPLEX_FULL : DUPLEX_HALF; + + /*link partner*/ + if (aner & EXPANSION_NWAY) + lpa_adv |= ADVERTISED_Autoneg; + if (anlpar & LPA_10HALF) + lpa_adv |= ADVERTISED_10baseT_Half; + if (anlpar & LPA_10FULL) + lpa_adv |= ADVERTISED_10baseT_Full; + if (anlpar & LPA_100HALF) + lpa_adv |= ADVERTISED_100baseT_Half; + if (anlpar & LPA_100FULL) + lpa_adv |= ADVERTISED_100baseT_Full; + if (anlpar & LPA_PAUSE_CAP) + lpa_adv |= ADVERTISED_Pause; + if (anlpar & LPA_PAUSE_ASYM) + lpa_adv |= ADVERTISED_Asym_Pause; + if (gbsr & LPA_1000HALF) + lpa_adv |= ADVERTISED_1000baseT_Half; + if (gbsr & LPA_1000FULL) + lpa_adv |= ADVERTISED_1000baseT_Full; + if (status_2500 & RTK_LPA_ADVERTISE_2500FULL) + lpa_adv |= ADVERTISED_2500baseX_Full; + } else { + /*link down*/ + speed = SPEED_UNKNOWN; + duplex = DUPLEX_UNKNOWN; + lpa_adv = 0; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + cmd->supported = supported; + cmd->advertising = advertising; + cmd->autoneg = autoneg; + cmd->speed = speed; + cmd->duplex = duplex; + cmd->port = PORT_TP; + cmd->lp_advertising = lpa_adv; +#else + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, + advertising); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, + lpa_adv); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) + if (supported & SUPPORTED_2500baseX_Full) { + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, + cmd->link_modes.supported, 0); + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.supported, 1); + } + if (advertising & ADVERTISED_2500baseX_Full) { + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, + cmd->link_modes.advertising, 0); + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.advertising, 1); + } + if (report_lpa) { + if (lpa_adv & ADVERTISED_2500baseX_Full) { + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, + cmd->link_modes.lp_advertising, 0); + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + cmd->link_modes.lp_advertising, 1); + } + if (status_2500 & RTK_LPA_ADVERTISE_5000FULL) + linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, + cmd->link_modes.lp_advertising, 1); + if (status_2500 & RTK_LPA_ADVERTISE_10000FULL) + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, + cmd->link_modes.lp_advertising, 1); + } +#endif + cmd->base.autoneg = autoneg; + cmd->base.speed = speed; + cmd->base.duplex = duplex; + cmd->base.port = PORT_TP; +#endif +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static int +rtl8125_get_settings(struct net_device *dev, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + struct ethtool_cmd *cmd +#else + struct ethtool_link_ksettings *cmd +#endif + ) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->get_settings(dev, cmd); + + return 0; +} + +static void rtl8125_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *p) +{ + struct rtl8125_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + unsigned int i; + u8 *data = p; + + if (regs->len < R8125_REGS_DUMP_SIZE) + return /* -EINVAL */; + + memset(p, 0, regs->len); + + for (i = 0; i < R8125_MAC_REGS_SIZE; i++) + *data++ = readb(ioaddr + i); + data = (u8*)p + 256; + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + for (i = 0; i < R8125_PHY_REGS_SIZE/2; i++) { + *(u16*)data = rtl8125_mdio_read(tp, i); + data += 2; + } + data = (u8*)p + 256 * 2; + + for (i = 0; i < R8125_EPHY_REGS_SIZE/2; i++) { + *(u16*)data = rtl8125_ephy_read(tp, i); + data += 2; + } + data = (u8*)p + 256 * 3; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + for (i = 0; i < R8125_ERI_REGS_SIZE; i+=4) { + *(u32*)data = rtl8125_eri_read(tp, i , 4, ERIAR_ExGMAC); + data += 4; + } + break; + } +} + +static void rtl8125_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + pause->autoneg = (tp->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + if (tp->fcpause == rtl8125_fc_rx_pause) + pause->rx_pause = 1; + else if (tp->fcpause == rtl8125_fc_tx_pause) + pause->tx_pause = 1; + else if (tp->fcpause == rtl8125_fc_full) { + pause->rx_pause = 1; + pause->tx_pause = 1; + } +} + +static int rtl8125_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct rtl8125_private *tp = netdev_priv(dev); + enum rtl8125_fc_mode newfc; + + if (pause->tx_pause || pause->rx_pause) + newfc = rtl8125_fc_full; + else + newfc = rtl8125_fc_none; + + if (tp->fcpause != newfc) { + tp->fcpause = newfc; + + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + } + + return 0; + +} + +static u32 +rtl8125_get_msglevel(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + return tp->msg_enable; +} + +static void +rtl8125_set_msglevel(struct net_device *dev, + u32 value) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + tp->msg_enable = value; +} + +static const char rtl8125_gstrings[][ETH_GSTRING_LEN] = { + /* legacy */ + "tx_packets", + "rx_packets", + "tx_errors", + "rx_errors", + "rx_missed", + "align_errors", + "tx_single_collisions", + "tx_multi_collisions", + "unicast", + "broadcast", + "multicast", + "tx_aborted", + "tx_underrun", + + /* extended */ + "tx_octets", + "rx_octets", + "rx_multicast64", + "tx_unicast64", + "tx_broadcast64", + "tx_multicast64", + "tx_pause_on", + "tx_pause_off", + "tx_pause_all", + "tx_deferred", + "tx_late_collision", + "tx_all_collision", + "tx_aborted32", + "align_errors32", + "rx_frame_too_long", + "rx_runt", + "rx_pause_on", + "rx_pause_off", + "rx_pause_all", + "rx_unknown_opcode", + "rx_mac_error", + "tx_underrun32", + "rx_mac_missed", + "rx_tcam_dropped", + "tdu", + "rdu", +}; +#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static int rtl8125_get_stats_count(struct net_device *dev) +{ + return ARRAY_SIZE(rtl8125_gstrings); +} +#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +#else +static int rtl8125_get_sset_count(struct net_device *dev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return ARRAY_SIZE(rtl8125_gstrings); + default: + return -EOPNOTSUPP; + } +} +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static void +rtl8125_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, + u64 *data) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct rtl8125_counters *counters; + dma_addr_t paddr; + + ASSERT_RTNL(); + + counters = tp->tally_vaddr; + paddr = tp->tally_paddr; + if (!counters) + return; + + rtl8125_dump_tally_counter(tp, paddr); + + data[0] = le64_to_cpu(counters->tx_packets); + data[1] = le64_to_cpu(counters->rx_packets); + data[2] = le64_to_cpu(counters->tx_errors); + data[3] = le32_to_cpu(counters->rx_errors); + data[4] = le16_to_cpu(counters->rx_missed); + data[5] = le16_to_cpu(counters->align_errors); + data[6] = le32_to_cpu(counters->tx_one_collision); + data[7] = le32_to_cpu(counters->tx_multi_collision); + data[8] = le64_to_cpu(counters->rx_unicast); + data[9] = le64_to_cpu(counters->rx_broadcast); + data[10] = le32_to_cpu(counters->rx_multicast); + data[11] = le16_to_cpu(counters->tx_aborted); + data[12] = le16_to_cpu(counters->tx_underrun); + + data[13] = le64_to_cpu(counters->tx_octets); + data[14] = le64_to_cpu(counters->rx_octets); + data[15] = le64_to_cpu(counters->rx_multicast64); + data[16] = le64_to_cpu(counters->tx_unicast64); + data[17] = le64_to_cpu(counters->tx_broadcast64); + data[18] = le64_to_cpu(counters->tx_multicast64); + data[19] = le32_to_cpu(counters->tx_pause_on); + data[20] = le32_to_cpu(counters->tx_pause_off); + data[21] = le32_to_cpu(counters->tx_pause_all); + data[22] = le32_to_cpu(counters->tx_deferred); + data[23] = le32_to_cpu(counters->tx_late_collision); + data[24] = le32_to_cpu(counters->tx_all_collision); + data[25] = le32_to_cpu(counters->tx_aborted32); + data[26] = le32_to_cpu(counters->align_errors32); + data[27] = le32_to_cpu(counters->rx_frame_too_long); + data[28] = le32_to_cpu(counters->rx_runt); + data[29] = le32_to_cpu(counters->rx_pause_on); + data[30] = le32_to_cpu(counters->rx_pause_off); + data[31] = le32_to_cpu(counters->rx_pause_all); + data[32] = le32_to_cpu(counters->rx_unknown_opcode); + data[33] = le32_to_cpu(counters->rx_mac_error); + data[34] = le32_to_cpu(counters->tx_underrun32); + data[35] = le32_to_cpu(counters->rx_mac_missed); + data[36] = le32_to_cpu(counters->rx_tcam_dropped); + data[37] = le32_to_cpu(counters->tdu); + data[38] = le32_to_cpu(counters->rdu); +} + +static void +rtl8125_get_strings(struct net_device *dev, + u32 stringset, + u8 *data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, *rtl8125_gstrings, sizeof(rtl8125_gstrings)); + break; + } +} +#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +static int rtl_get_eeprom_len(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + return tp->eeprom_len; +} + +static int rtl_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *buf) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i,j,ret; + int start_w, end_w; + int VPD_addr, VPD_data; + u32 *eeprom_buff; + u16 tmp; + + if (tp->eeprom_type == EEPROM_TYPE_NONE) { + dev_printk(KERN_DEBUG, tp_to_dev(tp), "Detect none EEPROM\n"); + return -EOPNOTSUPP; + } else if (eeprom->len == 0 || (eeprom->offset+eeprom->len) > tp->eeprom_len) { + dev_printk(KERN_DEBUG, tp_to_dev(tp), "Invalid parameter\n"); + return -EINVAL; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + VPD_addr = 0xD2; + VPD_data = 0xD4; + break; + } + + start_w = eeprom->offset >> 2; + end_w = (eeprom->offset + eeprom->len - 1) >> 2; + + eeprom_buff = kmalloc(sizeof(u32)*(end_w - start_w + 1), GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + rtl8125_enable_cfg9346_write(tp); + ret = -EFAULT; + for (i=start_w; i<=end_w; i++) { + pci_write_config_word(tp->pci_dev, VPD_addr, (u16)i*4); + ret = -EFAULT; + for (j = 0; j < 10; j++) { + udelay(400); + pci_read_config_word(tp->pci_dev, VPD_addr, &tmp); + if (tmp&0x8000) { + ret = 0; + break; + } + } + + if (ret) + break; + + pci_read_config_dword(tp->pci_dev, VPD_data, &eeprom_buff[i-start_w]); + } + rtl8125_disable_cfg9346_write(tp); + + if (!ret) + memcpy(buf, (u8 *)eeprom_buff + (eeprom->offset & 3), eeprom->len); + + kfree(eeprom_buff); + + return ret; +} + +#undef ethtool_op_get_link +#define ethtool_op_get_link _kc_ethtool_op_get_link +static u32 _kc_ethtool_op_get_link(struct net_device *dev) +{ + return netif_carrier_ok(dev) ? 1 : 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) +#undef ethtool_op_get_sg +#define ethtool_op_get_sg _kc_ethtool_op_get_sg +static u32 _kc_ethtool_op_get_sg(struct net_device *dev) +{ +#ifdef NETIF_F_SG + return (dev->features & NETIF_F_SG) != 0; +#else + return 0; +#endif +} + +#undef ethtool_op_set_sg +#define ethtool_op_set_sg _kc_ethtool_op_set_sg +static int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_DEFAULT) + return -EOPNOTSUPP; + +#ifdef NETIF_F_SG + if (data) + dev->features |= NETIF_F_SG; + else + dev->features &= ~NETIF_F_SG; +#endif + + return 0; +} +#endif + +static int rtl8125_enable_eee(struct rtl8125_private *tp) +{ + struct ethtool_eee *eee = &tp->eee; + u16 eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); + int ret; + + ret = 0; + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + RTL_W16(tp, EEE_TXIDLE_TIMER_8125, eee->tx_lpi_timer); + + SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); + SetMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); + + SetEthPhyOcpBit(tp, 0xA432, BIT_4); + SetEthPhyOcpBit(tp, 0xA5D0, eee_adv_t); + ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); + + ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); + ClearEthPhyOcpBit(tp, 0xA428, BIT_7); + ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); + break; + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W16(tp, EEE_TXIDLE_TIMER_8125, eee->tx_lpi_timer); + + SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); + + SetEthPhyOcpBit(tp, 0xA5D0, eee_adv_t); + if (eee->advertised & SUPPORTED_2500baseX_Full) + SetEthPhyOcpBit(tp, 0xA6D4, BIT_0); + else + ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); + + ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); + ClearEthPhyOcpBit(tp, 0xA428, BIT_7); + ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); + break; + default: +// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); + ret = -EOPNOTSUPP; + break; + } + + /*Advanced EEE*/ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_set_phy_mcu_patch_request(tp); + ClearMcuAccessRegBit(tp, 0xE052, BIT_0); + ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); + ClearEthPhyOcpBit(tp, 0xA430, BIT_15); + rtl8125_clear_phy_mcu_patch_request(tp); + break; + } + + return ret; +} + +static int rtl8125_disable_eee(struct rtl8125_private *tp) +{ + int ret; + + ret = 0; + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); + ClearMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); + + ClearEthPhyOcpBit(tp, 0xA432, BIT_4); + ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); + ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); + + ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); + ClearEthPhyOcpBit(tp, 0xA428, BIT_7); + ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); + break; + case CFG_METHOD_4: + case CFG_METHOD_5: + ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); + + ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); + ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); + + ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); + ClearEthPhyOcpBit(tp, 0xA428, BIT_7); + ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); + break; + default: +// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); + ret = -EOPNOTSUPP; + break; + } + + /*Advanced EEE*/ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_set_phy_mcu_patch_request(tp); + ClearMcuAccessRegBit(tp, 0xE052, BIT_0); + ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); + ClearEthPhyOcpBit(tp, 0xA430, BIT_15); + rtl8125_clear_phy_mcu_patch_request(tp); + break; + } + + return ret; +} + +static int rtl_nway_reset(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret, bmcr; + + if (unlikely(tp->rtk_enable_diag)) + return -EBUSY; + + /* if autoneg is off, it's an error */ + rtl8125_mdio_write(tp, 0x1F, 0x0000); + bmcr = rtl8125_mdio_read(tp, MII_BMCR); + + if (bmcr & BMCR_ANENABLE) { + bmcr |= BMCR_ANRESTART; + rtl8125_mdio_write(tp, MII_BMCR, bmcr); + ret = 0; + } else { + ret = -EINVAL; + } + + return ret; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +static u32 +rtl8125_tx_lpi_timer_to_us(struct rtl8125_private *tp , u32 tx_lpi_timer) +{ + u32 to_us; + u16 status; + + //2.5G : tx_lpi_timer * 3.2ns + //Giga: tx_lpi_timer * 8ns + //100M : tx_lpi_timer * 80ns + to_us = tx_lpi_timer * 80; + status = RTL_R16(tp, PHYstatus); + if (status & LinkStatus) { + /*link on*/ + if (status & _2500bpsF) + to_us = (tx_lpi_timer * 32) / 10; + else if (status & _1000bpsF) + to_us = tx_lpi_timer * 8; + } + + //ns to us + to_us /= 1000; + + return to_us; +} + +static int +rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) +{ + struct rtl8125_private *tp = netdev_priv(net); + struct ethtool_eee *eee = &tp->eee; + u32 lp, adv, tx_lpi_timer, supported = 0; + u16 val; + + if (unlikely(tp->rtk_enable_diag)) + return -EBUSY; + + /* Get Supported EEE */ + //val = mdio_direct_read_phy_ocp(tp, 0xA5C4); + //supported = mmd_eee_cap_to_ethtool_sup_t(val); + supported = eee->supported; + + /* Get advertisement EEE */ + val = mdio_direct_read_phy_ocp(tp, 0xA5D0); + adv = mmd_eee_adv_to_ethtool_adv_t(val); + + /* Get LP advertisement EEE */ + val = mdio_direct_read_phy_ocp(tp, 0xA5D2); + lp = mmd_eee_adv_to_ethtool_adv_t(val); + + /* Get EEE Tx LPI timer*/ + tx_lpi_timer = RTL_R16(tp, EEE_TXIDLE_TIMER_8125); + + val = rtl8125_mac_ocp_read(tp, 0xE040); + val &= BIT_1 | BIT_0; + + edata->eee_enabled = !!val; + edata->eee_active = !!(supported & adv & lp); + edata->supported = supported; + edata->advertised = adv; + edata->lp_advertised = lp; + edata->tx_lpi_enabled = edata->eee_enabled; + edata->tx_lpi_timer = rtl8125_tx_lpi_timer_to_us(tp, tx_lpi_timer); + + return 0; +} + +static int +rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata) +{ + struct rtl8125_private *tp = netdev_priv(net); + struct ethtool_eee *eee = &tp->eee; + u32 advertising; + int rc = 0; + + if (!HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp) || + tp->DASH) + return -EOPNOTSUPP; + + if (unlikely(tp->rtk_enable_diag)) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "Diag Enabled\n"); + rc = -EBUSY; + goto out; + } + + if (tp->autoneg != AUTONEG_ENABLE) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE requires autoneg\n"); + rc = -EINVAL; + goto out; + } + + if (edata->tx_lpi_enabled) { + if (edata->tx_lpi_timer > tp->max_jumbo_frame_size || + edata->tx_lpi_timer < ETH_MIN_MTU) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "Valid LPI timer range is %d to %d. \n", + ETH_MIN_MTU, tp->max_jumbo_frame_size); + rc = -EINVAL; + goto out; + } + } + + advertising = tp->advertising; + if (!edata->advertised) { + edata->advertised = advertising & eee->supported; + } else if (edata->advertised & ~advertising) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE advertised %x must be a subset of autoneg advertised speeds %x\n", + edata->advertised, advertising); + rc = -EINVAL; + goto out; + } + + if (edata->advertised & ~eee->supported) { + dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE advertised %x must be a subset of support %x\n", + edata->advertised, eee->supported); + rc = -EINVAL; + goto out; + } + + //tp->eee.eee_enabled = edata->eee_enabled; + //tp->eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(edata->advertised); + + dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE tx_lpi_timer %x must be a subset of support %x\n", + edata->tx_lpi_timer, eee->tx_lpi_timer); + + eee->advertised = edata->advertised; + eee->tx_lpi_enabled = edata->tx_lpi_enabled; + eee->tx_lpi_timer = edata->tx_lpi_timer; + eee->eee_enabled = edata->eee_enabled; + + if (eee->eee_enabled) + rtl8125_enable_eee(tp); + else + rtl8125_disable_eee(tp); + + rtl_nway_reset(net); + + return rc; + +out: + + return rc; +} +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) +static const struct ethtool_ops rtl8125_ethtool_ops = { + .get_drvinfo = rtl8125_get_drvinfo, + .get_regs_len = rtl8125_get_regs_len, + .get_link = ethtool_op_get_link, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) + .get_settings = rtl8125_get_settings, + .set_settings = rtl8125_set_settings, +#else + .get_link_ksettings = rtl8125_get_settings, + .set_link_ksettings = rtl8125_set_settings, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + .get_pauseparam = rtl8125_get_pauseparam, + .set_pauseparam = rtl8125_set_pauseparam, +#endif + .get_msglevel = rtl8125_get_msglevel, + .set_msglevel = rtl8125_set_msglevel, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) + .get_rx_csum = rtl8125_get_rx_csum, + .set_rx_csum = rtl8125_set_rx_csum, + .get_tx_csum = rtl8125_get_tx_csum, + .set_tx_csum = rtl8125_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, +#endif +#endif + .get_regs = rtl8125_get_regs, + .get_wol = rtl8125_get_wol, + .set_wol = rtl8125_set_wol, + .get_strings = rtl8125_get_strings, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + .get_stats_count = rtl8125_get_stats_count, +#else + .get_sset_count = rtl8125_get_sset_count, +#endif + .get_ethtool_stats = rtl8125_get_ethtool_stats, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) +#ifdef ETHTOOL_GPERMADDR + .get_perm_addr = ethtool_op_get_perm_addr, +#endif +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + .get_eeprom = rtl_get_eeprom, + .get_eeprom_len = rtl_get_eeprom_len, +#ifdef ENABLE_RSS_SUPPORT + .get_rxnfc = rtl8125_get_rxnfc, + .set_rxnfc = rtl8125_set_rxnfc, + .get_rxfh_indir_size = rtl8125_rss_indir_size, + .get_rxfh_key_size = rtl8125_get_rxfh_key_size, + .get_rxfh = rtl8125_get_rxfh, + .set_rxfh = rtl8125_set_rxfh, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) +#ifdef ENABLE_PTP_SUPPORT + .get_ts_info = rtl8125_get_ts_info, +#else + .get_ts_info = ethtool_op_get_ts_info, +#endif //ENABLE_PTP_SUPPORT +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + .get_eee = rtl_ethtool_get_eee, + .set_eee = rtl_ethtool_set_eee, +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ + .nway_reset = rtl_nway_reset, + +}; +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + +#if 0 + +static int rtl8125_enable_green_feature(struct rtl8125_private *tp) +{ + u16 gphy_val; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); + SetEthPhyOcpBit(tp, 0xA438, BIT_15); + rtl8125_mdio_write(tp, 0x00, 0x9200); + break; + default: + dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); + break; + } + + return 0; +} + +static int rtl8125_disable_green_feature(struct rtl8125_private *tp) +{ + u16 gphy_val; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); + ClearEthPhyOcpBit(tp, 0xA438, BIT_15); + rtl8125_mdio_write(tp, 0x00, 0x9200); + break; + default: + dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); + break; + } + + return 0; +} + +#endif + +static void rtl8125_get_mac_version(struct rtl8125_private *tp) +{ + u32 reg,val32; + u32 ICVerID; + + val32 = RTL_R32(tp, TxConfig); + reg = val32 & 0x7c800000; + ICVerID = val32 & 0x00700000; + + switch (reg) { + case 0x60800000: + if (ICVerID == 0x00000000) { + tp->mcfg = CFG_METHOD_2; + } else if (ICVerID == 0x100000) { + tp->mcfg = CFG_METHOD_3; + } else { + tp->mcfg = CFG_METHOD_3; + tp->HwIcVerUnknown = TRUE; + } + + tp->efuse_ver = EFUSE_SUPPORT_V4; + break; + case 0x64000000: + if (ICVerID == 0x00000000) { + tp->mcfg = CFG_METHOD_4; + } else if (ICVerID == 0x100000) { + tp->mcfg = CFG_METHOD_5; + } else { + tp->mcfg = CFG_METHOD_5; + tp->HwIcVerUnknown = TRUE; + } + + tp->efuse_ver = EFUSE_SUPPORT_V4; + break; + default: + printk("unknown chip version (%x)\n",reg); + tp->mcfg = CFG_METHOD_DEFAULT; + tp->HwIcVerUnknown = TRUE; + tp->efuse_ver = EFUSE_NOT_SUPPORT; + break; + } +} + +static void +rtl8125_print_mac_version(struct rtl8125_private *tp) +{ + int i; + for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { + if (tp->mcfg == rtl_chip_info[i].mcfg) { + dprintk("Realtek PCIe 2.5GbE Family Controller mcfg = %04d\n", + rtl_chip_info[i].mcfg); + return; + } + } + + dprintk("mac_version == Unknown\n"); +} + +static void +rtl8125_tally_counter_addr_fill(struct rtl8125_private *tp) +{ + if (!tp->tally_paddr) + return; + + RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); + RTL_W32(tp, CounterAddrLow, (u64)tp->tally_paddr & (DMA_BIT_MASK(32))); +} + +static void +rtl8125_tally_counter_clear(struct rtl8125_private *tp) +{ + if (!tp->tally_paddr) + return; + + RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); + RTL_W32(tp, CounterAddrLow, ((u64)tp->tally_paddr & (DMA_BIT_MASK(32))) | CounterReset); +} + +static void +rtl8125_clear_phy_ups_reg(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + ClearEthPhyOcpBit(tp, 0xA466, BIT_0); + break; + }; + ClearEthPhyOcpBit(tp, 0xA468, BIT_3 | BIT_1); +} + +static int +rtl8125_is_ups_resume(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + return (rtl8125_mac_ocp_read(tp, 0xD42C) & BIT_8); + + return 0; +} + +static void +rtl8125_clear_ups_resume_bit(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + rtl8125_mac_ocp_write(tp, 0xD408, rtl8125_mac_ocp_read(tp, 0xD408) & ~(BIT_8)); +} + +static void +rtl8125_wait_phy_ups_resume(struct net_device *dev, u16 PhyState) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 TmpPhyState; + int i=0; + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + do { + TmpPhyState = mdio_direct_read_phy_ocp(tp, 0xA420); + TmpPhyState &= 0x7; + mdelay(1); + i++; + } while ((i < 100) && (TmpPhyState != PhyState)); + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + WARN_ON_ONCE(i == 100); +#endif +} + +void +rtl8125_enable_now_is_oob(struct rtl8125_private *tp) +{ + if ( tp->HwSuppNowIsOobVer == 1 ) { + RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | Now_is_oob); + } +} + +void +rtl8125_disable_now_is_oob(struct rtl8125_private *tp) +{ + if ( tp->HwSuppNowIsOobVer == 1 ) { + RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) & ~Now_is_oob); + } +} + +static void +rtl8125_exit_oob(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 data16; + + RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys)); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_dash2_disable_txrx(dev); + break; + } + + if (tp->DASH) { + rtl8125_driver_stop(tp); + rtl8125_driver_start(tp); +#ifdef ENABLE_DASH_SUPPORT + DashHwInit(dev); +#endif + } + +#ifdef ENABLE_REALWOW_SUPPORT + rtl8125_realwow_hw_init(dev); +#else + //Disable realwow function + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xC0BC, 0x00FF); + break; + } +#endif //ENABLE_REALWOW_SUPPORT + + rtl8125_nic_reset(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_disable_now_is_oob(tp); + + data16 = rtl8125_mac_ocp_read(tp, 0xE8DE) & ~BIT_14; + rtl8125_mac_ocp_write(tp, 0xE8DE, data16); + rtl8125_wait_ll_share_fifo_ready(dev); + + rtl8125_mac_ocp_write(tp, 0xC0AA, 0x07D0); + rtl8125_mac_ocp_write(tp, 0xC0A6, 0x01B5); + rtl8125_mac_ocp_write(tp, 0xC01E, 0x5555); + + rtl8125_wait_ll_share_fifo_ready(dev); + break; + } + + //wait ups resume (phy state 2) + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + if (rtl8125_is_ups_resume(dev)) { + rtl8125_wait_phy_ups_resume(dev, 2); + rtl8125_clear_ups_resume_bit(dev); + rtl8125_clear_phy_ups_reg(dev); + } + break; + }; +} + +void +rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_enable_cfg9346_write(tp); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + rtl8125_disable_cfg9346_write(tp); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xFC38, 0x0000); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xFC28, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC2C, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC2E, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC30, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC32, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC34, 0x0000); + rtl8125_mac_ocp_write(tp, 0xFC36, 0x0000); + mdelay(3); + rtl8125_mac_ocp_write(tp, 0xFC26, 0x0000); + break; + } +} + +#ifndef ENABLE_USE_FIRMWARE_FILE +static void +rtl8125_set_mac_mcu_8125a_1(struct net_device *dev) +{ + rtl8125_hw_disable_mac_mcu_bps(dev); +} + +static void +rtl8125_set_mac_mcu_8125a_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 i; + static const u16 mcu_patch_code_8125a_2[] = { + 0xE008, 0xE01E, 0xE02E, 0xE054, 0xE057, 0xE059, 0xE0C2, 0xE0CB, 0x9996, + 0x49D1, 0xF005, 0x49D4, 0xF10A, 0x49D8, 0xF108, 0xC00F, 0x7100, 0x209C, + 0x249C, 0xC009, 0x9900, 0xE004, 0xC006, 0x1900, 0x9900, 0xC602, 0xBE00, + 0x5A48, 0xE0C2, 0x0004, 0xE10A, 0xC60F, 0x73C4, 0x49B3, 0xF106, 0x73C2, + 0xC608, 0xB406, 0xC609, 0xFF80, 0xC605, 0xB406, 0xC605, 0xFF80, 0x0544, + 0x0568, 0xE906, 0xCDE8, 0xC724, 0xC624, 0x9EE2, 0x1E01, 0x9EE0, 0x76E0, + 0x49E0, 0xF1FE, 0x76E6, 0x486D, 0x4868, 0x9EE4, 0x1E03, 0x9EE0, 0x76E0, + 0x49E0, 0xF1FE, 0xC615, 0x9EE2, 0x1E01, 0x9EE0, 0x76E0, 0x49E0, 0xF1FE, + 0x76E6, 0x486F, 0x9EE4, 0x1E03, 0x9EE0, 0x76E0, 0x49E0, 0xF1FE, 0x7196, + 0xC702, 0xBF00, 0x5A44, 0xEB0E, 0x0070, 0x00C3, 0x1BC0, 0xC602, 0xBE00, + 0x0E26, 0xC602, 0xBE00, 0x0EBA, 0x1501, 0xF02A, 0x1500, 0xF15D, 0xC661, + 0x75C8, 0x49D5, 0xF00A, 0x49D6, 0xF008, 0x49D7, 0xF006, 0x49D8, 0xF004, + 0x75D2, 0x49D9, 0xF150, 0xC553, 0x77A0, 0x75C8, 0x4855, 0x4856, 0x4857, + 0x4858, 0x48DA, 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, + 0x9DC8, 0x75D2, 0x4859, 0x9DD2, 0xC643, 0x75C0, 0x49D4, 0xF033, 0x49D0, + 0xF137, 0xE030, 0xC63A, 0x75C8, 0x49D5, 0xF00E, 0x49D6, 0xF00C, 0x49D7, + 0xF00A, 0x49D8, 0xF008, 0x75D2, 0x49D9, 0xF005, 0xC62E, 0x75C0, 0x49D7, + 0xF125, 0xC528, 0x77A0, 0xC627, 0x75C8, 0x4855, 0x4856, 0x4857, 0x4858, + 0x48DA, 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, 0x9DC8, + 0x75D2, 0x4859, 0x9DD2, 0xC616, 0x75C0, 0x4857, 0x9DC0, 0xC613, 0x75C0, + 0x49DA, 0xF003, 0x49D0, 0xF107, 0xC60B, 0xC50E, 0x48D9, 0x9DC0, 0x4859, + 0x9DC0, 0xC608, 0xC702, 0xBF00, 0x3AE0, 0xE860, 0xB400, 0xB5D4, 0xE908, + 0xE86C, 0x1200, 0xC409, 0x6780, 0x48F1, 0x8F80, 0xC404, 0xC602, 0xBE00, + 0x10AA, 0xC010, 0xEA7C, 0xC602, 0xBE00, 0x0000 + }; + + rtl8125_hw_disable_mac_mcu_bps(dev); + + for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8125a_2); i++) { + rtl8125_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8125a_2[i]); + } + + rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); + + rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0540); + rtl8125_mac_ocp_write(tp, 0xFC2E, 0x0E24); + rtl8125_mac_ocp_write(tp, 0xFC30, 0x0EB8); + rtl8125_mac_ocp_write(tp, 0xFC32, 0x3A5C); + rtl8125_mac_ocp_write(tp, 0xFC34, 0x10A8); + + rtl8125_mac_ocp_write(tp, 0xFC48, 0x007A); +} + +static void +rtl8125_set_mac_mcu_8125b_1(struct net_device *dev) +{ + rtl8125_hw_disable_mac_mcu_bps(dev); +} + +static void +rtl8125_set_mac_mcu_8125b_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 i; + static const u16 mcu_patch_code_8125b_2[] = { + 0xE010, 0xE01B, 0xE026, 0xE037, 0xE03D, 0xE057, 0xE05B, 0xE05F, 0xE061, + 0xE063, 0xE065, 0xE067, 0xE069, 0xE06B, 0xE06D, 0xE06F, 0x740A, 0x4846, + 0x4847, 0x9C0A, 0xC607, 0x74C0, 0x48C6, 0x9CC0, 0xC602, 0xBE00, 0x13F0, + 0xE054, 0x72CA, 0x4826, 0x4827, 0x9ACA, 0xC607, 0x72C0, 0x48A6, 0x9AC0, + 0xC602, 0xBE00, 0x081C, 0xE054, 0xC60F, 0x74C4, 0x49CC, 0xF109, 0xC60C, + 0x74CA, 0x48C7, 0x9CCA, 0xC609, 0x74C0, 0x4846, 0x9CC0, 0xC602, 0xBE00, + 0x2494, 0xE092, 0xE0C0, 0xE054, 0x7420, 0x48C0, 0x9C20, 0x7444, 0xC602, + 0xBE00, 0x12DC, 0x733A, 0x21B5, 0x25BC, 0x1304, 0xF111, 0x1B12, 0x1D2A, + 0x3168, 0x3ADA, 0x31AB, 0x1A00, 0x9AC0, 0x1300, 0xF1FB, 0x7620, 0x236E, + 0x276F, 0x1A3C, 0x22A1, 0x41B5, 0x9EE2, 0x76E4, 0x486F, 0x9EE4, 0xC602, + 0xBE00, 0x4A26, 0x733A, 0x49BB, 0xC602, 0xBE00, 0x47A2, 0x48C1, 0x48C2, + 0xC5C3, 0xBD00, 0x0A52, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, + 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, + 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, + 0xC602, 0xBE00, 0x0000 + }; + + rtl8125_hw_disable_mac_mcu_bps(dev); + + for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8125b_2); i++) { + rtl8125_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8125b_2[i]); + } + + rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); + + rtl8125_mac_ocp_write(tp, 0xFC28, 0x13E6); + rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0812); + rtl8125_mac_ocp_write(tp, 0xFC2C, 0x248C); + rtl8125_mac_ocp_write(tp, 0xFC2E, 0x12DA); + rtl8125_mac_ocp_write(tp, 0xFC30, 0x4A20); + rtl8125_mac_ocp_write(tp, 0xFC32, 0x47A0); + rtl8125_mac_ocp_write(tp, 0xFC34, 0x0A46); + + rtl8125_mac_ocp_write(tp, 0xFC48, 0x007F); +} + +static void +rtl8125_hw_mac_mcu_config(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->NotWrMcuPatchCode == TRUE) return; + + switch (tp->mcfg) { + case CFG_METHOD_2: + rtl8125_set_mac_mcu_8125a_1(dev); + break; + case CFG_METHOD_3: + rtl8125_set_mac_mcu_8125a_2(dev); + break; + case CFG_METHOD_4: + rtl8125_set_mac_mcu_8125b_1(dev); + break; + case CFG_METHOD_5: + rtl8125_set_mac_mcu_8125b_2(dev); + break; + } +} +#endif + +#ifdef ENABLE_USE_FIRMWARE_FILE +static void rtl8125_release_firmware(struct rtl8125_private *tp) +{ + if (tp->rtl_fw) { + rtl8125_fw_release_firmware(tp->rtl_fw); + kfree(tp->rtl_fw); + tp->rtl_fw = NULL; + } +} + +void rtl8125_apply_firmware(struct rtl8125_private *tp) +{ + /* TODO: release firmware if rtl_fw_write_firmware signals failure. */ + if (tp->rtl_fw) { + rtl8125_fw_write_firmware(tp, tp->rtl_fw); + /* At least one firmware doesn't reset tp->ocp_base. */ + tp->ocp_base = OCP_STD_PHY_BASE; + + /* PHY soft reset may still be in progress */ + //phy_read_poll_timeout(tp->phydev, MII_BMCR, val, + // !(val & BMCR_RESET), + // 50000, 600000, true); + rtl8125_wait_phy_reset_complete(tp); + + tp->hw_ram_code_ver = rtl8125_get_hw_phy_mcu_code_ver(tp); + tp->sw_ram_code_ver = tp->hw_ram_code_ver; + tp->HwHasWrRamCodeToMicroP = TRUE; + } +} +#endif + +static void +rtl8125_hw_init(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 csi_tmp; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_enable_cfg9346_write(tp); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + rtl8125_disable_cfg9346_write(tp); + RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); + break; + } + + //Disable UPS + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xD40A, rtl8125_mac_ocp_read( tp, 0xD40A) & ~(BIT_4)); + break; + } + +#ifndef ENABLE_USE_FIRMWARE_FILE + if (!tp->rtl_fw) + rtl8125_hw_mac_mcu_config(dev); +#endif + + /*disable ocp phy power saving*/ + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) + rtl8125_disable_ocp_phy_power_saving(dev); + + //Set PCIE uncorrectable error status mask pcie 0x108 + csi_tmp = rtl8125_csi_read(tp, 0x108); + csi_tmp |= BIT_20; + rtl8125_csi_write(tp, 0x108, csi_tmp); + + rtl8125_enable_cfg9346_write(tp); + rtl8125_disable_linkchg_wakeup(dev); + rtl8125_disable_cfg9346_write(tp); + rtl8125_disable_magic_packet(dev); + rtl8125_disable_d0_speedup(tp); + rtl8125_set_pci_pme(tp, 0); + if (s0_magic_packet == 1) + rtl8125_enable_magic_packet(dev); + +#ifdef ENABLE_USE_FIRMWARE_FILE + if (tp->rtl_fw && + !tp->resume_not_chg_speed && + !(HW_DASH_SUPPORT_TYPE_3(tp) && + tp->HwPkgDet == 0x06)) + rtl8125_apply_firmware(tp); +#endif +} + +static void +rtl8125_hw_ephy_config(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + rtl8125_ephy_write(tp, 0x01, 0xA812); + rtl8125_ephy_write(tp, 0x09, 0x520C); + rtl8125_ephy_write(tp, 0x04, 0xD000); + rtl8125_ephy_write(tp, 0x0D, 0xF702); + rtl8125_ephy_write(tp, 0x0A, 0x8653); + rtl8125_ephy_write(tp, 0x06, 0x001E); + rtl8125_ephy_write(tp, 0x08, 0x3595); + rtl8125_ephy_write(tp, 0x20, 0x9455); + rtl8125_ephy_write(tp, 0x21, 0x99FF); + rtl8125_ephy_write(tp, 0x02, 0x6046); + rtl8125_ephy_write(tp, 0x29, 0xFE00); + rtl8125_ephy_write(tp, 0x23, 0xAB62); + + rtl8125_ephy_write(tp, 0x41, 0xA80C); + rtl8125_ephy_write(tp, 0x49, 0x520C); + rtl8125_ephy_write(tp, 0x44, 0xD000); + rtl8125_ephy_write(tp, 0x4D, 0xF702); + rtl8125_ephy_write(tp, 0x4A, 0x8653); + rtl8125_ephy_write(tp, 0x46, 0x001E); + rtl8125_ephy_write(tp, 0x48, 0x3595); + rtl8125_ephy_write(tp, 0x60, 0x9455); + rtl8125_ephy_write(tp, 0x61, 0x99FF); + rtl8125_ephy_write(tp, 0x42, 0x6046); + rtl8125_ephy_write(tp, 0x69, 0xFE00); + rtl8125_ephy_write(tp, 0x63, 0xAB62); + break; + case CFG_METHOD_3: + rtl8125_ephy_write(tp, 0x04, 0xD000); + rtl8125_ephy_write(tp, 0x0A, 0x8653); + rtl8125_ephy_write(tp, 0x23, 0xAB66); + rtl8125_ephy_write(tp, 0x20, 0x9455); + rtl8125_ephy_write(tp, 0x21, 0x99FF); + rtl8125_ephy_write(tp, 0x29, 0xFE04); + + rtl8125_ephy_write(tp, 0x44, 0xD000); + rtl8125_ephy_write(tp, 0x4A, 0x8653); + rtl8125_ephy_write(tp, 0x63, 0xAB66); + rtl8125_ephy_write(tp, 0x60, 0x9455); + rtl8125_ephy_write(tp, 0x61, 0x99FF); + rtl8125_ephy_write(tp, 0x69, 0xFE04); + + ClearAndSetPCIePhyBit(tp, + 0x2A, + (BIT_14 | BIT_13 | BIT_12), + (BIT_13 | BIT_12) + ); + ClearPCIePhyBit(tp, 0x19, BIT_6); + SetPCIePhyBit(tp, 0x1B, (BIT_11 | BIT_10 | BIT_9)); + ClearPCIePhyBit(tp, 0x1B, (BIT_14 | BIT_13 | BIT_12)); + rtl8125_ephy_write(tp, 0x02, 0x6042); + rtl8125_ephy_write(tp, 0x06, 0x0014); + + ClearAndSetPCIePhyBit(tp, + 0x6A, + (BIT_14 | BIT_13 | BIT_12), + (BIT_13 | BIT_12) + ); + ClearPCIePhyBit(tp, 0x59, BIT_6); + SetPCIePhyBit(tp, 0x5B, (BIT_11 | BIT_10 | BIT_9)); + ClearPCIePhyBit(tp, 0x5B, (BIT_14 | BIT_13 | BIT_12)); + rtl8125_ephy_write(tp, 0x42, 0x6042); + rtl8125_ephy_write(tp, 0x46, 0x0014); + break; + case CFG_METHOD_4: + rtl8125_ephy_write(tp, 0x06, 0x001F); + rtl8125_ephy_write(tp, 0x0A, 0xB66B); + rtl8125_ephy_write(tp, 0x01, 0xA852); + rtl8125_ephy_write(tp, 0x24, 0x0008); + rtl8125_ephy_write(tp, 0x2F, 0x6052); + rtl8125_ephy_write(tp, 0x0D, 0xF716); + rtl8125_ephy_write(tp, 0x20, 0xD477); + rtl8125_ephy_write(tp, 0x21, 0x4477); + rtl8125_ephy_write(tp, 0x22, 0x0013); + rtl8125_ephy_write(tp, 0x23, 0xBB66); + rtl8125_ephy_write(tp, 0x0B, 0xA909); + rtl8125_ephy_write(tp, 0x29, 0xFF04); + rtl8125_ephy_write(tp, 0x1B, 0x1EA0); + + rtl8125_ephy_write(tp, 0x46, 0x001F); + rtl8125_ephy_write(tp, 0x4A, 0xB66B); + rtl8125_ephy_write(tp, 0x41, 0xA84A); + rtl8125_ephy_write(tp, 0x64, 0x000C); + rtl8125_ephy_write(tp, 0x6F, 0x604A); + rtl8125_ephy_write(tp, 0x4D, 0xF716); + rtl8125_ephy_write(tp, 0x60, 0xD477); + rtl8125_ephy_write(tp, 0x61, 0x4477); + rtl8125_ephy_write(tp, 0x62, 0x0013); + rtl8125_ephy_write(tp, 0x63, 0xBB66); + rtl8125_ephy_write(tp, 0x4B, 0xA909); + rtl8125_ephy_write(tp, 0x69, 0xFF04); + rtl8125_ephy_write(tp, 0x5B, 0x1EA0); + break; + case CFG_METHOD_5: + rtl8125_ephy_write(tp, 0x0B, 0xA908); + rtl8125_ephy_write(tp, 0x22, 0x0023); + rtl8125_ephy_write(tp, 0x1E, 0x28EB); + + rtl8125_ephy_write(tp, 0x4B, 0xA908); + rtl8125_ephy_write(tp, 0x62, 0x0023); + rtl8125_ephy_write(tp, 0x5E, 0x28EB); + break; + } +} + +static u16 +rtl8125_get_hw_phy_mcu_code_ver(struct rtl8125_private *tp) +{ + u16 hw_ram_code_ver = ~0; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); + hw_ram_code_ver = mdio_direct_read_phy_ocp(tp, 0xA438); + break; + } + + return hw_ram_code_ver; +} + +static int +rtl8125_check_hw_phy_mcu_code_ver(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ram_code_ver_match = 0; + + tp->hw_ram_code_ver = rtl8125_get_hw_phy_mcu_code_ver(tp); + + if (tp->hw_ram_code_ver == tp->sw_ram_code_ver) { + ram_code_ver_match = 1; + tp->HwHasWrRamCodeToMicroP = TRUE; + } + + return ram_code_ver_match; +} + +bool +rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp) +{ + u16 gphy_val; + u16 WaitCount; + bool bSuccess = TRUE; + + SetEthPhyOcpBit(tp, 0xB820, BIT_4); + + WaitCount = 0; + do { + gphy_val = mdio_direct_read_phy_ocp(tp, 0xB800); + udelay(100); + WaitCount++; + } while (!(gphy_val & BIT_6) && (WaitCount < 1000)); + + if (!(gphy_val & BIT_6) && (WaitCount == 1000)) bSuccess = FALSE; + + if (!bSuccess) + dprintk("rtl8125_set_phy_mcu_patch_request fail.\n"); + + return bSuccess; +} + +bool +rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp) +{ + u16 gphy_val; + u16 WaitCount; + bool bSuccess = TRUE; + + ClearEthPhyOcpBit(tp, 0xB820, BIT_4); + + WaitCount = 0; + do { + gphy_val = mdio_direct_read_phy_ocp(tp, 0xB800); + udelay(100); + WaitCount++; + } while ((gphy_val & BIT_6) && (WaitCount < 1000)); + + if ((gphy_val & BIT_6) && (WaitCount == 1000)) bSuccess = FALSE; + + if (!bSuccess) + dprintk("rtl8125_clear_phy_mcu_patch_request fail.\n"); + + return bSuccess; +} + +#ifndef ENABLE_USE_FIRMWARE_FILE +static void +rtl8125_write_hw_phy_mcu_code_ver(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); + mdio_direct_write_phy_ocp(tp, 0xA438, tp->sw_ram_code_ver); + tp->hw_ram_code_ver = tp->sw_ram_code_ver; + break; + } +} + +static void +rtl8125_acquire_phy_mcu_patch_key_lock(struct rtl8125_private *tp) +{ + u16 PatchKey; + + switch (tp->mcfg) { + case CFG_METHOD_2: + PatchKey = 0x8600; + break; + case CFG_METHOD_3: + PatchKey = 0x8601; + break; + case CFG_METHOD_4: + PatchKey = 0x3700; + break; + case CFG_METHOD_5: + PatchKey = 0x3701; + break; + default: + return; + } + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); + mdio_direct_write_phy_ocp(tp, 0xA438, PatchKey); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xB82E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); +} + +static void +rtl8125_release_phy_mcu_patch_key_lock(struct rtl8125_private *tp) +{ + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mdio_direct_write_phy_ocp(tp, 0xA436, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + ClearEthPhyOcpBit(tp, 0xB82E, BIT_0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + break; + default: + break; + } +} + +static void +rtl8125_set_phy_mcu_ram_code(struct net_device *dev, const u16 *ramcode, u16 codesize) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 i; + u16 addr; + u16 val; + + if (ramcode == NULL || codesize % 2) { + goto out; + } + + for (i = 0; i < codesize; i += 2) { + addr = ramcode[i]; + val = ramcode[i + 1]; + if (addr == 0xFFFF && val == 0xFFFF) { + break; + } + mdio_direct_write_phy_ocp(tp, addr, val); + } + +out: + return; +} + +static void +rtl8125_enable_phy_disable_mode(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppCheckPhyDisableModeVer) { + case 3: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_5); + break; + } + + dprintk("enable phy disable mode.\n"); +} + +static void +rtl8125_disable_phy_disable_mode(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->HwSuppCheckPhyDisableModeVer) { + case 3: + RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_5); + break; + } + + mdelay(1); + + dprintk("disable phy disable mode.\n"); +} + +static void +rtl8125_set_hw_phy_before_init_phy_mcu(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u16 PhyRegValue; + + switch (tp->mcfg) { + case CFG_METHOD_4: + mdio_direct_write_phy_ocp(tp, 0xBF86, 0x9000); + + SetEthPhyOcpBit(tp, 0xC402, BIT_10); + ClearEthPhyOcpBit(tp, 0xC402, BIT_10); + + PhyRegValue = mdio_direct_read_phy_ocp(tp, 0xBF86); + PhyRegValue &= (BIT_1 | BIT_0); + if (PhyRegValue != 0) + dprintk("PHY watch dog not clear, value = 0x%x \n", PhyRegValue); + + mdio_direct_write_phy_ocp(tp, 0xBD86, 0x1010); + mdio_direct_write_phy_ocp(tp, 0xBD88, 0x1010); + + ClearAndSetEthPhyOcpBit(tp, + 0xBD4E, + BIT_11 | BIT_10, + BIT_11); + ClearAndSetEthPhyOcpBit(tp, + 0xBF46, + BIT_11 | BIT_10 | BIT_9 | BIT_8, + BIT_10 | BIT_9 | BIT_8); + break; + } +} + +static void +rtl8125_real_set_phy_mcu_8125a_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_acquire_phy_mcu_patch_key_lock(tp); + + + SetEthPhyOcpBit(tp, 0xB820, BIT_7); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8013); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8021); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x802f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x803d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8042); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa088); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a50); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a6c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8080); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd019); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a84); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8970); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c07); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0901); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcf09); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd705); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xceff); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf0a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1213); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8401); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8580); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1253); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd181); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4018); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd706); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2c59); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x804d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc60f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc605); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x10fd); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x10f4); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1252); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1206); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a78); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a60); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a4f); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3f00); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8066); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x807c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8089); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x808e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80b2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80c2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62db); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x655c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x653c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0346); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8208); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x609d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x607d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0221); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ce); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0169); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00a6); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x000d); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x029f); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x007f); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8017); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8029); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8054); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x805a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8064); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9430); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9480); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb408); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd120); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd057); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb80); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9906); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0567); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb94); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8406); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8dff); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0773); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4045); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07ec); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fa7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0481); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8220); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x078e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd150); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6121); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x61a2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6223); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0537); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0642); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0686); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0788); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x047b); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x065c); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0769); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0565); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x06f9); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ff); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8593); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9caf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x85a5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfb0c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86d7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xda02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xdd02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfd0c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86dd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fe); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf2f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2cac); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0286); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x65af); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x212b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x022c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86b6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf21); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cd1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8710); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x870d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8716); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x871f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x871c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8728); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8725); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8707); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbad); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x281c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3402); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3102); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3d02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3a02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4302); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4c02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4902); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2e02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4602); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4f02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf35); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7ff8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfaef); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x69bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fe); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ec); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ef); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cef); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x96fe); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf8fa); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xef69); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xef02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf202); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf502); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf802); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xef96); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfefc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0420); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x53b5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4086); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb9b5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb03a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbac8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb13a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xba77); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2677); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2640); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x28bb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa430); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2f71); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x20d9); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2109); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x34e7); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x000f); + + + ClearEthPhyOcpBit(tp, 0xB820, BIT_7); + + + rtl8125_release_phy_mcu_patch_key_lock(tp); +} + +static void +rtl8125_set_phy_mcu_8125a_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_set_phy_mcu_patch_request(tp); + + rtl8125_real_set_phy_mcu_8125a_1(dev); + + rtl8125_clear_phy_mcu_patch_request(tp); +} + +static void +rtl8125_real_set_phy_mcu_8125a_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_acquire_phy_mcu_patch_key_lock(tp); + + + SetEthPhyOcpBit(tp, 0xB820, BIT_7); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x808b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x808f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8093); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8097); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x809d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80aa); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x607b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x42da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x615b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac11); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa410); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4779); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac22); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa420); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4559); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf023); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac44); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa440); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4339); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac88); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa480); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4119); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf001); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fac); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc48f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x141b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x121a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0898); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd18a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x401c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa804); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8804); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x053b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0648); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc520); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa201); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x252d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd708); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4006); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0307); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1645); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0647); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x053a); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7c); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0c); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0896); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xff00); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8015); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xad02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x02d7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ed); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xc100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x008f); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x008d); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00eb); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8014); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8018); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8024); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8055); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8072); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x80dc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa380); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4085); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8280); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd158); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd04d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8380); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd10d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa220); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd130); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xbb80); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1c4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd074); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x604b); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa90c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd116); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd119); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6241); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x63e2); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6583); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf054); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d50); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf021); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d60); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf013); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d70); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d80); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ff4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07fb); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f6f); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f4e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f2d); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f0c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1f5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xd049); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ec); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ea); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x06a9); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x078a); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d2); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x067f); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0665); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00fc); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x45af); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xee82); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf900); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf03); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7f8); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0a6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00e1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa601); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xef01); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x58f0); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa080); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x37a1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8402); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae16); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa185); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8702); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae0c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xa188); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x07a1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8902); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1c); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03b3); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); + mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); + + + ClearEthPhyOcpBit(tp, 0xB820, BIT_7); + + + rtl8125_release_phy_mcu_patch_key_lock(tp); +} + +static void +rtl8125_set_phy_mcu_8125a_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_set_phy_mcu_patch_request(tp); + + rtl8125_real_set_phy_mcu_8125a_2(dev); + + rtl8125_clear_phy_mcu_patch_request(tp); +} + +static const u16 phy_mcu_ram_code_8125b_1[] = { + 0xa436, 0x8024, 0xa438, 0x3700, 0xa436, 0xB82E, 0xa438, 0x0001, + 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, + 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, + 0xa438, 0x1800, 0xa438, 0x8025, 0xa438, 0x1800, 0xa438, 0x803a, + 0xa438, 0x1800, 0xa438, 0x8044, 0xa438, 0x1800, 0xa438, 0x8083, + 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0x1800, 0xa438, 0x808d, + 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0xd712, 0xa438, 0x4077, + 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, 0xa438, 0x6099, + 0xa438, 0x7f44, 0xa438, 0x1800, 0xa438, 0x1a14, 0xa438, 0x9040, + 0xa438, 0x9201, 0xa438, 0x1800, 0xa438, 0x1b1a, 0xa438, 0xd71e, + 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, 0xa438, 0x3ce5, + 0xa438, 0x1afb, 0xa438, 0x1800, 0xa438, 0x1b00, 0xa438, 0xd712, + 0xa438, 0x4077, 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, + 0xa438, 0x60b9, 0xa438, 0x2421, 0xa438, 0x1c17, 0xa438, 0x1800, + 0xa438, 0x1a14, 0xa438, 0x9040, 0xa438, 0x1800, 0xa438, 0x1c2c, + 0xa438, 0xd71e, 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, + 0xa438, 0x3ce5, 0xa438, 0x1c0f, 0xa438, 0x1800, 0xa438, 0x1c13, + 0xa438, 0xd702, 0xa438, 0xd501, 0xa438, 0x6072, 0xa438, 0x8401, + 0xa438, 0xf002, 0xa438, 0xa401, 0xa438, 0x1000, 0xa438, 0x146e, + 0xa438, 0x1800, 0xa438, 0x0b77, 0xa438, 0xd703, 0xa438, 0x665d, + 0xa438, 0x653e, 0xa438, 0x641f, 0xa438, 0xd700, 0xa438, 0x62c4, + 0xa438, 0x6185, 0xa438, 0x6066, 0xa438, 0x1800, 0xa438, 0x165a, + 0xa438, 0xc101, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, + 0xa438, 0xd700, 0xa438, 0x7fa6, 0xa438, 0x1800, 0xa438, 0x807d, + 0xa438, 0xc102, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, + 0xa438, 0xd700, 0xa438, 0x2569, 0xa438, 0x8058, 0xa438, 0x1800, + 0xa438, 0x807d, 0xa438, 0xc104, 0xa438, 0xcb00, 0xa438, 0x1000, + 0xa438, 0x1945, 0xa438, 0xd700, 0xa438, 0x7fa4, 0xa438, 0x1800, + 0xa438, 0x807d, 0xa438, 0xc120, 0xa438, 0xcb00, 0xa438, 0x1000, + 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbf, 0xa438, 0x1800, + 0xa438, 0x807d, 0xa438, 0xc140, 0xa438, 0xcb00, 0xa438, 0x1000, + 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbe, 0xa438, 0x1800, + 0xa438, 0x807d, 0xa438, 0xc180, 0xa438, 0xcb00, 0xa438, 0x1000, + 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbd, 0xa438, 0xc100, + 0xa438, 0xcb00, 0xa438, 0xd708, 0xa438, 0x6018, 0xa438, 0x1800, + 0xa438, 0x165a, 0xa438, 0x1000, 0xa438, 0x14f6, 0xa438, 0xd014, + 0xa438, 0xd1e3, 0xa438, 0x1000, 0xa438, 0x1356, 0xa438, 0xd705, + 0xa438, 0x5fbe, 0xa438, 0x1800, 0xa438, 0x1559, 0xa436, 0xA026, + 0xa438, 0xffff, 0xa436, 0xA024, 0xa438, 0xffff, 0xa436, 0xA022, + 0xa438, 0xffff, 0xa436, 0xA020, 0xa438, 0x1557, 0xa436, 0xA006, + 0xa438, 0x1677, 0xa436, 0xA004, 0xa438, 0x0b75, 0xa436, 0xA002, + 0xa438, 0x1c17, 0xa436, 0xA000, 0xa438, 0x1b04, 0xa436, 0xA008, + 0xa438, 0x1f00, 0xa436, 0xA016, 0xa438, 0x0020, 0xa436, 0xA012, + 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, + 0xa438, 0x1800, 0xa438, 0x817f, 0xa438, 0x1800, 0xa438, 0x82ab, + 0xa438, 0x1800, 0xa438, 0x83f8, 0xa438, 0x1800, 0xa438, 0x8444, + 0xa438, 0x1800, 0xa438, 0x8454, 0xa438, 0x1800, 0xa438, 0x8459, + 0xa438, 0x1800, 0xa438, 0x8465, 0xa438, 0xcb11, 0xa438, 0xa50c, + 0xa438, 0x8310, 0xa438, 0xd701, 0xa438, 0x4076, 0xa438, 0x0c03, + 0xa438, 0x0903, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x1000, 0xa438, 0x0a4d, + 0xa438, 0xcb12, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5f84, 0xa438, 0xd102, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd701, + 0xa438, 0x60f3, 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, + 0xa438, 0xd410, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb13, + 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, + 0xa438, 0xa00a, 0xa438, 0xa910, 0xa438, 0xa780, 0xa438, 0xd14a, + 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, + 0xa438, 0x6255, 0xa438, 0xd700, 0xa438, 0x5f74, 0xa438, 0x6326, + 0xa438, 0xd702, 0xa438, 0x5f07, 0xa438, 0x800a, 0xa438, 0xa004, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, + 0xa438, 0x0902, 0xa438, 0xffe2, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x5fab, 0xa438, 0xba08, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8b, 0xa438, 0x9a08, + 0xa438, 0x800a, 0xa438, 0xd702, 0xa438, 0x6535, 0xa438, 0xd40d, + 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb14, 0xa438, 0xa004, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa00a, + 0xa438, 0xa780, 0xa438, 0xd14a, 0xa438, 0xd048, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x6206, + 0xa438, 0xd702, 0xa438, 0x5f47, 0xa438, 0x800a, 0xa438, 0xa004, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, + 0xa438, 0x0902, 0xa438, 0x1800, 0xa438, 0x8064, 0xa438, 0x800a, + 0xa438, 0xd40e, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0xd701, 0xa438, 0x6073, 0xa438, 0xd701, + 0xa438, 0x4216, 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, + 0xa438, 0x8004, 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, + 0xa438, 0x8001, 0xa438, 0xd120, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x8504, + 0xa438, 0xcb21, 0xa438, 0xa301, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, 0xa438, 0xd704, + 0xa438, 0x40e0, 0xa438, 0xd196, 0xa438, 0xd04d, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb22, + 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, + 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8910, 0xa438, 0x8720, + 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, + 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, + 0xa438, 0x0a7d, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb23, + 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, + 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, + 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, + 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, + 0xa438, 0x5dee, 0xa438, 0xcb24, 0xa438, 0x8f1f, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f6e, 0xa438, 0xa111, + 0xa438, 0xa215, 0xa438, 0xa401, 0xa438, 0x8404, 0xa438, 0xa720, + 0xa438, 0xcb25, 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, + 0xa438, 0x9503, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, + 0xa438, 0x0b86, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0xcb26, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x8205, + 0xa438, 0x8404, 0xa438, 0xcb27, 0xa438, 0xd404, 0xa438, 0x1000, + 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0xa104, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8104, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa120, + 0xa438, 0xaa0f, 0xa438, 0x8110, 0xa438, 0xa284, 0xa438, 0xa404, + 0xa438, 0xa00a, 0xa438, 0xd193, 0xa438, 0xd046, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb28, + 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fa8, 0xa438, 0x8110, 0xa438, 0x8284, 0xa438, 0xa404, + 0xa438, 0x800a, 0xa438, 0x8710, 0xa438, 0xb804, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, + 0xa438, 0xcb29, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, + 0xa438, 0xcb2a, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa404, + 0xa438, 0xa00a, 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8149, + 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8151, + 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, + 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, + 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8404, + 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, + 0xa438, 0x0433, 0xa438, 0xcb15, 0xa438, 0xa508, 0xa438, 0xd700, + 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, + 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, + 0xa438, 0x1000, 0xa438, 0x0a4d, 0xa438, 0xa301, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, + 0xa438, 0xd704, 0xa438, 0x40e0, 0xa438, 0xd115, 0xa438, 0xd04f, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, + 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb16, + 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, + 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8720, 0xa438, 0xd17a, + 0xa438, 0xd04c, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb17, + 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, + 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, + 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, + 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, + 0xa438, 0x61ce, 0xa438, 0xd700, 0xa438, 0x5db4, 0xa438, 0xcb18, + 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, + 0xa438, 0xa720, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xffd6, 0xa438, 0x8f1f, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f8e, 0xa438, 0xa131, + 0xa438, 0xaa0f, 0xa438, 0xa2d5, 0xa438, 0xa407, 0xa438, 0xa720, + 0xa438, 0x8310, 0xa438, 0xa308, 0xa438, 0x8308, 0xa438, 0xcb19, + 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, + 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, 0xa438, 0x0b86, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, + 0xa438, 0xcb1a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x82c5, 0xa438, 0xa404, + 0xa438, 0x8402, 0xa438, 0xb804, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, 0xa438, 0xcb1b, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f85, + 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, 0xa438, 0xcb1c, + 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, + 0xa438, 0x0a7d, 0xa438, 0xa110, 0xa438, 0xa284, 0xa438, 0xa404, + 0xa438, 0x8402, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fa8, 0xa438, 0xcb1d, 0xa438, 0xa180, 0xa438, 0xa402, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, + 0xa438, 0xa220, 0xa438, 0xd1f5, 0xa438, 0xd049, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8221, + 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xb920, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fa3, + 0xa438, 0xa504, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa00a, 0xa438, 0x8190, + 0xa438, 0x82a4, 0xa438, 0x8402, 0xa438, 0xa404, 0xa438, 0xb808, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7fa3, + 0xa438, 0x9808, 0xa438, 0xcb2b, 0xa438, 0xcb2c, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f84, 0xa438, 0xd14a, + 0xa438, 0xd048, 0xa438, 0xa780, 0xa438, 0xcb2d, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f94, 0xa438, 0x6208, + 0xa438, 0xd702, 0xa438, 0x5f27, 0xa438, 0x800a, 0xa438, 0xa004, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, + 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, + 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xffe9, 0xa438, 0xcb2e, + 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, + 0xa438, 0x0a7d, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa406, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, + 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x827d, + 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, + 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, + 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8406, + 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, + 0xa438, 0x0433, 0xa438, 0xcb30, 0xa438, 0x8380, 0xa438, 0xcb31, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f86, + 0xa438, 0x9308, 0xa438, 0xb204, 0xa438, 0xb301, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x5fa2, 0xa438, 0xb302, + 0xa438, 0x9204, 0xa438, 0xcb32, 0xa438, 0xd408, 0xa438, 0x1000, + 0xa438, 0x0a37, 0xa438, 0xd141, 0xa438, 0xd043, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd704, + 0xa438, 0x4ccc, 0xa438, 0xd700, 0xa438, 0x4c81, 0xa438, 0xd702, + 0xa438, 0x609e, 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0xf003, + 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, + 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, 0xa438, 0x0c1f, + 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x8710, + 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, + 0xa438, 0xa203, 0xa438, 0x8120, 0xa438, 0x8a0f, 0xa438, 0xa111, + 0xa438, 0x8204, 0xa438, 0xa140, 0xa438, 0x1000, 0xa438, 0x0a42, + 0xa438, 0x8140, 0xa438, 0xd17a, 0xa438, 0xd04b, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xa204, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, + 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0xd404, 0xa438, 0x1000, + 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0x8101, + 0xa438, 0x8201, 0xa438, 0xa104, 0xa438, 0x1000, 0xa438, 0x0a42, + 0xa438, 0x8104, 0xa438, 0xa120, 0xa438, 0xaa0f, 0xa438, 0x8110, + 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0xa00a, 0xa438, 0xd193, + 0xa438, 0xd047, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fa8, 0xa438, 0xa180, 0xa438, 0xd13d, + 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0xf024, 0xa438, 0xa710, 0xa438, 0xa00a, + 0xa438, 0x8190, 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, + 0xa438, 0x8710, 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0x800a, + 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0x8406, 0xa438, 0xd700, + 0xa438, 0x4121, 0xa438, 0xd701, 0xa438, 0x60f3, 0xa438, 0xd1e5, + 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0x8710, 0xa438, 0xa00a, 0xa438, 0x8190, + 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, 0xa438, 0xb920, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, + 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, + 0xa438, 0x7f8c, 0xa438, 0xcb33, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd71f, 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, + 0xa438, 0x9820, 0xa438, 0xcb34, 0xa438, 0xa00a, 0xa438, 0xa190, + 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fa9, 0xa438, 0xd701, 0xa438, 0x6853, + 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d00, + 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, 0xa438, 0x1000, + 0xa438, 0x0a7d, 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0xcb35, + 0xa438, 0xd407, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8110, + 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa00a, 0xa438, 0xd704, + 0xa438, 0x4215, 0xa438, 0xa304, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fb8, 0xa438, 0xd1c3, 0xa438, 0xd043, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, + 0xa438, 0x8304, 0xa438, 0xd700, 0xa438, 0x4109, 0xa438, 0xf01e, + 0xa438, 0xcb36, 0xa438, 0xd412, 0xa438, 0x1000, 0xa438, 0x0a37, + 0xa438, 0xd700, 0xa438, 0x6309, 0xa438, 0xd702, 0xa438, 0x42c7, + 0xa438, 0x800a, 0xa438, 0x8180, 0xa438, 0x8280, 0xa438, 0x8404, + 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, + 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, + 0xa438, 0x0c03, 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xd14a, + 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, + 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, + 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xcc55, 0xa438, 0xcb37, + 0xa438, 0xa00a, 0xa438, 0xa190, 0xa438, 0xa2a4, 0xa438, 0xa404, + 0xa438, 0xd700, 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd13d, + 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, + 0xa438, 0x5fa9, 0xa438, 0xd702, 0xa438, 0x5f71, 0xa438, 0xcb38, + 0xa438, 0x8224, 0xa438, 0xa288, 0xa438, 0x8180, 0xa438, 0xa110, + 0xa438, 0xa404, 0xa438, 0x800a, 0xa438, 0xd700, 0xa438, 0x6041, + 0xa438, 0x8402, 0xa438, 0xd415, 0xa438, 0x1000, 0xa438, 0x0a37, + 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, + 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb39, 0xa438, 0xa00a, + 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xd700, + 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd17a, 0xa438, 0xd047, + 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, + 0xa438, 0x1800, 0xa438, 0x0560, 0xa438, 0xa111, 0xa438, 0x0000, + 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0xd3f5, + 0xa438, 0xd219, 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, + 0xa438, 0x5fa5, 0xa438, 0xa215, 0xa438, 0xd30e, 0xa438, 0xd21a, + 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x63e9, + 0xa438, 0xd708, 0xa438, 0x5f65, 0xa438, 0xd708, 0xa438, 0x7f36, + 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8004, + 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8001, + 0xa438, 0xd708, 0xa438, 0x4098, 0xa438, 0xd102, 0xa438, 0x9401, + 0xa438, 0xf003, 0xa438, 0xd103, 0xa438, 0xb401, 0xa438, 0x1000, + 0xa438, 0x0c27, 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0c35, + 0xa438, 0x8108, 0xa438, 0x8110, 0xa438, 0x8294, 0xa438, 0xa202, + 0xa438, 0x1800, 0xa438, 0x0bdb, 0xa438, 0xd39c, 0xa438, 0xd210, + 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x5fa5, + 0xa438, 0xd39c, 0xa438, 0xd210, 0xa438, 0x1000, 0xa438, 0x0c31, + 0xa438, 0xd708, 0xa438, 0x5fa5, 0xa438, 0x1000, 0xa438, 0x0c31, + 0xa438, 0xd708, 0xa438, 0x29b5, 0xa438, 0x840e, 0xa438, 0xd708, + 0xa438, 0x5f4a, 0xa438, 0x0c1f, 0xa438, 0x1014, 0xa438, 0x1000, + 0xa438, 0x0c31, 0xa438, 0xd709, 0xa438, 0x7fa4, 0xa438, 0x901f, + 0xa438, 0x1800, 0xa438, 0x0c23, 0xa438, 0xcb43, 0xa438, 0xa508, + 0xa438, 0xd701, 0xa438, 0x3699, 0xa438, 0x844a, 0xa438, 0xa504, + 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xa00a, + 0xa438, 0xd700, 0xa438, 0x2109, 0xa438, 0x05ea, 0xa438, 0xa402, + 0xa438, 0x1800, 0xa438, 0x05ea, 0xa438, 0xcb90, 0xa438, 0x0cf0, + 0xa438, 0x0ca0, 0xa438, 0x1800, 0xa438, 0x06db, 0xa438, 0xd1ff, + 0xa438, 0xd052, 0xa438, 0xa508, 0xa438, 0x8718, 0xa438, 0xa00a, + 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0x0cf0, + 0xa438, 0x0c50, 0xa438, 0x1800, 0xa438, 0x09ef, 0xa438, 0x1000, + 0xa438, 0x0a5e, 0xa438, 0xd704, 0xa438, 0x2e70, 0xa438, 0x06da, + 0xa438, 0xd700, 0xa438, 0x5f55, 0xa438, 0xa90c, 0xa438, 0x1800, + 0xa438, 0x0645, 0xa436, 0xA10E, 0xa438, 0x0644, 0xa436, 0xA10C, + 0xa438, 0x09e9, 0xa436, 0xA10A, 0xa438, 0x06da, 0xa436, 0xA108, + 0xa438, 0x05e1, 0xa436, 0xA106, 0xa438, 0x0be4, 0xa436, 0xA104, + 0xa438, 0x0435, 0xa436, 0xA102, 0xa438, 0x0141, 0xa436, 0xA100, + 0xa438, 0x026d, 0xa436, 0xA110, 0xa438, 0x00ff, 0xa436, 0xb87c, + 0xa438, 0x85fe, 0xa436, 0xb87e, 0xa438, 0xaf86, 0xa438, 0x16af, + 0xa438, 0x8699, 0xa438, 0xaf86, 0xa438, 0xe5af, 0xa438, 0x86f9, + 0xa438, 0xaf87, 0xa438, 0x7aaf, 0xa438, 0x883a, 0xa438, 0xaf88, + 0xa438, 0x58af, 0xa438, 0x8b6c, 0xa438, 0xd48b, 0xa438, 0x7c02, + 0xa438, 0x8644, 0xa438, 0x2c00, 0xa438, 0x503c, 0xa438, 0xffd6, + 0xa438, 0xac27, 0xa438, 0x18e1, 0xa438, 0x82fe, 0xa438, 0xad28, + 0xa438, 0x0cd4, 0xa438, 0x8b84, 0xa438, 0x0286, 0xa438, 0x442c, + 0xa438, 0x003c, 0xa438, 0xac27, 0xa438, 0x06ee, 0xa438, 0x8299, + 0xa438, 0x01ae, 0xa438, 0x04ee, 0xa438, 0x8299, 0xa438, 0x00af, + 0xa438, 0x23dc, 0xa438, 0xf9fa, 0xa438, 0xcefa, 0xa438, 0xfbef, + 0xa438, 0x79fb, 0xa438, 0xc4bf, 0xa438, 0x8b76, 0xa438, 0x026c, + 0xa438, 0x6dac, 0xa438, 0x2804, 0xa438, 0xd203, 0xa438, 0xae02, + 0xa438, 0xd201, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, + 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x648a, + 0xa438, 0x0002, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, + 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x7402, + 0xa438, 0x72cd, 0xa438, 0xac50, 0xa438, 0x02ef, 0xa438, 0x643a, + 0xa438, 0x019f, 0xa438, 0xe4ef, 0xa438, 0x4678, 0xa438, 0x03ac, + 0xa438, 0x2002, 0xa438, 0xae02, 0xa438, 0xd0ff, 0xa438, 0xffef, + 0xa438, 0x97ff, 0xa438, 0xfec6, 0xa438, 0xfefd, 0xa438, 0x041f, + 0xa438, 0x771f, 0xa438, 0x221c, 0xa438, 0x450d, 0xa438, 0x481f, + 0xa438, 0x00ac, 0xa438, 0x7f04, 0xa438, 0x1a94, 0xa438, 0xae08, + 0xa438, 0x1a94, 0xa438, 0xac7f, 0xa438, 0x03d7, 0xa438, 0x0100, + 0xa438, 0xef46, 0xa438, 0x0d48, 0xa438, 0x1f00, 0xa438, 0x1c45, + 0xa438, 0xef69, 0xa438, 0xef57, 0xa438, 0xef74, 0xa438, 0x0272, + 0xa438, 0xe8a7, 0xa438, 0xffff, 0xa438, 0x0d1a, 0xa438, 0x941b, + 0xa438, 0x979e, 0xa438, 0x072d, 0xa438, 0x0100, 0xa438, 0x1a64, + 0xa438, 0xef76, 0xa438, 0xef97, 0xa438, 0x0d98, 0xa438, 0xd400, + 0xa438, 0xff1d, 0xa438, 0x941a, 0xa438, 0x89cf, 0xa438, 0x1a75, + 0xa438, 0xaf74, 0xa438, 0xf9bf, 0xa438, 0x8b79, 0xa438, 0x026c, + 0xa438, 0x6da1, 0xa438, 0x0005, 0xa438, 0xe180, 0xa438, 0xa0ae, + 0xa438, 0x03e1, 0xa438, 0x80a1, 0xa438, 0xaf26, 0xa438, 0x9aac, + 0xa438, 0x284d, 0xa438, 0xe08f, 0xa438, 0xffef, 0xa438, 0x10c0, + 0xa438, 0xe08f, 0xa438, 0xfe10, 0xa438, 0x1b08, 0xa438, 0xa000, + 0xa438, 0x04c8, 0xa438, 0xaf40, 0xa438, 0x67c8, 0xa438, 0xbf8b, + 0xa438, 0x8c02, 0xa438, 0x6c4e, 0xa438, 0xc4bf, 0xa438, 0x8b8f, + 0xa438, 0x026c, 0xa438, 0x6def, 0xa438, 0x74e0, 0xa438, 0x830c, + 0xa438, 0xad20, 0xa438, 0x0302, 0xa438, 0x74ac, 0xa438, 0xccef, + 0xa438, 0x971b, 0xa438, 0x76ad, 0xa438, 0x5f02, 0xa438, 0xae13, + 0xa438, 0xef69, 0xa438, 0xef30, 0xa438, 0x1b32, 0xa438, 0xc4ef, + 0xa438, 0x46e4, 0xa438, 0x8ffb, 0xa438, 0xe58f, 0xa438, 0xfce7, + 0xa438, 0x8ffd, 0xa438, 0xcc10, 0xa438, 0x11ae, 0xa438, 0xb8d1, + 0xa438, 0x00a1, 0xa438, 0x1f03, 0xa438, 0xaf40, 0xa438, 0x4fbf, + 0xa438, 0x8b8c, 0xa438, 0x026c, 0xa438, 0x4ec4, 0xa438, 0xbf8b, + 0xa438, 0x8f02, 0xa438, 0x6c6d, 0xa438, 0xef74, 0xa438, 0xe083, + 0xa438, 0x0cad, 0xa438, 0x2003, 0xa438, 0x0274, 0xa438, 0xaccc, + 0xa438, 0xef97, 0xa438, 0x1b76, 0xa438, 0xad5f, 0xa438, 0x02ae, + 0xa438, 0x04ef, 0xa438, 0x69ef, 0xa438, 0x3111, 0xa438, 0xaed1, + 0xa438, 0x0287, 0xa438, 0x80af, 0xa438, 0x2293, 0xa438, 0xf8f9, + 0xa438, 0xfafb, 0xa438, 0xef59, 0xa438, 0xe080, 0xa438, 0x13ad, + 0xa438, 0x252f, 0xa438, 0xbf88, 0xa438, 0x2802, 0xa438, 0x6c6d, + 0xa438, 0xef64, 0xa438, 0x1f44, 0xa438, 0xe18f, 0xa438, 0xb91b, + 0xa438, 0x64ad, 0xa438, 0x4f1d, 0xa438, 0xd688, 0xa438, 0x2bd7, + 0xa438, 0x882e, 0xa438, 0x0274, 0xa438, 0x73ad, 0xa438, 0x5008, + 0xa438, 0xbf88, 0xa438, 0x3102, 0xa438, 0x737c, 0xa438, 0xae03, + 0xa438, 0x0287, 0xa438, 0xd0bf, 0xa438, 0x882b, 0xa438, 0x0273, + 0xa438, 0x73e0, 0xa438, 0x824c, 0xa438, 0xf621, 0xa438, 0xe482, + 0xa438, 0x4cbf, 0xa438, 0x8834, 0xa438, 0x0273, 0xa438, 0x7cef, + 0xa438, 0x95ff, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf8f9, + 0xa438, 0xfafb, 0xa438, 0xef79, 0xa438, 0xbf88, 0xa438, 0x1f02, + 0xa438, 0x737c, 0xa438, 0x1f22, 0xa438, 0xac32, 0xa438, 0x31ef, + 0xa438, 0x12bf, 0xa438, 0x8822, 0xa438, 0x026c, 0xa438, 0x4ed6, + 0xa438, 0x8fba, 0xa438, 0x1f33, 0xa438, 0xac3c, 0xa438, 0x1eef, + 0xa438, 0x13bf, 0xa438, 0x8837, 0xa438, 0x026c, 0xa438, 0x4eef, + 0xa438, 0x96d8, 0xa438, 0x19d9, 0xa438, 0xbf88, 0xa438, 0x2502, + 0xa438, 0x6c4e, 0xa438, 0xbf88, 0xa438, 0x2502, 0xa438, 0x6c4e, + 0xa438, 0x1616, 0xa438, 0x13ae, 0xa438, 0xdf12, 0xa438, 0xaecc, + 0xa438, 0xbf88, 0xa438, 0x1f02, 0xa438, 0x7373, 0xa438, 0xef97, + 0xa438, 0xfffe, 0xa438, 0xfdfc, 0xa438, 0x0466, 0xa438, 0xac88, + 0xa438, 0x54ac, 0xa438, 0x88f0, 0xa438, 0xac8a, 0xa438, 0x92ac, + 0xa438, 0xbadd, 0xa438, 0xac6c, 0xa438, 0xeeac, 0xa438, 0x6cff, + 0xa438, 0xad02, 0xa438, 0x99ac, 0xa438, 0x0030, 0xa438, 0xac88, + 0xa438, 0xd4c3, 0xa438, 0x5000, 0xa438, 0x0000, 0xa438, 0x0000, + 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, + 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x00b4, 0xa438, 0xecee, + 0xa438, 0x8298, 0xa438, 0x00af, 0xa438, 0x1412, 0xa438, 0xf8bf, + 0xa438, 0x8b5d, 0xa438, 0x026c, 0xa438, 0x6d58, 0xa438, 0x03e1, + 0xa438, 0x8fb8, 0xa438, 0x2901, 0xa438, 0xe58f, 0xa438, 0xb8a0, + 0xa438, 0x0049, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x02e5, + 0xa438, 0x8303, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, + 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, + 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, + 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, + 0xa438, 0xf728, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, + 0xa438, 0xf628, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, + 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6002, + 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, + 0xa438, 0xaf89, 0xa438, 0x96a0, 0xa438, 0x0149, 0xa438, 0xef47, + 0xa438, 0xe483, 0xa438, 0x04e5, 0xa438, 0x8305, 0xa438, 0xbfc2, + 0xa438, 0x5f1a, 0xa438, 0x95f7, 0xa438, 0x05ee, 0xa438, 0xffd2, + 0xa438, 0x00d8, 0xa438, 0xf605, 0xa438, 0x1f11, 0xa438, 0xef60, + 0xa438, 0xbf8b, 0xa438, 0x3002, 0xa438, 0x6c4e, 0xa438, 0xbf8b, + 0xa438, 0x3302, 0xa438, 0x6c6d, 0xa438, 0xf729, 0xa438, 0xbf8b, + 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0xf629, 0xa438, 0xbf8b, + 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0x0c64, 0xa438, 0xef46, + 0xa438, 0xbf8b, 0xa438, 0x6302, 0xa438, 0x6c4e, 0xa438, 0x0289, + 0xa438, 0x9902, 0xa438, 0x3920, 0xa438, 0xaf89, 0xa438, 0x96a0, + 0xa438, 0x0249, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x06e5, + 0xa438, 0x8307, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, + 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, + 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, + 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, + 0xa438, 0xf72a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, + 0xa438, 0xf62a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, + 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6602, + 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, + 0xa438, 0xaf89, 0xa438, 0x96ef, 0xa438, 0x47e4, 0xa438, 0x8308, + 0xa438, 0xe583, 0xa438, 0x09bf, 0xa438, 0xc25f, 0xa438, 0x1a95, + 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xd8f6, + 0xa438, 0x051f, 0xa438, 0x11ef, 0xa438, 0x60bf, 0xa438, 0x8b30, + 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b33, 0xa438, 0x026c, + 0xa438, 0x6df7, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, + 0xa438, 0x4ef6, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, + 0xa438, 0x4e0c, 0xa438, 0x64ef, 0xa438, 0x46bf, 0xa438, 0x8b69, + 0xa438, 0x026c, 0xa438, 0x4e02, 0xa438, 0x8999, 0xa438, 0x0239, + 0xa438, 0x20af, 0xa438, 0x8996, 0xa438, 0xaf39, 0xa438, 0x1ef8, + 0xa438, 0xf9fa, 0xa438, 0xe08f, 0xa438, 0xb838, 0xa438, 0x02ad, + 0xa438, 0x2702, 0xa438, 0xae03, 0xa438, 0xaf8b, 0xa438, 0x201f, + 0xa438, 0x66ef, 0xa438, 0x65bf, 0xa438, 0xc21f, 0xa438, 0x1a96, + 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdaf6, + 0xa438, 0x05bf, 0xa438, 0xc22f, 0xa438, 0x1a96, 0xa438, 0xf705, + 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdbf6, 0xa438, 0x05ef, + 0xa438, 0x021f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b3c, + 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021b, 0xa438, 0x031f, + 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b36, 0xa438, 0x026c, + 0xa438, 0x4eef, 0xa438, 0x021a, 0xa438, 0x031f, 0xa438, 0x110d, + 0xa438, 0x42bf, 0xa438, 0x8b39, 0xa438, 0x026c, 0xa438, 0x4ebf, + 0xa438, 0xc23f, 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, + 0xa438, 0xd200, 0xa438, 0xdaf6, 0xa438, 0x05bf, 0xa438, 0xc24f, + 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, + 0xa438, 0xdbf6, 0xa438, 0x05ef, 0xa438, 0x021f, 0xa438, 0x110d, + 0xa438, 0x42bf, 0xa438, 0x8b45, 0xa438, 0x026c, 0xa438, 0x4eef, + 0xa438, 0x021b, 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, + 0xa438, 0x8b3f, 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021a, + 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b42, + 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x56d0, 0xa438, 0x201f, + 0xa438, 0x11bf, 0xa438, 0x8b4e, 0xa438, 0x026c, 0xa438, 0x4ebf, + 0xa438, 0x8b48, 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b4b, + 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8578, 0xa438, 0xef03, + 0xa438, 0x480a, 0xa438, 0x2805, 0xa438, 0xef20, 0xa438, 0x1b01, + 0xa438, 0xad27, 0xa438, 0x3f1f, 0xa438, 0x44e0, 0xa438, 0x8560, + 0xa438, 0xe185, 0xa438, 0x61bf, 0xa438, 0x8b51, 0xa438, 0x026c, + 0xa438, 0x4ee0, 0xa438, 0x8566, 0xa438, 0xe185, 0xa438, 0x67bf, + 0xa438, 0x8b54, 0xa438, 0x026c, 0xa438, 0x4ee0, 0xa438, 0x856c, + 0xa438, 0xe185, 0xa438, 0x6dbf, 0xa438, 0x8b57, 0xa438, 0x026c, + 0xa438, 0x4ee0, 0xa438, 0x8572, 0xa438, 0xe185, 0xa438, 0x73bf, + 0xa438, 0x8b5a, 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8fb8, + 0xa438, 0x5900, 0xa438, 0xf728, 0xa438, 0xe58f, 0xa438, 0xb8af, + 0xa438, 0x8b2c, 0xa438, 0xe185, 0xa438, 0x791b, 0xa438, 0x21ad, + 0xa438, 0x373e, 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x62e1, + 0xa438, 0x8563, 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, + 0xa438, 0xe085, 0xa438, 0x68e1, 0xa438, 0x8569, 0xa438, 0xbf8b, + 0xa438, 0x5402, 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x6ee1, + 0xa438, 0x856f, 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, + 0xa438, 0xe085, 0xa438, 0x74e1, 0xa438, 0x8575, 0xa438, 0xbf8b, + 0xa438, 0x5a02, 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, + 0xa438, 0x00f7, 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae4a, + 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x64e1, 0xa438, 0x8565, + 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, 0xa438, 0xe085, + 0xa438, 0x6ae1, 0xa438, 0x856b, 0xa438, 0xbf8b, 0xa438, 0x5402, + 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x70e1, 0xa438, 0x8571, + 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, 0xa438, 0xe085, + 0xa438, 0x76e1, 0xa438, 0x8577, 0xa438, 0xbf8b, 0xa438, 0x5a02, + 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, 0xa438, 0x00f7, + 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae0c, 0xa438, 0xe18f, + 0xa438, 0xb839, 0xa438, 0x04ac, 0xa438, 0x2f04, 0xa438, 0xee8f, + 0xa438, 0xb800, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf0ac, + 0xa438, 0x8efc, 0xa438, 0xac8c, 0xa438, 0xf0ac, 0xa438, 0xfaf0, + 0xa438, 0xacf8, 0xa438, 0xf0ac, 0xa438, 0xf6f0, 0xa438, 0xad00, + 0xa438, 0xf0ac, 0xa438, 0xfef0, 0xa438, 0xacfc, 0xa438, 0xf0ac, + 0xa438, 0xf4f0, 0xa438, 0xacf2, 0xa438, 0xf0ac, 0xa438, 0xf0f0, + 0xa438, 0xacb0, 0xa438, 0xf0ac, 0xa438, 0xaef0, 0xa438, 0xacac, + 0xa438, 0xf0ac, 0xa438, 0xaaf0, 0xa438, 0xacee, 0xa438, 0xf0b0, + 0xa438, 0x24f0, 0xa438, 0xb0a4, 0xa438, 0xf0b1, 0xa438, 0x24f0, + 0xa438, 0xb1a4, 0xa438, 0xee8f, 0xa438, 0xb800, 0xa438, 0xd400, + 0xa438, 0x00af, 0xa438, 0x3976, 0xa438, 0x66ac, 0xa438, 0xeabb, + 0xa438, 0xa430, 0xa438, 0x6e50, 0xa438, 0x6e53, 0xa438, 0x6e56, + 0xa438, 0x6e59, 0xa438, 0x6e5c, 0xa438, 0x6e5f, 0xa438, 0x6e62, + 0xa438, 0x6e65, 0xa438, 0xd9ac, 0xa438, 0x70f0, 0xa438, 0xac6a, + 0xa436, 0xb85e, 0xa438, 0x23b7, 0xa436, 0xb860, 0xa438, 0x74db, + 0xa436, 0xb862, 0xa438, 0x268c, 0xa436, 0xb864, 0xa438, 0x3FE5, + 0xa436, 0xb886, 0xa438, 0x2250, 0xa436, 0xb888, 0xa438, 0x140e, + 0xa436, 0xb88a, 0xa438, 0x3696, 0xa436, 0xb88c, 0xa438, 0x3973, + 0xa436, 0xb838, 0xa438, 0x00ff, 0xb820, 0x0010, 0xa436, 0x8464, + 0xa438, 0xaf84, 0xa438, 0x7caf, 0xa438, 0x8485, 0xa438, 0xaf85, + 0xa438, 0x13af, 0xa438, 0x851e, 0xa438, 0xaf85, 0xa438, 0xb9af, + 0xa438, 0x8684, 0xa438, 0xaf87, 0xa438, 0x01af, 0xa438, 0x8701, + 0xa438, 0xac38, 0xa438, 0x03af, 0xa438, 0x38bb, 0xa438, 0xaf38, + 0xa438, 0xc302, 0xa438, 0x4618, 0xa438, 0xbf85, 0xa438, 0x0a02, + 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x1002, 0xa438, 0x54c0, + 0xa438, 0xd400, 0xa438, 0x0fbf, 0xa438, 0x8507, 0xa438, 0x024f, + 0xa438, 0x48bf, 0xa438, 0x8504, 0xa438, 0x024f, 0xa438, 0x6759, + 0xa438, 0xf0a1, 0xa438, 0x3008, 0xa438, 0xbf85, 0xa438, 0x0d02, + 0xa438, 0x54c0, 0xa438, 0xae06, 0xa438, 0xbf85, 0xa438, 0x0d02, + 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x0402, 0xa438, 0x4f67, + 0xa438, 0xa183, 0xa438, 0x02ae, 0xa438, 0x15a1, 0xa438, 0x8502, + 0xa438, 0xae10, 0xa438, 0x59f0, 0xa438, 0xa180, 0xa438, 0x16bf, + 0xa438, 0x8501, 0xa438, 0x024f, 0xa438, 0x67a1, 0xa438, 0x381b, + 0xa438, 0xae0b, 0xa438, 0xe18f, 0xa438, 0xffbf, 0xa438, 0x84fe, + 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x17bf, 0xa438, 0x84fe, + 0xa438, 0x0254, 0xa438, 0xb7bf, 0xa438, 0x84fb, 0xa438, 0x0254, + 0xa438, 0xb7ae, 0xa438, 0x09a1, 0xa438, 0x5006, 0xa438, 0xbf84, + 0xa438, 0xfb02, 0xa438, 0x54c0, 0xa438, 0xaf04, 0xa438, 0x4700, + 0xa438, 0xad34, 0xa438, 0xfdad, 0xa438, 0x0670, 0xa438, 0xae14, + 0xa438, 0xf0a6, 0xa438, 0x00b8, 0xa438, 0xbd32, 0xa438, 0x30bd, + 0xa438, 0x30aa, 0xa438, 0xbd2c, 0xa438, 0xccbd, 0xa438, 0x2ca1, + 0xa438, 0x0705, 0xa438, 0xec80, 0xa438, 0xaf40, 0xa438, 0xf7af, + 0xa438, 0x40f5, 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, + 0xa438, 0x4f48, 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, + 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, + 0xa438, 0x024d, 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, + 0xa438, 0x67bf, 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, + 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, + 0xa438, 0x85b3, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, + 0xa438, 0xddbf, 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, + 0xa438, 0x8ffa, 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, + 0xa438, 0x024f, 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, + 0xa438, 0xad02, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, + 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, + 0xa438, 0xfcdd, 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, + 0xa438, 0xbf8f, 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, + 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, + 0xa438, 0xa702, 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0xa102, + 0xa438, 0x54b7, 0xa438, 0xaf3c, 0xa438, 0x2066, 0xa438, 0xb800, + 0xa438, 0xb8bd, 0xa438, 0x30ee, 0xa438, 0xbd2c, 0xa438, 0xb8bd, + 0xa438, 0x7040, 0xa438, 0xbd86, 0xa438, 0xc8bd, 0xa438, 0x8640, + 0xa438, 0xbd88, 0xa438, 0xc8bd, 0xa438, 0x8802, 0xa438, 0x1929, + 0xa438, 0xa202, 0xa438, 0x02ae, 0xa438, 0x03a2, 0xa438, 0x032e, + 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, + 0xa438, 0xe18f, 0xa438, 0xf7bf, 0xa438, 0x85ad, 0xa438, 0x024f, + 0xa438, 0x48e1, 0xa438, 0x8ff8, 0xa438, 0xbf85, 0xa438, 0xb002, + 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf9bf, 0xa438, 0x85b3, + 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ffa, 0xa438, 0xbf85, + 0xa438, 0xb602, 0xa438, 0x4f48, 0xa438, 0xae2c, 0xa438, 0xd100, + 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0xe18f, + 0xa438, 0xfbbf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x48e1, + 0xa438, 0x8ffc, 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f48, + 0xa438, 0xe18f, 0xa438, 0xfdbf, 0xa438, 0x85b3, 0xa438, 0x024f, + 0xa438, 0x48e1, 0xa438, 0x8ffe, 0xa438, 0xbf85, 0xa438, 0xb602, + 0xa438, 0x4f48, 0xa438, 0xbf86, 0xa438, 0x7e02, 0xa438, 0x4f67, + 0xa438, 0xa100, 0xa438, 0x02ae, 0xa438, 0x25a1, 0xa438, 0x041d, + 0xa438, 0xe18f, 0xa438, 0xf1bf, 0xa438, 0x8675, 0xa438, 0x024f, + 0xa438, 0x48e1, 0xa438, 0x8ff2, 0xa438, 0xbf86, 0xa438, 0x7802, + 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf3bf, 0xa438, 0x867b, + 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x29a1, 0xa438, 0x070b, + 0xa438, 0xae24, 0xa438, 0xbf86, 0xa438, 0x8102, 0xa438, 0x4f67, + 0xa438, 0xad28, 0xa438, 0x1be1, 0xa438, 0x8ff4, 0xa438, 0xbf86, + 0xa438, 0x7502, 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf5bf, + 0xa438, 0x8678, 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ff6, + 0xa438, 0xbf86, 0xa438, 0x7b02, 0xa438, 0x4f48, 0xa438, 0xaf09, + 0xa438, 0x8420, 0xa438, 0xbc32, 0xa438, 0x20bc, 0xa438, 0x3e76, + 0xa438, 0xbc08, 0xa438, 0xfda6, 0xa438, 0x1a00, 0xa438, 0xb64e, + 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, 0xa438, 0x4f48, + 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, 0xa438, 0xd10f, + 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0x024d, + 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x67bf, + 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, 0xa438, 0x024f, + 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, 0xa438, 0x85b3, + 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, 0xa438, 0xddbf, + 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ffa, + 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, 0xa438, 0x024f, + 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, 0xa438, 0xad02, + 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, 0xa438, 0xbf85, + 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfcdd, + 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, 0xa438, 0xbf8f, + 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, 0xa438, 0x4f67, + 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, 0xa438, 0xa702, + 0xa438, 0x54b7, 0xa438, 0xaf00, 0xa438, 0x8800, 0xa436, 0xb818, + 0xa438, 0x38b8, 0xa436, 0xb81a, 0xa438, 0x0444, 0xa436, 0xb81c, + 0xa438, 0x40ee, 0xa436, 0xb81e, 0xa438, 0x3C1A, 0xa436, 0xb850, + 0xa438, 0x0981, 0xa436, 0xb852, 0xa438, 0x0085, 0xa436, 0xb878, + 0xa438, 0xffff, 0xa436, 0xb884, 0xa438, 0xffff, 0xa436, 0xb832, + 0xa438, 0x003f, 0xa436, 0x0000, 0xa438, 0x0000, 0xa436, 0xB82E, + 0xa438, 0x0000, 0xa436, 0x8024, 0xa438, 0x0000, 0xb820, 0x0000, + 0xa436, 0x801E, 0xa438, 0x0021, 0xFFFF, 0xFFFF +}; + +static const u16 phy_mcu_ram_code_8125b_2[] = { + 0xa436, 0x8024, 0xa438, 0x3701, 0xa436, 0xB82E, 0xa438, 0x0001, + 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, + 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, + 0xa438, 0x1800, 0xa438, 0x801a, 0xa438, 0x1800, 0xa438, 0x803f, + 0xa438, 0x1800, 0xa438, 0x8045, 0xa438, 0x1800, 0xa438, 0x8067, + 0xa438, 0x1800, 0xa438, 0x806d, 0xa438, 0x1800, 0xa438, 0x8079, + 0xa438, 0x1800, 0xa438, 0x807e, 0xa438, 0xd093, 0xa438, 0xd1c4, + 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd704, 0xa438, 0x5fbc, + 0xa438, 0xd504, 0xa438, 0xc9f1, 0xa438, 0x1800, 0xa438, 0x0fc9, + 0xa438, 0xbb50, 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd504, + 0xa438, 0x8c0f, 0xa438, 0xd500, 0xa438, 0x1000, 0xa438, 0x1519, + 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd75e, 0xa438, 0x5fae, + 0xa438, 0x9b50, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd75e, + 0xa438, 0x7fae, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd707, + 0xa438, 0x40a7, 0xa438, 0xd719, 0xa438, 0x4071, 0xa438, 0x1800, + 0xa438, 0x1557, 0xa438, 0xd719, 0xa438, 0x2f70, 0xa438, 0x803b, + 0xa438, 0x2f73, 0xa438, 0x156a, 0xa438, 0x5e70, 0xa438, 0x1800, + 0xa438, 0x155d, 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd500, + 0xa438, 0xffed, 0xa438, 0xd709, 0xa438, 0x4054, 0xa438, 0xa788, + 0xa438, 0xd70b, 0xa438, 0x1800, 0xa438, 0x172a, 0xa438, 0xc0c1, + 0xa438, 0xc0c0, 0xa438, 0xd05a, 0xa438, 0xd1ba, 0xa438, 0xd701, + 0xa438, 0x2529, 0xa438, 0x022a, 0xa438, 0xd0a7, 0xa438, 0xd1b9, + 0xa438, 0xa208, 0xa438, 0x1000, 0xa438, 0x080e, 0xa438, 0xd701, + 0xa438, 0x408b, 0xa438, 0x1000, 0xa438, 0x0a65, 0xa438, 0xf003, + 0xa438, 0x1000, 0xa438, 0x0a6b, 0xa438, 0xd701, 0xa438, 0x1000, + 0xa438, 0x0920, 0xa438, 0x1000, 0xa438, 0x0915, 0xa438, 0x1000, + 0xa438, 0x0909, 0xa438, 0x228f, 0xa438, 0x804e, 0xa438, 0x9801, + 0xa438, 0xd71e, 0xa438, 0x5d61, 0xa438, 0xd701, 0xa438, 0x1800, + 0xa438, 0x022a, 0xa438, 0x2005, 0xa438, 0x091a, 0xa438, 0x3bd9, + 0xa438, 0x0919, 0xa438, 0x1800, 0xa438, 0x0916, 0xa438, 0x1000, + 0xa438, 0x14c5, 0xa438, 0xd703, 0xa438, 0x3181, 0xa438, 0x8077, + 0xa438, 0x60ad, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd703, + 0xa438, 0x5fba, 0xa438, 0x1800, 0xa438, 0x0cc7, 0xa438, 0xd096, + 0xa438, 0xd1a9, 0xa438, 0xd503, 0xa438, 0x1800, 0xa438, 0x0c94, + 0xa438, 0xa802, 0xa438, 0xa301, 0xa438, 0xa801, 0xa438, 0xc004, + 0xa438, 0xd710, 0xa438, 0x4000, 0xa438, 0x1800, 0xa438, 0x1e79, + 0xa436, 0xA026, 0xa438, 0x1e78, 0xa436, 0xA024, 0xa438, 0x0c93, + 0xa436, 0xA022, 0xa438, 0x0cc5, 0xa436, 0xA020, 0xa438, 0x0915, + 0xa436, 0xA006, 0xa438, 0x020a, 0xa436, 0xA004, 0xa438, 0x1726, + 0xa436, 0xA002, 0xa438, 0x1542, 0xa436, 0xA000, 0xa438, 0x0fc7, + 0xa436, 0xA008, 0xa438, 0xff00, 0xa436, 0xA016, 0xa438, 0x0010, + 0xa436, 0xA012, 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, + 0xa438, 0x8010, 0xa438, 0x1800, 0xa438, 0x801d, 0xa438, 0x1800, + 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, + 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, + 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0xd700, + 0xa438, 0x6090, 0xa438, 0x60d1, 0xa438, 0xc95c, 0xa438, 0xf007, + 0xa438, 0x60b1, 0xa438, 0xc95a, 0xa438, 0xf004, 0xa438, 0xc956, + 0xa438, 0xf002, 0xa438, 0xc94e, 0xa438, 0x1800, 0xa438, 0x00cd, + 0xa438, 0xd700, 0xa438, 0x6090, 0xa438, 0x60d1, 0xa438, 0xc95c, + 0xa438, 0xf007, 0xa438, 0x60b1, 0xa438, 0xc95a, 0xa438, 0xf004, + 0xa438, 0xc956, 0xa438, 0xf002, 0xa438, 0xc94e, 0xa438, 0x1000, + 0xa438, 0x022a, 0xa438, 0x1800, 0xa438, 0x0132, 0xa436, 0xA08E, + 0xa438, 0xffff, 0xa436, 0xA08C, 0xa438, 0xffff, 0xa436, 0xA08A, + 0xa438, 0xffff, 0xa436, 0xA088, 0xa438, 0xffff, 0xa436, 0xA086, + 0xa438, 0xffff, 0xa436, 0xA084, 0xa438, 0xffff, 0xa436, 0xA082, + 0xa438, 0x012f, 0xa436, 0xA080, 0xa438, 0x00cc, 0xa436, 0xA090, + 0xa438, 0x0103, 0xa436, 0xA016, 0xa438, 0x0020, 0xa436, 0xA012, + 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, + 0xa438, 0x1800, 0xa438, 0x8020, 0xa438, 0x1800, 0xa438, 0x802a, + 0xa438, 0x1800, 0xa438, 0x8035, 0xa438, 0x1800, 0xa438, 0x803c, + 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0x1800, 0xa438, 0x803c, + 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0xd107, 0xa438, 0xd042, + 0xa438, 0xa404, 0xa438, 0x1000, 0xa438, 0x09df, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0x8280, 0xa438, 0xd700, 0xa438, 0x6065, + 0xa438, 0xd125, 0xa438, 0xf002, 0xa438, 0xd12b, 0xa438, 0xd040, + 0xa438, 0x1800, 0xa438, 0x077f, 0xa438, 0x0cf0, 0xa438, 0x0c50, + 0xa438, 0xd104, 0xa438, 0xd040, 0xa438, 0x1000, 0xa438, 0x0aa8, + 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x1800, 0xa438, 0x0a2e, + 0xa438, 0xcb9b, 0xa438, 0xd110, 0xa438, 0xd040, 0xa438, 0x1000, + 0xa438, 0x0b7b, 0xa438, 0x1000, 0xa438, 0x09df, 0xa438, 0xd700, + 0xa438, 0x5fb4, 0xa438, 0x1800, 0xa438, 0x081b, 0xa438, 0x1000, + 0xa438, 0x09df, 0xa438, 0xd704, 0xa438, 0x7fb8, 0xa438, 0xa718, + 0xa438, 0x1800, 0xa438, 0x074e, 0xa436, 0xA10E, 0xa438, 0xffff, + 0xa436, 0xA10C, 0xa438, 0xffff, 0xa436, 0xA10A, 0xa438, 0xffff, + 0xa436, 0xA108, 0xa438, 0xffff, 0xa436, 0xA106, 0xa438, 0x074d, + 0xa436, 0xA104, 0xa438, 0x0818, 0xa436, 0xA102, 0xa438, 0x0a2c, + 0xa436, 0xA100, 0xa438, 0x077e, 0xa436, 0xA110, 0xa438, 0x000f, + 0xa436, 0xb87c, 0xa438, 0x8625, 0xa436, 0xb87e, 0xa438, 0xaf86, + 0xa438, 0x3daf, 0xa438, 0x8689, 0xa438, 0xaf88, 0xa438, 0x69af, + 0xa438, 0x8887, 0xa438, 0xaf88, 0xa438, 0x9caf, 0xa438, 0x889c, + 0xa438, 0xaf88, 0xa438, 0x9caf, 0xa438, 0x889c, 0xa438, 0xbf86, + 0xa438, 0x49d7, 0xa438, 0x0040, 0xa438, 0x0277, 0xa438, 0x7daf, + 0xa438, 0x2727, 0xa438, 0x0000, 0xa438, 0x7205, 0xa438, 0x0000, + 0xa438, 0x7208, 0xa438, 0x0000, 0xa438, 0x71f3, 0xa438, 0x0000, + 0xa438, 0x71f6, 0xa438, 0x0000, 0xa438, 0x7229, 0xa438, 0x0000, + 0xa438, 0x722c, 0xa438, 0x0000, 0xa438, 0x7217, 0xa438, 0x0000, + 0xa438, 0x721a, 0xa438, 0x0000, 0xa438, 0x721d, 0xa438, 0x0000, + 0xa438, 0x7211, 0xa438, 0x0000, 0xa438, 0x7220, 0xa438, 0x0000, + 0xa438, 0x7214, 0xa438, 0x0000, 0xa438, 0x722f, 0xa438, 0x0000, + 0xa438, 0x7223, 0xa438, 0x0000, 0xa438, 0x7232, 0xa438, 0x0000, + 0xa438, 0x7226, 0xa438, 0xf8f9, 0xa438, 0xfae0, 0xa438, 0x85b3, + 0xa438, 0x3802, 0xa438, 0xad27, 0xa438, 0x02ae, 0xa438, 0x03af, + 0xa438, 0x8830, 0xa438, 0x1f66, 0xa438, 0xef65, 0xa438, 0xbfc2, + 0xa438, 0x1f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, + 0xa438, 0x00da, 0xa438, 0xf605, 0xa438, 0xbfc2, 0xa438, 0x2f1a, + 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00db, + 0xa438, 0xf605, 0xa438, 0xef02, 0xa438, 0x1f11, 0xa438, 0x0d42, + 0xa438, 0xbf88, 0xa438, 0x4202, 0xa438, 0x6e7d, 0xa438, 0xef02, + 0xa438, 0x1b03, 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, + 0xa438, 0x4502, 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1a03, + 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4802, + 0xa438, 0x6e7d, 0xa438, 0xbfc2, 0xa438, 0x3f1a, 0xa438, 0x96f7, + 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00da, 0xa438, 0xf605, + 0xa438, 0xbfc2, 0xa438, 0x4f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, + 0xa438, 0xffd2, 0xa438, 0x00db, 0xa438, 0xf605, 0xa438, 0xef02, + 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4b02, + 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1b03, 0xa438, 0x1f11, + 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4e02, 0xa438, 0x6e7d, + 0xa438, 0xef02, 0xa438, 0x1a03, 0xa438, 0x1f11, 0xa438, 0x0d42, + 0xa438, 0xbf88, 0xa438, 0x5102, 0xa438, 0x6e7d, 0xa438, 0xef56, + 0xa438, 0xd020, 0xa438, 0x1f11, 0xa438, 0xbf88, 0xa438, 0x5402, + 0xa438, 0x6e7d, 0xa438, 0xbf88, 0xa438, 0x5702, 0xa438, 0x6e7d, + 0xa438, 0xbf88, 0xa438, 0x5a02, 0xa438, 0x6e7d, 0xa438, 0xe185, + 0xa438, 0xa0ef, 0xa438, 0x0348, 0xa438, 0x0a28, 0xa438, 0x05ef, + 0xa438, 0x201b, 0xa438, 0x01ad, 0xa438, 0x2735, 0xa438, 0x1f44, + 0xa438, 0xe085, 0xa438, 0x88e1, 0xa438, 0x8589, 0xa438, 0xbf88, + 0xa438, 0x5d02, 0xa438, 0x6e7d, 0xa438, 0xe085, 0xa438, 0x8ee1, + 0xa438, 0x858f, 0xa438, 0xbf88, 0xa438, 0x6002, 0xa438, 0x6e7d, + 0xa438, 0xe085, 0xa438, 0x94e1, 0xa438, 0x8595, 0xa438, 0xbf88, + 0xa438, 0x6302, 0xa438, 0x6e7d, 0xa438, 0xe085, 0xa438, 0x9ae1, + 0xa438, 0x859b, 0xa438, 0xbf88, 0xa438, 0x6602, 0xa438, 0x6e7d, + 0xa438, 0xaf88, 0xa438, 0x3cbf, 0xa438, 0x883f, 0xa438, 0x026e, + 0xa438, 0x9cad, 0xa438, 0x2835, 0xa438, 0x1f44, 0xa438, 0xe08f, + 0xa438, 0xf8e1, 0xa438, 0x8ff9, 0xa438, 0xbf88, 0xa438, 0x5d02, + 0xa438, 0x6e7d, 0xa438, 0xe08f, 0xa438, 0xfae1, 0xa438, 0x8ffb, + 0xa438, 0xbf88, 0xa438, 0x6002, 0xa438, 0x6e7d, 0xa438, 0xe08f, + 0xa438, 0xfce1, 0xa438, 0x8ffd, 0xa438, 0xbf88, 0xa438, 0x6302, + 0xa438, 0x6e7d, 0xa438, 0xe08f, 0xa438, 0xfee1, 0xa438, 0x8fff, + 0xa438, 0xbf88, 0xa438, 0x6602, 0xa438, 0x6e7d, 0xa438, 0xaf88, + 0xa438, 0x3ce1, 0xa438, 0x85a1, 0xa438, 0x1b21, 0xa438, 0xad37, + 0xa438, 0x341f, 0xa438, 0x44e0, 0xa438, 0x858a, 0xa438, 0xe185, + 0xa438, 0x8bbf, 0xa438, 0x885d, 0xa438, 0x026e, 0xa438, 0x7de0, + 0xa438, 0x8590, 0xa438, 0xe185, 0xa438, 0x91bf, 0xa438, 0x8860, + 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8596, 0xa438, 0xe185, + 0xa438, 0x97bf, 0xa438, 0x8863, 0xa438, 0x026e, 0xa438, 0x7de0, + 0xa438, 0x859c, 0xa438, 0xe185, 0xa438, 0x9dbf, 0xa438, 0x8866, + 0xa438, 0x026e, 0xa438, 0x7dae, 0xa438, 0x401f, 0xa438, 0x44e0, + 0xa438, 0x858c, 0xa438, 0xe185, 0xa438, 0x8dbf, 0xa438, 0x885d, + 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8592, 0xa438, 0xe185, + 0xa438, 0x93bf, 0xa438, 0x8860, 0xa438, 0x026e, 0xa438, 0x7de0, + 0xa438, 0x8598, 0xa438, 0xe185, 0xa438, 0x99bf, 0xa438, 0x8863, + 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x859e, 0xa438, 0xe185, + 0xa438, 0x9fbf, 0xa438, 0x8866, 0xa438, 0x026e, 0xa438, 0x7dae, + 0xa438, 0x0ce1, 0xa438, 0x85b3, 0xa438, 0x3904, 0xa438, 0xac2f, + 0xa438, 0x04ee, 0xa438, 0x85b3, 0xa438, 0x00af, 0xa438, 0x39d9, + 0xa438, 0x22ac, 0xa438, 0xeaf0, 0xa438, 0xacf6, 0xa438, 0xf0ac, + 0xa438, 0xfaf0, 0xa438, 0xacf8, 0xa438, 0xf0ac, 0xa438, 0xfcf0, + 0xa438, 0xad00, 0xa438, 0xf0ac, 0xa438, 0xfef0, 0xa438, 0xacf0, + 0xa438, 0xf0ac, 0xa438, 0xf4f0, 0xa438, 0xacf2, 0xa438, 0xf0ac, + 0xa438, 0xb0f0, 0xa438, 0xacae, 0xa438, 0xf0ac, 0xa438, 0xacf0, + 0xa438, 0xacaa, 0xa438, 0xa100, 0xa438, 0x0ce1, 0xa438, 0x8ff7, + 0xa438, 0xbf88, 0xa438, 0x8402, 0xa438, 0x6e7d, 0xa438, 0xaf26, + 0xa438, 0xe9e1, 0xa438, 0x8ff6, 0xa438, 0xbf88, 0xa438, 0x8402, + 0xa438, 0x6e7d, 0xa438, 0xaf26, 0xa438, 0xf520, 0xa438, 0xac86, + 0xa438, 0xbf88, 0xa438, 0x3f02, 0xa438, 0x6e9c, 0xa438, 0xad28, + 0xa438, 0x03af, 0xa438, 0x3324, 0xa438, 0xad38, 0xa438, 0x03af, + 0xa438, 0x32e6, 0xa438, 0xaf32, 0xa438, 0xfb00, 0xa436, 0xb87c, + 0xa438, 0x8ff6, 0xa436, 0xb87e, 0xa438, 0x0705, 0xa436, 0xb87c, + 0xa438, 0x8ff8, 0xa436, 0xb87e, 0xa438, 0x19cc, 0xa436, 0xb87c, + 0xa438, 0x8ffa, 0xa436, 0xb87e, 0xa438, 0x28e3, 0xa436, 0xb87c, + 0xa438, 0x8ffc, 0xa436, 0xb87e, 0xa438, 0x1047, 0xa436, 0xb87c, + 0xa438, 0x8ffe, 0xa436, 0xb87e, 0xa438, 0x0a45, 0xa436, 0xb85e, + 0xa438, 0x271E, 0xa436, 0xb860, 0xa438, 0x3846, 0xa436, 0xb862, + 0xa438, 0x26E6, 0xa436, 0xb864, 0xa438, 0x32E3, 0xa436, 0xb886, + 0xa438, 0xffff, 0xa436, 0xb888, 0xa438, 0xffff, 0xa436, 0xb88a, + 0xa438, 0xffff, 0xa436, 0xb88c, 0xa438, 0xffff, 0xa436, 0xb838, + 0xa438, 0x000f, 0xb820, 0x0010, 0xa436, 0x846e, 0xa438, 0xaf84, + 0xa438, 0x86af, 0xa438, 0x8690, 0xa438, 0xaf86, 0xa438, 0xa4af, + 0xa438, 0x86a4, 0xa438, 0xaf86, 0xa438, 0xa4af, 0xa438, 0x86a4, + 0xa438, 0xaf86, 0xa438, 0xa4af, 0xa438, 0x86a4, 0xa438, 0xee82, + 0xa438, 0x5f00, 0xa438, 0x0284, 0xa438, 0x90af, 0xa438, 0x0441, + 0xa438, 0xf8e0, 0xa438, 0x8ff3, 0xa438, 0xa000, 0xa438, 0x0502, + 0xa438, 0x84a4, 0xa438, 0xae06, 0xa438, 0xa001, 0xa438, 0x0302, + 0xa438, 0x84c8, 0xa438, 0xfc04, 0xa438, 0xf8f9, 0xa438, 0xef59, + 0xa438, 0xe080, 0xa438, 0x15ad, 0xa438, 0x2702, 0xa438, 0xae03, + 0xa438, 0xaf84, 0xa438, 0xc3bf, 0xa438, 0x53ca, 0xa438, 0x0252, + 0xa438, 0xc8ad, 0xa438, 0x2807, 0xa438, 0x0285, 0xa438, 0x2cee, + 0xa438, 0x8ff3, 0xa438, 0x01ef, 0xa438, 0x95fd, 0xa438, 0xfc04, + 0xa438, 0xf8f9, 0xa438, 0xfaef, 0xa438, 0x69bf, 0xa438, 0x53ca, + 0xa438, 0x0252, 0xa438, 0xc8ac, 0xa438, 0x2822, 0xa438, 0xd480, + 0xa438, 0x00bf, 0xa438, 0x8684, 0xa438, 0x0252, 0xa438, 0xa9bf, + 0xa438, 0x8687, 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868a, + 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868d, 0xa438, 0x0252, + 0xa438, 0xa9ee, 0xa438, 0x8ff3, 0xa438, 0x00af, 0xa438, 0x8526, + 0xa438, 0xe08f, 0xa438, 0xf4e1, 0xa438, 0x8ff5, 0xa438, 0xe28f, + 0xa438, 0xf6e3, 0xa438, 0x8ff7, 0xa438, 0x1b45, 0xa438, 0xac27, + 0xa438, 0x0eee, 0xa438, 0x8ff4, 0xa438, 0x00ee, 0xa438, 0x8ff5, + 0xa438, 0x0002, 0xa438, 0x852c, 0xa438, 0xaf85, 0xa438, 0x26e0, + 0xa438, 0x8ff4, 0xa438, 0xe18f, 0xa438, 0xf52c, 0xa438, 0x0001, + 0xa438, 0xe48f, 0xa438, 0xf4e5, 0xa438, 0x8ff5, 0xa438, 0xef96, + 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf8f9, 0xa438, 0xef59, + 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa18b, + 0xa438, 0x02ae, 0xa438, 0x03af, 0xa438, 0x85da, 0xa438, 0xbf57, + 0xa438, 0x7202, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xf8e5, + 0xa438, 0x8ff9, 0xa438, 0xbf57, 0xa438, 0x7502, 0xa438, 0x52c8, + 0xa438, 0xe48f, 0xa438, 0xfae5, 0xa438, 0x8ffb, 0xa438, 0xbf57, + 0xa438, 0x7802, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfce5, + 0xa438, 0x8ffd, 0xa438, 0xbf57, 0xa438, 0x7b02, 0xa438, 0x52c8, + 0xa438, 0xe48f, 0xa438, 0xfee5, 0xa438, 0x8fff, 0xa438, 0xbf57, + 0xa438, 0x6c02, 0xa438, 0x52c8, 0xa438, 0xa102, 0xa438, 0x13ee, + 0xa438, 0x8ffc, 0xa438, 0x80ee, 0xa438, 0x8ffd, 0xa438, 0x00ee, + 0xa438, 0x8ffe, 0xa438, 0x80ee, 0xa438, 0x8fff, 0xa438, 0x00af, + 0xa438, 0x8599, 0xa438, 0xa101, 0xa438, 0x0cbf, 0xa438, 0x534c, + 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x0303, 0xa438, 0xaf85, + 0xa438, 0x77bf, 0xa438, 0x5322, 0xa438, 0x0252, 0xa438, 0xc8a1, + 0xa438, 0x8b02, 0xa438, 0xae03, 0xa438, 0xaf86, 0xa438, 0x64e0, + 0xa438, 0x8ff8, 0xa438, 0xe18f, 0xa438, 0xf9bf, 0xa438, 0x8684, + 0xa438, 0x0252, 0xa438, 0xa9e0, 0xa438, 0x8ffa, 0xa438, 0xe18f, + 0xa438, 0xfbbf, 0xa438, 0x8687, 0xa438, 0x0252, 0xa438, 0xa9e0, + 0xa438, 0x8ffc, 0xa438, 0xe18f, 0xa438, 0xfdbf, 0xa438, 0x868a, + 0xa438, 0x0252, 0xa438, 0xa9e0, 0xa438, 0x8ffe, 0xa438, 0xe18f, + 0xa438, 0xffbf, 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9af, + 0xa438, 0x867f, 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, + 0xa438, 0xa144, 0xa438, 0x3cbf, 0xa438, 0x547b, 0xa438, 0x0252, + 0xa438, 0xc8e4, 0xa438, 0x8ff8, 0xa438, 0xe58f, 0xa438, 0xf9bf, + 0xa438, 0x547e, 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ffa, + 0xa438, 0xe58f, 0xa438, 0xfbbf, 0xa438, 0x5481, 0xa438, 0x0252, + 0xa438, 0xc8e4, 0xa438, 0x8ffc, 0xa438, 0xe58f, 0xa438, 0xfdbf, + 0xa438, 0x5484, 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ffe, + 0xa438, 0xe58f, 0xa438, 0xffbf, 0xa438, 0x5322, 0xa438, 0x0252, + 0xa438, 0xc8a1, 0xa438, 0x4448, 0xa438, 0xaf85, 0xa438, 0xa7bf, + 0xa438, 0x5322, 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x313c, + 0xa438, 0xbf54, 0xa438, 0x7b02, 0xa438, 0x52c8, 0xa438, 0xe48f, + 0xa438, 0xf8e5, 0xa438, 0x8ff9, 0xa438, 0xbf54, 0xa438, 0x7e02, + 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfae5, 0xa438, 0x8ffb, + 0xa438, 0xbf54, 0xa438, 0x8102, 0xa438, 0x52c8, 0xa438, 0xe48f, + 0xa438, 0xfce5, 0xa438, 0x8ffd, 0xa438, 0xbf54, 0xa438, 0x8402, + 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfee5, 0xa438, 0x8fff, + 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa131, + 0xa438, 0x03af, 0xa438, 0x85a7, 0xa438, 0xd480, 0xa438, 0x00bf, + 0xa438, 0x8684, 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x8687, + 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868a, 0xa438, 0x0252, + 0xa438, 0xa9bf, 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9ef, + 0xa438, 0x95fd, 0xa438, 0xfc04, 0xa438, 0xf0d1, 0xa438, 0x2af0, + 0xa438, 0xd12c, 0xa438, 0xf0d1, 0xa438, 0x44f0, 0xa438, 0xd146, + 0xa438, 0xbf86, 0xa438, 0xa102, 0xa438, 0x52c8, 0xa438, 0xbf86, + 0xa438, 0xa102, 0xa438, 0x52c8, 0xa438, 0xd101, 0xa438, 0xaf06, + 0xa438, 0xa570, 0xa438, 0xce42, 0xa436, 0xb818, 0xa438, 0x043d, + 0xa436, 0xb81a, 0xa438, 0x06a3, 0xa436, 0xb81c, 0xa438, 0xffff, + 0xa436, 0xb81e, 0xa438, 0xffff, 0xa436, 0xb850, 0xa438, 0xffff, + 0xa436, 0xb852, 0xa438, 0xffff, 0xa436, 0xb878, 0xa438, 0xffff, + 0xa436, 0xb884, 0xa438, 0xffff, 0xa436, 0xb832, 0xa438, 0x0003, + 0xa436, 0x0000, 0xa438, 0x0000, 0xa436, 0xB82E, 0xa438, 0x0000, + 0xa436, 0x8024, 0xa438, 0x0000, 0xb820, 0x0000, 0xa436, 0x801E, + 0xa438, 0x0020, 0xFFFF, 0xFFFF +}; + +static void +rtl8125_real_set_phy_mcu_8125b_1(struct net_device *dev) +{ + rtl8125_set_phy_mcu_ram_code(dev, + phy_mcu_ram_code_8125b_1, + ARRAY_SIZE(phy_mcu_ram_code_8125b_1) + ); +} + +static void +rtl8125_set_phy_mcu_8125b_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_set_phy_mcu_patch_request(tp); + + rtl8125_real_set_phy_mcu_8125b_1(dev); + + rtl8125_clear_phy_mcu_patch_request(tp); +} + +static void +rtl8125_real_set_phy_mcu_8125b_2(struct net_device *dev) +{ + rtl8125_set_phy_mcu_ram_code(dev, + phy_mcu_ram_code_8125b_2, + ARRAY_SIZE(phy_mcu_ram_code_8125b_2) + ); +} + +static void +rtl8125_set_phy_mcu_8125b_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_set_phy_mcu_patch_request(tp); + + rtl8125_real_set_phy_mcu_8125b_2(dev); + + rtl8125_clear_phy_mcu_patch_request(tp); +} + +static void +rtl8125_init_hw_phy_mcu(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u8 require_disable_phy_disable_mode = FALSE; + + if (tp->NotWrRamCodeToMicroP == TRUE) return; + if (rtl8125_check_hw_phy_mcu_code_ver(dev)) return; + + if (HW_SUPPORT_CHECK_PHY_DISABLE_MODE(tp) && rtl8125_is_in_phy_disable_mode(dev)) + require_disable_phy_disable_mode = TRUE; + + if (require_disable_phy_disable_mode) + rtl8125_disable_phy_disable_mode(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + rtl8125_set_phy_mcu_8125a_1(dev); + break; + case CFG_METHOD_3: + rtl8125_set_phy_mcu_8125a_2(dev); + break; + case CFG_METHOD_4: + rtl8125_set_phy_mcu_8125b_1(dev); + break; + case CFG_METHOD_5: + rtl8125_set_phy_mcu_8125b_2(dev); + break; + } + + if (require_disable_phy_disable_mode) + rtl8125_enable_phy_disable_mode(dev); + + rtl8125_write_hw_phy_mcu_code_ver(dev); + + rtl8125_mdio_write(tp,0x1F, 0x0000); + + tp->HwHasWrRamCodeToMicroP = TRUE; +} +#endif + +static void +rtl8125_enable_phy_aldps(struct rtl8125_private *tp) +{ + //enable aldps + //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) + SetEthPhyOcpBit(tp, 0xA430, BIT_2); +} + +static void +rtl8125_hw_phy_config_8125a_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + ClearAndSetEthPhyOcpBit(tp, + 0xAD40, + 0x03FF, + 0x84 + ); + + SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); + ClearAndSetEthPhyOcpBit(tp, + 0xAD16, + 0x03FF, + 0x0006 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD32, + 0x003F, + 0x0006 + ); + ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); + ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); + ClearAndSetEthPhyOcpBit(tp, + 0xAC8A, + BIT_15|BIT_14|BIT_13|BIT_12, + BIT_14|BIT_13|BIT_12 + ); + SetEthPhyOcpBit(tp, 0xAD18, BIT_10); + SetEthPhyOcpBit(tp, 0xAD1A, 0x3FF); + SetEthPhyOcpBit(tp, 0xAD1C, 0x3FF); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xC400 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EB); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0x0700, + 0x0300 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F8); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x1C00 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F1); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x3000 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80FE); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xA500 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8102); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x5000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8105); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x3300 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8100); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x7000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8104); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xF000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8106); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x6500 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xED00 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); + SetEthPhyOcpBit(tp, 0xA438, BIT_8); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80E1); + ClearEthPhyOcpBit(tp, 0xA438, BIT_8); + + ClearAndSetEthPhyOcpBit(tp, + 0xBF06, + 0x003F, + 0x38 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x819F); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xD0B6); + + mdio_direct_write_phy_ocp(tp, 0xBC34, 0x5555); + ClearAndSetEthPhyOcpBit(tp, + 0xBF0A, + BIT_11|BIT_10|BIT_9, + BIT_11|BIT_9 + ); + + ClearEthPhyOcpBit(tp, 0xA5C0, BIT_10); + + SetEthPhyOcpBit(tp, 0xA442, BIT_11); + + //enable aldps + //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) + if (aspm) { + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + rtl8125_enable_phy_aldps(tp); + } + } +} + +static void +rtl8125_hw_phy_config_8125a_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); + ClearAndSetEthPhyOcpBit(tp, + 0xAD16, + 0x03FF, + 0x03FF + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD32, + 0x003F, + 0x0006 + ); + ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); + ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); + ClearAndSetEthPhyOcpBit(tp, + 0xACC0, + BIT_1|BIT_0, + BIT_1 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD40, + BIT_7|BIT_6|BIT_5, + BIT_6 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD40, + BIT_2|BIT_1|BIT_0, + BIT_2 + ); + ClearEthPhyOcpBit(tp, 0xAC14, BIT_7); + ClearEthPhyOcpBit(tp, 0xAC80, BIT_9|BIT_8); + ClearAndSetEthPhyOcpBit(tp, + 0xAC5E, + BIT_2|BIT_1|BIT_0, + BIT_1 + ); + mdio_direct_write_phy_ocp(tp, 0xAD4C, 0x00A8); + mdio_direct_write_phy_ocp(tp, 0xAC5C, 0x01FF); + ClearAndSetEthPhyOcpBit(tp, + 0xAC8A, + BIT_7|BIT_6|BIT_5|BIT_4, + BIT_5|BIT_4 + ); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); + ClearAndSetEthPhyOcpBit(tp, + 0xB87E, + 0xFF00, + 0x0500 + ); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8159); + ClearAndSetEthPhyOcpBit(tp, + 0xB87E, + 0xFF00, + 0x0700 + ); + + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80A2); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x809C); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x81B3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0043); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00A7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00D6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00EC); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00F6); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FB); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FD); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FF); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x00BB); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0058); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0029); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0013); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0009); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0004); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0002); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8257); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x020F); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x7843); + + + rtl8125_set_phy_mcu_patch_request(tp); + + ClearEthPhyOcpBit(tp, 0xB896, BIT_0); + ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); + + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC091); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC092); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1214); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC094); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1516); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC096); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x171B); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC098); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1B1C); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09A); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1F1F); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09C); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2021); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09E); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2224); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A0); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A2); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A4); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC018); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0AF2); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01A); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0D4A); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01C); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0F26); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01E); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x118D); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC020); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x14F3); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC022); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x175A); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC024); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x19C0); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC026); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1C26); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC089); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6050); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08A); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x5F6E); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08C); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08E); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC090); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); + + SetEthPhyOcpBit(tp, 0xB896, BIT_0); + + rtl8125_clear_phy_mcu_patch_request(tp); + + + SetEthPhyOcpBit(tp, 0xD068, BIT_13); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x81A2); + SetEthPhyOcpBit(tp, 0xA438, BIT_8); + ClearAndSetEthPhyOcpBit(tp, + 0xB54C, + 0xFF00, + 0xDB00); + + + ClearEthPhyOcpBit(tp, 0xA454, BIT_0); + + + SetEthPhyOcpBit(tp, 0xA5D4, BIT_5); + ClearEthPhyOcpBit(tp, 0xAD4E, BIT_4); + ClearEthPhyOcpBit(tp, 0xA86A, BIT_0); + + + SetEthPhyOcpBit(tp, 0xA442, BIT_11); + + + if (tp->RequirePhyMdiSwapPatch) { + u16 adccal_offset_p0; + u16 adccal_offset_p1; + u16 adccal_offset_p2; + u16 adccal_offset_p3; + u16 rg_lpf_cap_xg_p0; + u16 rg_lpf_cap_xg_p1; + u16 rg_lpf_cap_xg_p2; + u16 rg_lpf_cap_xg_p3; + u16 rg_lpf_cap_p0; + u16 rg_lpf_cap_p1; + u16 rg_lpf_cap_p2; + u16 rg_lpf_cap_p3; + + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0007, + 0x0001 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0000 + ); + adccal_offset_p0 = mdio_direct_read_phy_ocp(tp, 0xD06A); + adccal_offset_p0 &= 0x07FF; + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0008 + ); + adccal_offset_p1 = mdio_direct_read_phy_ocp(tp, 0xD06A); + adccal_offset_p1 &= 0x07FF; + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0010 + ); + adccal_offset_p2 = mdio_direct_read_phy_ocp(tp, 0xD06A); + adccal_offset_p2 &= 0x07FF; + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0018 + ); + adccal_offset_p3 = mdio_direct_read_phy_ocp(tp, 0xD06A); + adccal_offset_p3 &= 0x07FF; + + + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0000 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD06A, + 0x07FF, + adccal_offset_p3 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0008 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD06A, + 0x07FF, + adccal_offset_p2 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0010 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD06A, + 0x07FF, + adccal_offset_p1 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD068, + 0x0018, + 0x0018 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xD06A, + 0x07FF, + adccal_offset_p0 + ); + + + rg_lpf_cap_xg_p0 = mdio_direct_read_phy_ocp(tp, 0xBD5A); + rg_lpf_cap_xg_p0 &= 0x001F; + rg_lpf_cap_xg_p1 = mdio_direct_read_phy_ocp(tp, 0xBD5A); + rg_lpf_cap_xg_p1 &= 0x1F00; + rg_lpf_cap_xg_p2 = mdio_direct_read_phy_ocp(tp, 0xBD5C); + rg_lpf_cap_xg_p2 &= 0x001F; + rg_lpf_cap_xg_p3 = mdio_direct_read_phy_ocp(tp, 0xBD5C); + rg_lpf_cap_xg_p3 &= 0x1F00; + rg_lpf_cap_p0 = mdio_direct_read_phy_ocp(tp, 0xBC18); + rg_lpf_cap_p0 &= 0x001F; + rg_lpf_cap_p1 = mdio_direct_read_phy_ocp(tp, 0xBC18); + rg_lpf_cap_p1 &= 0x1F00; + rg_lpf_cap_p2 = mdio_direct_read_phy_ocp(tp, 0xBC1A); + rg_lpf_cap_p2 &= 0x001F; + rg_lpf_cap_p3 = mdio_direct_read_phy_ocp(tp, 0xBC1A); + rg_lpf_cap_p3 &= 0x1F00; + + + ClearAndSetEthPhyOcpBit(tp, + 0xBD5A, + 0x001F, + rg_lpf_cap_xg_p3 >> 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBD5A, + 0x1F00, + rg_lpf_cap_xg_p2 << 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBD5C, + 0x001F, + rg_lpf_cap_xg_p1 >> 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBD5C, + 0x1F00, + rg_lpf_cap_xg_p0 << 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBC18, + 0x001F, + rg_lpf_cap_p3 >> 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBC18, + 0x1F00, + rg_lpf_cap_p2 << 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBC1A, + 0x001F, + rg_lpf_cap_p1 >> 8 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xBC1A, + 0x1F00, + rg_lpf_cap_p0 << 8 + ); + } + + + if (aspm) { + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + rtl8125_enable_phy_aldps(tp); + } + } +} + +static void +rtl8125_hw_phy_config_8125b_1(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + SetEthPhyOcpBit(tp, 0xA442, BIT_11); + + + SetEthPhyOcpBit(tp, 0xBC08, (BIT_3 | BIT_2)); + + + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FFF); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x0400 + ); + } + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8560); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8562); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8564); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8566); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8568); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x856A); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FFE); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0907); + } + ClearAndSetEthPhyOcpBit(tp, + 0xACDA, + 0xFF00, + 0xFF00 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xACDE, + 0xF000, + 0xF000 + ); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80D6); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F2); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F4); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x6077); + mdio_direct_write_phy_ocp(tp, 0xB506, 0x01E7); + mdio_direct_write_phy_ocp(tp, 0xAC8C, 0x0FFC); + mdio_direct_write_phy_ocp(tp, 0xAC46, 0xB7B4); + mdio_direct_write_phy_ocp(tp, 0xAC50, 0x0FBC); + mdio_direct_write_phy_ocp(tp, 0xAC3C, 0x9240); + mdio_direct_write_phy_ocp(tp, 0xAC4E, 0x0DB4); + mdio_direct_write_phy_ocp(tp, 0xACC6, 0x0707); + mdio_direct_write_phy_ocp(tp, 0xACC8, 0xA0D3); + mdio_direct_write_phy_ocp(tp, 0xAD08, 0x0007); + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8013); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0700); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FB9); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBA); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBC); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1900); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBE); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE100); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC0); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0800); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC2); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE500); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC4); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC6); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF100); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC8); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0400); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCa); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF300); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCc); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFD00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCe); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD0); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFB00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD2); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD4); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF400); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD6); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD8); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF600); + + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x813D); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x390E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x814F); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x790E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80B0); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F31); + SetEthPhyOcpBit(tp, 0xBF4C, BIT_1); + SetEthPhyOcpBit(tp, 0xBCCA, (BIT_9 | BIT_8)); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8141); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x320E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8153); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x720E); + ClearEthPhyOcpBit(tp, 0xA432, BIT_6); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8529); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x050E); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x816C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8174); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8178); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x817C); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0719); + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF4); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0400); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0404); + } + mdio_direct_write_phy_ocp(tp, 0xBF4A, 0x001B); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8033); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8037); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803B); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFC32); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803F); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8043); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8047); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); + + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8145); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x370E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x770E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8169); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0D0A); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x817B); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1D0A); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8217); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x5000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x821A); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x5000 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DA); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0403); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x1000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x0384); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BA); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x6C00 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xF009); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BD); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x9F00 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C7); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xf083); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DD); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x03f0); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x1000 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CB); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CE); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x6C00 + ); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C9); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x8009); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80D1); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0x8000 + ); + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A3); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x200A); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A5); + mdio_direct_write_phy_ocp(tp, 0xA438, 0xF0AD); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x809F); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x6073); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A1); + mdio_direct_write_phy_ocp(tp, 0xA438, 0x000B); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A9); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + 0xFF00, + 0xC000 + ); + + rtl8125_set_phy_mcu_patch_request(tp); + + ClearEthPhyOcpBit(tp, 0xB896, BIT_0); + ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); + + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC23E); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0000); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC240); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0103); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC242); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0507); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC244); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x090B); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC246); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x0C0E); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC248); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1012); + mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC24A); + mdio_direct_write_phy_ocp(tp, 0xB890, 0x1416); + + SetEthPhyOcpBit(tp, 0xB896, BIT_0); + + rtl8125_clear_phy_mcu_patch_request(tp); + + + SetEthPhyOcpBit(tp, 0xA86A, BIT_0); + SetEthPhyOcpBit(tp, 0xA6F0, BIT_0); + + + mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); + mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); + mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); + mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); + mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); + ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); + SetEthPhyOcpBit(tp, 0xA438, BIT_12); + + + if (aspm) { + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + rtl8125_enable_phy_aldps(tp); + } + } +} + +static void +rtl8125_hw_phy_config_8125b_2(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + SetEthPhyOcpBit(tp, 0xA442, BIT_11); + + + ClearAndSetEthPhyOcpBit(tp, + 0xAC46, + 0x00F0, + 0x0090 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xAD30, + 0x0003, + 0x0001 + ); + + + RTL_W16(tp, EEE_TXIDLE_TIMER_8125, tp->eee.tx_lpi_timer); + + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F5); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x760E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8107); + mdio_direct_write_phy_ocp(tp, 0xB87E, 0x360E); + mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8551); + ClearAndSetEthPhyOcpBit(tp, + 0xB87E, + BIT_15 | BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8, + BIT_11 + ); + + ClearAndSetEthPhyOcpBit(tp, + 0xbf00, + 0xE000, + 0xA000 + ); + ClearAndSetEthPhyOcpBit(tp, + 0xbf46, + 0x0F00, + 0x0300 + ); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8044); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x804A); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8050); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8056); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x805C); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8062); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8068); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x806E); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x8074); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + mdio_direct_write_phy_ocp(tp, 0xa436, 0x807A); + mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); + + + SetEthPhyOcpBit(tp, 0xA4CA, BIT_6); + + + ClearAndSetEthPhyOcpBit(tp, + 0xBF84, + BIT_15 | BIT_14 | BIT_13, + BIT_15 | BIT_13 + ); + + + mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); + ClearAndSetEthPhyOcpBit(tp, + 0xA438, + BIT_13 | BIT_10 | BIT_9 | BIT_8, + BIT_15 | BIT_14 | BIT_12 | BIT_11 + ); + + /* + mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); + mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); + mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); + mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); + mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); + ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); + mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); + SetEthPhyOcpBit(tp, 0xA438, BIT_12); + */ + + + if (aspm) { + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + rtl8125_enable_phy_aldps(tp); + } + } +} + +static void +rtl8125_hw_phy_config(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (tp->resume_not_chg_speed) return; + + tp->phy_reset_enable(dev); + + if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) return; + +#ifndef ENABLE_USE_FIRMWARE_FILE + if (!tp->rtl_fw) { + rtl8125_set_hw_phy_before_init_phy_mcu(dev); + + rtl8125_init_hw_phy_mcu(dev); + } +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + rtl8125_hw_phy_config_8125a_1(dev); + break; + case CFG_METHOD_3: + rtl8125_hw_phy_config_8125a_2(dev); + break; + case CFG_METHOD_4: + rtl8125_hw_phy_config_8125b_1(dev); + break; + case CFG_METHOD_5: + rtl8125_hw_phy_config_8125b_2(dev); + break; + } + + //legacy force mode(Chap 22) + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + rtl8125_mdio_write(tp, 0x1F, 0x0A5B); + rtl8125_clear_eth_phy_bit(tp, 0x12, BIT_15); + rtl8125_mdio_write(tp, 0x1F, 0x0000); + break; + } + + /*ocp phy power saving*/ + /* + if (aspm) { + if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) + rtl8125_enable_ocp_phy_power_saving(dev); + } + */ + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + + if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { + if (tp->eee.eee_enabled) + rtl8125_enable_eee(tp); + else + rtl8125_disable_eee(tp); + } +} + +static void +rtl8125_up(struct net_device *dev) +{ + rtl8125_hw_init(dev); + rtl8125_hw_reset(dev); + rtl8125_powerup_pll(dev); + rtl8125_hw_ephy_config(dev); + rtl8125_hw_phy_config(dev); + rtl8125_hw_config(dev); +} + +/* +static inline void rtl8125_delete_esd_timer(struct net_device *dev, struct timer_list *timer) +{ + del_timer_sync(timer); +} + +static inline void rtl8125_request_esd_timer(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct timer_list *timer = &tp->esd_timer; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) + setup_timer(timer, rtl8125_esd_timer, (unsigned long)dev); +#else + timer_setup(timer, rtl8125_esd_timer, 0); +#endif + mod_timer(timer, jiffies + RTL8125_ESD_TIMEOUT); +} +*/ + +/* +static inline void rtl8125_delete_link_timer(struct net_device *dev, struct timer_list *timer) +{ + del_timer_sync(timer); +} + +static inline void rtl8125_request_link_timer(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct timer_list *timer = &tp->link_timer; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) + setup_timer(timer, rtl8125_link_timer, (unsigned long)dev); +#else + timer_setup(timer, rtl8125_link_timer, 0); +#endif + mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); +} +*/ + +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +static void +rtl8125_netpoll(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + for (i = 0; i < tp->irq_nvecs; i++) { + struct r8125_irq *irq = &tp->irq_tbl[i]; + struct r8125_napi *r8125napi = &tp->r8125napi[i]; + + disable_irq(irq->vector); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) + irq->handler(irq->vector, r8125napi); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + irq->handler(irq->vector, r8125napi, NULL); +#else + irq->handler(irq->vector, r8125napi); +#endif + + enable_irq(irq->vector); + } +} +#endif //CONFIG_NET_POLL_CONTROLLER + +static void +rtl8125_get_bios_setting(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->bios_setting = RTL_R32(tp, TimeInt2); + break; + } +} + +static void +rtl8125_set_bios_setting(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W32(tp, TimeInt2, tp->bios_setting); + break; + } +} + +static void +rtl8125_setup_mqs_reg(struct rtl8125_private *tp) +{ + int i; + + //tx + tp->tx_ring[0].tdsar_reg = TxDescStartAddrLow; + for (i = 1; i < R8125_MAX_TX_QUEUES; i++) { + tp->tx_ring[i].tdsar_reg = (u16)(TNPDS_Q1_LOW_8125 + (i - 1) * 8); + } + + for (i = 0; i < R8125_MAX_TX_QUEUES; i++) { + tp->tx_ring[i].hw_clo_ptr_reg = (u16)(HW_CLO_PTR0_8125 + i * 4); + tp->tx_ring[i].sw_tail_ptr_reg = (u16)(SW_TAIL_PTR0_8125 + i * 4); + } + + //rx + tp->rx_ring[0].rdsar_reg = RxDescAddrLow; + for (i = 1; i < R8125_MAX_RX_QUEUES; i++) { + tp->rx_ring[i].rdsar_reg = (u16)(RDSAR_Q1_LOW_8125 + (i - 1) * 8); + } + + tp->isr_reg[0] = ISR0_8125; + for (i = 1; i < R8125_MAX_QUEUES; i++) { + tp->isr_reg[i] = (u16)(ISR1_8125 + (i - 1) * 4); + } + + tp->imr_reg[0] = IMR0_8125; + for (i = 1; i < R8125_MAX_QUEUES; i++) { + tp->imr_reg[i] = (u16)(IMR1_8125 + (i - 1) * 4); + } +} + +static void +rtl8125_init_software_variable(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct pci_dev *pdev = tp->pci_dev; + + rtl8125_get_bios_setting(dev); + +#ifdef ENABLE_LIB_SUPPORT + tp->ring_lib_enabled = 1; +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + //tp->HwSuppDashVer = 3; + break; + default: + tp->HwSuppDashVer = 0; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwPkgDet = rtl8125_mac_ocp_read(tp, 0xDC00); + tp->HwPkgDet = (tp->HwPkgDet >> 3) & 0x07; + break; + } + + if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) + eee_enable = 0; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppNowIsOobVer = 1; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwPcieSNOffset = 0x16C; + break; + } + +#ifdef ENABLE_REALWOW_SUPPORT + rtl8125_get_realwow_hw_version(dev); +#endif //ENABLE_REALWOW_SUPPORT + + if (HW_DASH_SUPPORT_DASH(tp) && rtl8125_check_dash(tp)) + tp->DASH = 1; + else + tp->DASH = 0; + + if (tp->DASH) { + if (HW_DASH_SUPPORT_TYPE_3(tp)) { + u64 CmacMemPhysAddress; + void __iomem *cmac_ioaddr = NULL; + + //map CMAC IO space + CmacMemPhysAddress = rtl8125_csi_other_fun_read(tp, 0, 0x18); + if (!(CmacMemPhysAddress & BIT_0)) { + if (CmacMemPhysAddress & BIT_2) + CmacMemPhysAddress |= (u64)rtl8125_csi_other_fun_read(tp, 0, 0x1C) << 32; + + CmacMemPhysAddress &= 0xFFFFFFF0; + /* ioremap MMIO region */ + cmac_ioaddr = ioremap(CmacMemPhysAddress, R8125_REGS_SIZE); + } + + if (cmac_ioaddr == NULL) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "cannot remap CMAC MMIO, aborting\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + } + + if (cmac_ioaddr == NULL) { + tp->DASH = 0; + } else { + tp->mapped_cmac_ioaddr = cmac_ioaddr; + } + } + + eee_enable = 0; + } + + if (HW_DASH_SUPPORT_TYPE_3(tp)) + tp->cmac_ioaddr = tp->mapped_cmac_ioaddr; + + if (aspm) { + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->org_pci_offset_99 = rtl8125_csi_fun0_read_byte(tp, 0x99); + tp->org_pci_offset_99 &= ~(BIT_5|BIT_6); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x264); + break; + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x214); + break; + } + } + + pci_read_config_byte(pdev, 0x80, &tp->org_pci_offset_80); + pci_read_config_byte(pdev, 0x81, &tp->org_pci_offset_81); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + default: + tp->use_timer_interrrupt = TRUE; + break; + } + + if (timer_count == 0 || tp->mcfg == CFG_METHOD_DEFAULT) + tp->use_timer_interrrupt = FALSE; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_V3; + break; + default: + tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_NOT_SUPPORT; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppLinkChgWakeUpVer = 3; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppD0SpeedUpVer = 1; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppCheckPhyDisableModeVer = 3; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppTxNoCloseVer = 3; + break; + } + + if (tp->HwSuppTxNoCloseVer > 0 && tx_no_close_enable == 1) + tp->EnableTxNoClose = TRUE; + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + tp->RequireLSOPatch = TRUE; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_2; + break; + case CFG_METHOD_3: + tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_3; + break; + case CFG_METHOD_4: + tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_4; + break; + case CFG_METHOD_5: + tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_5; + break; + } + + if (tp->HwIcVerUnknown) { + tp->NotWrRamCodeToMicroP = TRUE; + tp->NotWrMcuPatchCode = TRUE; + } + + switch (tp->mcfg) { + case CFG_METHOD_3: + if ((rtl8125_mac_ocp_read(tp, 0xD442) & BIT_5) && + (mdio_direct_read_phy_ocp(tp, 0xD068) & BIT_1) + ) { + tp->RequirePhyMdiSwapPatch = TRUE; + } + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppNumTxQueues = 2; + tp->HwSuppNumRxQueues = 4; + break; + default: + tp->HwSuppNumTxQueues = 1; + tp->HwSuppNumRxQueues = 1; + break; + } + + tp->num_tx_rings = 1; +#ifdef ENABLE_MULTIPLE_TX_QUEUE +#ifndef ENABLE_LIB_SUPPORT + tp->num_tx_rings = tp->HwSuppNumTxQueues; +#endif +#endif + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppRssVer = 5; + tp->HwSuppIndirTblEntries = 128; + break; + } + + tp->num_rx_rings = 1; +#ifdef ENABLE_RSS_SUPPORT +#ifdef ENABLE_LIB_SUPPORT + if (tp->HwSuppRssVer > 0) + tp->EnableRss = 1; +#else + if (tp->HwSuppRssVer > 0) { + u8 rss_queue_num = netif_get_num_default_rss_queues(); + tp->num_rx_rings = (tp->HwSuppNumRxQueues > rss_queue_num)? + rss_queue_num : tp->HwSuppNumRxQueues; + + if (!(tp->num_rx_rings >= 2 && tp->irq_nvecs >= tp->num_rx_rings)) + tp->num_rx_rings = 1; + + if (tp->num_rx_rings >= 2) + tp->EnableRss = 1; + } +#endif + if (tp->EnableRss) + rtl8125_init_rss(tp); +#endif + + rtl8125_setup_mqs_reg(tp); + + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppPtpVer = 1; + break; + } +#ifdef ENABLE_PTP_SUPPORT + if (tp->HwSuppPtpVer > 0) + tp->EnablePtp = 1; +#endif + + tp->InitRxDescType = RX_DESC_RING_TYPE_1; + if (tp->EnableRss || tp->EnablePtp) + tp->InitRxDescType = RX_DESC_RING_TYPE_3; + + tp->RxDescLength = RX_DESC_LEN_TYPE_1; + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + tp->RxDescLength = RX_DESC_LEN_TYPE_3; + tp->RxDescRingLength = NUM_RX_DESC * tp->RxDescLength; + + tp->rtl8125_rx_config = rtl_chip_info[tp->chipset].RCR_Cfg; + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + tp->rtl8125_rx_config |= EnableRxDescV3; + + //init interrupt + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppIsrVer = 2; + break; + default: + tp->HwSuppIsrVer = 1; + break; + } + + tp->HwCurrIsrVer = tp->HwSuppIsrVer; + if (tp->HwSuppIsrVer == 2) { + if (!(tp->features & RTL_FEATURE_MSIX) || + tp->irq_nvecs < R8125_MIN_MSIX_VEC_8125B) + tp->HwCurrIsrVer = 1; + } + + if (tp->HwCurrIsrVer < 2 || tp->irq_nvecs < 19) + tp->num_tx_rings = 1; + + if (tp->HwCurrIsrVer == 2) { + int i; + + tp->intr_mask = ISRIMR_V2_LINKCHG | ISRIMR_TOK_Q0; + if (tp->num_tx_rings > 1) + tp->intr_mask |= ISRIMR_TOK_Q1; + + for (i = 0; i < tp->num_rx_rings; i++) + tp->intr_mask |= ISRIMR_V2_ROK_Q0 << i; + } else { + tp->intr_mask = LinkChg | RxDescUnavail | TxOK | RxOK | SWInt; + tp->timer_intr_mask = LinkChg | PCSTimeout; + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + if (HW_DASH_SUPPORT_TYPE_3(tp)) { + tp->timer_intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); + tp->intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); + } + } +#endif + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + tp->HwSuppIntMitiVer = 3; + break; + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppIntMitiVer = 4; + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->HwSuppExtendTallyCounterVer = 1; + break; + } + + timer_count_v2 = (timer_count / 0x100); + + tp->NicCustLedValue = RTL_R16(tp, CustomLED); + + tp->wol_opts = rtl8125_get_hw_wol(tp); + tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; + + rtl8125_link_option((u8*)&autoneg_mode, (u32*)&speed_mode, (u8*)&duplex_mode, (u32*)&advertising_mode); + + tp->autoneg = autoneg_mode; + tp->speed = speed_mode; + tp->duplex = duplex_mode; + tp->advertising = advertising_mode; + tp->fcpause = rtl8125_fc_full; + + tp->max_jumbo_frame_size = rtl_chip_info[tp->chipset].jumbo_frame_sz; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + /* MTU range: 60 - hw-specific max */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = tp->max_jumbo_frame_size; +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + + if (tp->mcfg != CFG_METHOD_DEFAULT) { + struct ethtool_eee *eee = &tp->eee; + + eee->eee_enabled = eee_enable; + eee->supported = SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full; + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + eee->supported |= SUPPORTED_2500baseX_Full; + break; + } + eee->advertised = mmd_eee_adv_to_ethtool_adv_t(MDIO_EEE_1000T | MDIO_EEE_100TX); + eee->tx_lpi_timer = dev->mtu + ETH_HLEN + 0x20; + } + + tp->ptp_master_mode = enable_ptp_master_mode; +} + +static void +rtl8125_release_board(struct pci_dev *pdev, + struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + + rtl8125_set_bios_setting(dev); + rtl8125_rar_set(tp, tp->org_mac_addr); + tp->wol_enabled = WOL_DISABLED; + + if (!tp->DASH) + rtl8125_phy_power_down(dev); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + FreeAllocatedDashShareMemory(dev); +#endif + + if (tp->mapped_cmac_ioaddr != NULL) + iounmap(tp->mapped_cmac_ioaddr); + + iounmap(ioaddr); + pci_release_regions(pdev); + pci_clear_mwi(pdev); + pci_disable_device(pdev); + free_netdev(dev); +} + +static int +rtl8125_get_mac_address(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + u8 mac_addr[MAC_ADDR_LEN]; + + for (i = 0; i < MAC_ADDR_LEN; i++) + mac_addr[i] = RTL_R8(tp, MAC0 + i); + + if(tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + *(u32*)&mac_addr[0] = RTL_R32(tp, BACKUP_ADDR0_8125); + *(u16*)&mac_addr[4] = RTL_R16(tp, BACKUP_ADDR1_8125); + } + + if (!is_valid_ether_addr(mac_addr)) { + netif_err(tp, probe, dev, "Invalid ether addr %pM\n", + mac_addr); + eth_hw_addr_random(dev); + ether_addr_copy(mac_addr, dev->dev_addr); + netif_info(tp, probe, dev, "Random ether addr %pM\n", + mac_addr); + tp->random_mac = 1; + } + + rtl8125_rar_set(tp, mac_addr); + + for (i = 0; i < MAC_ADDR_LEN; i++) { + dev->dev_addr[i] = RTL_R8(tp, MAC0 + i); + tp->org_mac_addr[i] = dev->dev_addr[i]; /* keep the original MAC address */ + } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); +#endif +// memcpy(dev->dev_addr, dev->dev_addr, dev->addr_len); + + return 0; +} + +/** + * rtl8125_set_mac_address - Change the Ethernet Address of the NIC + * @dev: network interface device structure + * @p: pointer to an address structure + * + * Return 0 on success, negative on failure + **/ +static int +rtl8125_set_mac_address(struct net_device *dev, + void *p) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + rtl8125_rar_set(tp, dev->dev_addr); + + return 0; +} + +/****************************************************************************** + * rtl8125_rar_set - Puts an ethernet address into a receive address register. + * + * tp - The private data structure for driver + * addr - Address to put into receive address register + *****************************************************************************/ +void +rtl8125_rar_set(struct rtl8125_private *tp, + uint8_t *addr) +{ + uint32_t rar_low = 0; + uint32_t rar_high = 0; + + rar_low = ((uint32_t) addr[0] | + ((uint32_t) addr[1] << 8) | + ((uint32_t) addr[2] << 16) | + ((uint32_t) addr[3] << 24)); + + rar_high = ((uint32_t) addr[4] | + ((uint32_t) addr[5] << 8)); + + rtl8125_enable_cfg9346_write(tp); + RTL_W32(tp, MAC0, rar_low); + RTL_W32(tp, MAC4, rar_high); + + rtl8125_disable_cfg9346_write(tp); +} + +#ifdef ETHTOOL_OPS_COMPAT +static int ethtool_get_settings(struct net_device *dev, void *useraddr) +{ + struct ethtool_cmd cmd = { ETHTOOL_GSET }; + int err; + + if (!ethtool_ops->get_settings) + return -EOPNOTSUPP; + + err = ethtool_ops->get_settings(dev, &cmd); + if (err < 0) + return err; + + if (copy_to_user(useraddr, &cmd, sizeof(cmd))) + return -EFAULT; + return 0; +} + +static int ethtool_set_settings(struct net_device *dev, void *useraddr) +{ + struct ethtool_cmd cmd; + + if (!ethtool_ops->set_settings) + return -EOPNOTSUPP; + + if (copy_from_user(&cmd, useraddr, sizeof(cmd))) + return -EFAULT; + + return ethtool_ops->set_settings(dev, &cmd); +} + +static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) +{ + struct ethtool_drvinfo info; + struct ethtool_ops *ops = ethtool_ops; + + if (!ops->get_drvinfo) + return -EOPNOTSUPP; + + memset(&info, 0, sizeof(info)); + info.cmd = ETHTOOL_GDRVINFO; + ops->get_drvinfo(dev, &info); + + if (ops->self_test_count) + info.testinfo_len = ops->self_test_count(dev); + if (ops->get_stats_count) + info.n_stats = ops->get_stats_count(dev); + if (ops->get_regs_len) + info.regdump_len = ops->get_regs_len(dev); + if (ops->get_eeprom_len) + info.eedump_len = ops->get_eeprom_len(dev); + + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +static int ethtool_get_regs(struct net_device *dev, char *useraddr) +{ + struct ethtool_regs regs; + struct ethtool_ops *ops = ethtool_ops; + void *regbuf; + int reglen, ret; + + if (!ops->get_regs || !ops->get_regs_len) + return -EOPNOTSUPP; + + if (copy_from_user(®s, useraddr, sizeof(regs))) + return -EFAULT; + + reglen = ops->get_regs_len(dev); + if (regs.len > reglen) + regs.len = reglen; + + regbuf = kmalloc(reglen, GFP_USER); + if (!regbuf) + return -ENOMEM; + + ops->get_regs(dev, ®s, regbuf); + + ret = -EFAULT; + if (copy_to_user(useraddr, ®s, sizeof(regs))) + goto out; + useraddr += offsetof(struct ethtool_regs, data); + if (copy_to_user(useraddr, regbuf, reglen)) + goto out; + ret = 0; + +out: + kfree(regbuf); + return ret; +} + +static int ethtool_get_wol(struct net_device *dev, char *useraddr) +{ + struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; + + if (!ethtool_ops->get_wol) + return -EOPNOTSUPP; + + ethtool_ops->get_wol(dev, &wol); + + if (copy_to_user(useraddr, &wol, sizeof(wol))) + return -EFAULT; + return 0; +} + +static int ethtool_set_wol(struct net_device *dev, char *useraddr) +{ + struct ethtool_wolinfo wol; + + if (!ethtool_ops->set_wol) + return -EOPNOTSUPP; + + if (copy_from_user(&wol, useraddr, sizeof(wol))) + return -EFAULT; + + return ethtool_ops->set_wol(dev, &wol); +} + +static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GMSGLVL }; + + if (!ethtool_ops->get_msglevel) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_msglevel(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_msglevel) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + ethtool_ops->set_msglevel(dev, edata.data); + return 0; +} + +static int ethtool_nway_reset(struct net_device *dev) +{ + if (!ethtool_ops->nway_reset) + return -EOPNOTSUPP; + + return ethtool_ops->nway_reset(dev); +} + +static int ethtool_get_link(struct net_device *dev, void *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GLINK }; + + if (!ethtool_ops->get_link) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_link(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) +{ + struct ethtool_eeprom eeprom; + struct ethtool_ops *ops = ethtool_ops; + u8 *data; + int ret; + + if (!ops->get_eeprom || !ops->get_eeprom_len) + return -EOPNOTSUPP; + + if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) + return -EFAULT; + + /* Check for wrap and zero */ + if (eeprom.offset + eeprom.len <= eeprom.offset) + return -EINVAL; + + /* Check for exceeding total eeprom len */ + if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) + return -EINVAL; + + data = kmalloc(eeprom.len, GFP_USER); + if (!data) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) + goto out; + + ret = ops->get_eeprom(dev, &eeprom, data); + if (ret) + goto out; + + ret = -EFAULT; + if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) + goto out; + if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) +{ + struct ethtool_eeprom eeprom; + struct ethtool_ops *ops = ethtool_ops; + u8 *data; + int ret; + + if (!ops->set_eeprom || !ops->get_eeprom_len) + return -EOPNOTSUPP; + + if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) + return -EFAULT; + + /* Check for wrap and zero */ + if (eeprom.offset + eeprom.len <= eeprom.offset) + return -EINVAL; + + /* Check for exceeding total eeprom len */ + if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) + return -EINVAL; + + data = kmalloc(eeprom.len, GFP_USER); + if (!data) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) + goto out; + + ret = ops->set_eeprom(dev, &eeprom, data); + if (ret) + goto out; + + if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) + ret = -EFAULT; + +out: + kfree(data); + return ret; +} + +static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) +{ + struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; + + if (!ethtool_ops->get_coalesce) + return -EOPNOTSUPP; + + ethtool_ops->get_coalesce(dev, &coalesce); + + if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) + return -EFAULT; + return 0; +} + +static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) +{ + struct ethtool_coalesce coalesce; + + if (!ethtool_ops->get_coalesce) + return -EOPNOTSUPP; + + if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) + return -EFAULT; + + return ethtool_ops->set_coalesce(dev, &coalesce); +} + +static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; + + if (!ethtool_ops->get_ringparam) + return -EOPNOTSUPP; + + ethtool_ops->get_ringparam(dev, &ringparam); + + if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) + return -EFAULT; + return 0; +} + +static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_ringparam ringparam; + + if (!ethtool_ops->get_ringparam) + return -EOPNOTSUPP; + + if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) + return -EFAULT; + + return ethtool_ops->set_ringparam(dev, &ringparam); +} + +static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; + + if (!ethtool_ops->get_pauseparam) + return -EOPNOTSUPP; + + ethtool_ops->get_pauseparam(dev, &pauseparam); + + if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) + return -EFAULT; + return 0; +} + +static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) +{ + struct ethtool_pauseparam pauseparam; + + if (!ethtool_ops->get_pauseparam) + return -EOPNOTSUPP; + + if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) + return -EFAULT; + + return ethtool_ops->set_pauseparam(dev, &pauseparam); +} + +static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GRXCSUM }; + + if (!ethtool_ops->get_rx_csum) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_rx_csum(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_rx_csum) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + ethtool_ops->set_rx_csum(dev, edata.data); + return 0; +} + +static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GTXCSUM }; + + if (!ethtool_ops->get_tx_csum) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_tx_csum(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_tx_csum) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + return ethtool_ops->set_tx_csum(dev, edata.data); +} + +static int ethtool_get_sg(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GSG }; + + if (!ethtool_ops->get_sg) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_sg(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_sg(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_sg) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + return ethtool_ops->set_sg(dev, edata.data); +} + +static int ethtool_get_tso(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GTSO }; + + if (!ethtool_ops->get_tso) + return -EOPNOTSUPP; + + edata.data = ethtool_ops->get_tso(dev); + + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_tso(struct net_device *dev, char *useraddr) +{ + struct ethtool_value edata; + + if (!ethtool_ops->set_tso) + return -EOPNOTSUPP; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + + return ethtool_ops->set_tso(dev, edata.data); +} + +static int ethtool_self_test(struct net_device *dev, char *useraddr) +{ + struct ethtool_test test; + struct ethtool_ops *ops = ethtool_ops; + u64 *data; + int ret; + + if (!ops->self_test || !ops->self_test_count) + return -EOPNOTSUPP; + + if (copy_from_user(&test, useraddr, sizeof(test))) + return -EFAULT; + + test.len = ops->self_test_count(dev); + data = kmalloc(test.len * sizeof(u64), GFP_USER); + if (!data) + return -ENOMEM; + + ops->self_test(dev, &test, data); + + ret = -EFAULT; + if (copy_to_user(useraddr, &test, sizeof(test))) + goto out; + useraddr += sizeof(test); + if (copy_to_user(useraddr, data, test.len * sizeof(u64))) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_get_strings(struct net_device *dev, void *useraddr) +{ + struct ethtool_gstrings gstrings; + struct ethtool_ops *ops = ethtool_ops; + u8 *data; + int ret; + + if (!ops->get_strings) + return -EOPNOTSUPP; + + if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) + return -EFAULT; + + switch (gstrings.string_set) { + case ETH_SS_TEST: + if (!ops->self_test_count) + return -EOPNOTSUPP; + gstrings.len = ops->self_test_count(dev); + break; + case ETH_SS_STATS: + if (!ops->get_stats_count) + return -EOPNOTSUPP; + gstrings.len = ops->get_stats_count(dev); + break; + default: + return -EINVAL; + } + + data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); + if (!data) + return -ENOMEM; + + ops->get_strings(dev, gstrings.string_set, data); + + ret = -EFAULT; + if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) + goto out; + useraddr += sizeof(gstrings); + if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_phys_id(struct net_device *dev, void *useraddr) +{ + struct ethtool_value id; + + if (!ethtool_ops->phys_id) + return -EOPNOTSUPP; + + if (copy_from_user(&id, useraddr, sizeof(id))) + return -EFAULT; + + return ethtool_ops->phys_id(dev, id.data); +} + +static int ethtool_get_stats(struct net_device *dev, void *useraddr) +{ + struct ethtool_stats stats; + struct ethtool_ops *ops = ethtool_ops; + u64 *data; + int ret; + + if (!ops->get_ethtool_stats || !ops->get_stats_count) + return -EOPNOTSUPP; + + if (copy_from_user(&stats, useraddr, sizeof(stats))) + return -EFAULT; + + stats.n_stats = ops->get_stats_count(dev); + data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); + if (!data) + return -ENOMEM; + + ops->get_ethtool_stats(dev, &stats, data); + + ret = -EFAULT; + if (copy_to_user(useraddr, &stats, sizeof(stats))) + goto out; + useraddr += sizeof(stats); + if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + +static int ethtool_ioctl(struct ifreq *ifr) +{ + struct net_device *dev = __dev_get_by_name(ifr->ifr_name); + void *useraddr = (void *) ifr->ifr_data; + u32 ethcmd; + + /* + * XXX: This can be pushed down into the ethtool_* handlers that + * need it. Keep existing behaviour for the moment. + */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!dev || !netif_device_present(dev)) + return -ENODEV; + + if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GSET: + return ethtool_get_settings(dev, useraddr); + case ETHTOOL_SSET: + return ethtool_set_settings(dev, useraddr); + case ETHTOOL_GDRVINFO: + return ethtool_get_drvinfo(dev, useraddr); + case ETHTOOL_GREGS: + return ethtool_get_regs(dev, useraddr); + case ETHTOOL_GWOL: + return ethtool_get_wol(dev, useraddr); + case ETHTOOL_SWOL: + return ethtool_set_wol(dev, useraddr); + case ETHTOOL_GMSGLVL: + return ethtool_get_msglevel(dev, useraddr); + case ETHTOOL_SMSGLVL: + return ethtool_set_msglevel(dev, useraddr); + case ETHTOOL_NWAY_RST: + return ethtool_nway_reset(dev); + case ETHTOOL_GLINK: + return ethtool_get_link(dev, useraddr); + case ETHTOOL_GEEPROM: + return ethtool_get_eeprom(dev, useraddr); + case ETHTOOL_SEEPROM: + return ethtool_set_eeprom(dev, useraddr); + case ETHTOOL_GCOALESCE: + return ethtool_get_coalesce(dev, useraddr); + case ETHTOOL_SCOALESCE: + return ethtool_set_coalesce(dev, useraddr); + case ETHTOOL_GRINGPARAM: + return ethtool_get_ringparam(dev, useraddr); + case ETHTOOL_SRINGPARAM: + return ethtool_set_ringparam(dev, useraddr); + case ETHTOOL_GPAUSEPARAM: + return ethtool_get_pauseparam(dev, useraddr); + case ETHTOOL_SPAUSEPARAM: + return ethtool_set_pauseparam(dev, useraddr); + case ETHTOOL_GRXCSUM: + return ethtool_get_rx_csum(dev, useraddr); + case ETHTOOL_SRXCSUM: + return ethtool_set_rx_csum(dev, useraddr); + case ETHTOOL_GTXCSUM: + return ethtool_get_tx_csum(dev, useraddr); + case ETHTOOL_STXCSUM: + return ethtool_set_tx_csum(dev, useraddr); + case ETHTOOL_GSG: + return ethtool_get_sg(dev, useraddr); + case ETHTOOL_SSG: + return ethtool_set_sg(dev, useraddr); + case ETHTOOL_GTSO: + return ethtool_get_tso(dev, useraddr); + case ETHTOOL_STSO: + return ethtool_set_tso(dev, useraddr); + case ETHTOOL_TEST: + return ethtool_self_test(dev, useraddr); + case ETHTOOL_GSTRINGS: + return ethtool_get_strings(dev, useraddr); + case ETHTOOL_PHYS_ID: + return ethtool_phys_id(dev, useraddr); + case ETHTOOL_GSTATS: + return ethtool_get_stats(dev, useraddr); + default: + return -EOPNOTSUPP; + } + + return -EOPNOTSUPP; +} +#endif //ETHTOOL_OPS_COMPAT + +static int +rtl8125_do_ioctl(struct net_device *dev, + struct ifreq *ifr, + int cmd) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct mii_ioctl_data *data = if_mii(ifr); + int ret; + + ret = 0; + switch (cmd) { + case SIOCGMIIPHY: + data->phy_id = 32; /* Internal PHY */ + break; + + case SIOCGMIIREG: + rtl8125_mdio_write(tp, 0x1F, 0x0000); + data->val_out = rtl8125_mdio_read(tp, data->reg_num); + break; + + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, data->reg_num, data->val_in); + break; + +#ifdef ETHTOOL_OPS_COMPAT + case SIOCETHTOOL: + ret = ethtool_ioctl(ifr); + break; +#endif + +#ifdef ENABLE_DASH_SUPPORT + case SIOCDEVPRIVATE_RTLDASH: + if (!netif_running(dev)) { + ret = -ENODEV; + break; + } + if (!capable(CAP_NET_ADMIN)) { + ret = -EPERM; + break; + } + + ret = rtl8125_dash_ioctl(dev, ifr); + break; +#endif + +#ifdef ENABLE_REALWOW_SUPPORT + case SIOCDEVPRIVATE_RTLREALWOW: + if (!netif_running(dev)) { + ret = -ENODEV; + break; + } + + ret = rtl8125_realwow_ioctl(dev, ifr); + break; +#endif + +#ifdef ENABLE_PTP_SUPPORT + case SIOCSHWTSTAMP: + case SIOCGHWTSTAMP: + if (tp->EnablePtp) + ret = rtl8125_ptp_ioctl(dev, ifr, cmd); + else + ret = -EOPNOTSUPP; + break; +#endif + case SIOCRTLTOOL: + ret = rtl8125_tool_ioctl(tp, ifr); + break; + + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static void +rtl8125_phy_power_up(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (rtl8125_is_in_phy_disable_mode(dev)) { + return; + } + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE); + + //wait ups resume (phy state 3) + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_wait_phy_ups_resume(dev, 3); + break; + }; +} + +static void +rtl8125_phy_power_down(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + rtl8125_mdio_write(tp, 0x1F, 0x0000); + rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); +} + +static int __devinit +rtl8125_init_board(struct pci_dev *pdev, + struct net_device **dev_out, + void __iomem **ioaddr_out) +{ + void __iomem *ioaddr; + struct net_device *dev; + struct rtl8125_private *tp; + int rc = -ENOMEM, i, pm_cap; + + assert(ioaddr_out != NULL); + + /* dev zeroed in alloc_etherdev */ + dev = alloc_etherdev_mq(sizeof (*tp), R8125_MAX_QUEUES); + if (dev == NULL) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_drv(&debug)) + dev_err(&pdev->dev, "unable to alloc new ethernet\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + goto err_out; + } + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); + tp = netdev_priv(dev); + tp->dev = dev; + tp->pci_dev = pdev; + tp->msg_enable = netif_msg_init(debug.msg_enable, R8125_MSG_DEFAULT); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + if (!aspm) + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | + PCIE_LINK_STATE_CLKPM); +#endif + + /* enable device (incl. PCI PM wakeup and hotplug setup) */ + rc = pci_enable_device(pdev); + if (rc < 0) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "enable failure\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + goto err_out_free_dev; + } + + if (pci_set_mwi(pdev) < 0) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_drv(&debug)) + dev_info(&pdev->dev, "Mem-Wr-Inval unavailable.\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + } + + /* save power state before pci_enable_device overwrites it */ + pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); + if (pm_cap) { + u16 pwr_command; + + pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); + } else { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) { + dev_err(&pdev->dev, "PowerManagement capability not found.\n"); + } +#else + printk("PowerManagement capability not found.\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + + } + + /* make sure PCI base addr 1 is MMIO */ + if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + rc = -ENODEV; + goto err_out_mwi; + } + /* check for weird/broken PCI region reporting */ + if (pci_resource_len(pdev, 2) < R8125_REGS_SIZE) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + rc = -ENODEV; + goto err_out_mwi; + } + + rc = pci_request_regions(pdev, MODULENAME); + if (rc < 0) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "could not request regions.\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + goto err_out_mwi; + } + + if ((sizeof(dma_addr_t) > 4) && + use_dac && + !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && + !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { + dev->features |= NETIF_F_HIGHDMA; + } else { + rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (rc < 0) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "DMA configuration failed.\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + goto err_out_free_res; + } + } + + /* ioremap MMIO region */ + ioaddr = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); + if (ioaddr == NULL) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + rc = -EIO; + goto err_out_free_res; + } + + tp->mmio_addr = ioaddr; + + /* Identify chip attached to board */ + rtl8125_get_mac_version(tp); + + rtl8125_print_mac_version(tp); + + for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { + if (tp->mcfg == rtl_chip_info[i].mcfg) + break; + } + + if (i < 0) { + /* Unknown chip: assume array element #0, original RTL-8125 */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (netif_msg_probe(tp)) + dev_printk(KERN_DEBUG, &pdev->dev, "unknown chip version, assuming %s\n", rtl_chip_info[0].name); +#else + printk("Realtek unknown chip version, assuming %s\n", rtl_chip_info[0].name); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + i++; + } + + tp->chipset = i; + + *ioaddr_out = ioaddr; + *dev_out = dev; +out: + return rc; + +err_out_free_res: + pci_release_regions(pdev); +err_out_mwi: + pci_clear_mwi(pdev); + pci_disable_device(pdev); +err_out_free_dev: + free_netdev(dev); +err_out: + *ioaddr_out = NULL; + *dev_out = NULL; + goto out; +} + +static void +rtl8125_esd_checker(struct rtl8125_private *tp) +{ + struct net_device *dev = tp->dev; + struct pci_dev *pdev = tp->pci_dev; + u8 cmd; + u16 io_base_l; + u16 mem_base_l; + u16 mem_base_h; + u8 ilr; + u16 resv_0x1c_h; + u16 resv_0x1c_l; + u16 resv_0x20_l; + u16 resv_0x20_h; + u16 resv_0x24_l; + u16 resv_0x24_h; + u16 resv_0x2c_h; + u16 resv_0x2c_l; + u32 pci_sn_l; + u32 pci_sn_h; + + tp->esd_flag = 0; + + pci_read_config_byte(pdev, PCI_COMMAND, &cmd); + if (cmd != tp->pci_cfg_space.cmd) { + printk(KERN_ERR "%s: cmd = 0x%02x, should be 0x%02x \n.", dev->name, cmd, tp->pci_cfg_space.cmd); + pci_write_config_byte(pdev, PCI_COMMAND, tp->pci_cfg_space.cmd); + tp->esd_flag |= BIT_0; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &io_base_l); + if (io_base_l != tp->pci_cfg_space.io_base_l) { + printk(KERN_ERR "%s: io_base_l = 0x%04x, should be 0x%04x \n.", dev->name, io_base_l, tp->pci_cfg_space.io_base_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_0, tp->pci_cfg_space.io_base_l); + tp->esd_flag |= BIT_1; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &mem_base_l); + if (mem_base_l != tp->pci_cfg_space.mem_base_l) { + printk(KERN_ERR "%s: mem_base_l = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_l, tp->pci_cfg_space.mem_base_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_2, tp->pci_cfg_space.mem_base_l); + tp->esd_flag |= BIT_2; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &mem_base_h); + if (mem_base_h!= tp->pci_cfg_space.mem_base_h) { + printk(KERN_ERR "%s: mem_base_h = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_h, tp->pci_cfg_space.mem_base_h); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, tp->pci_cfg_space.mem_base_h); + tp->esd_flag |= BIT_3; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &resv_0x1c_l); + if (resv_0x1c_l != tp->pci_cfg_space.resv_0x1c_l) { + printk(KERN_ERR "%s: resv_0x1c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_l, tp->pci_cfg_space.resv_0x1c_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_3, tp->pci_cfg_space.resv_0x1c_l); + tp->esd_flag |= BIT_4; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &resv_0x1c_h); + if (resv_0x1c_h != tp->pci_cfg_space.resv_0x1c_h) { + printk(KERN_ERR "%s: resv_0x1c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_h, tp->pci_cfg_space.resv_0x1c_h); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, tp->pci_cfg_space.resv_0x1c_h); + tp->esd_flag |= BIT_5; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &resv_0x20_l); + if (resv_0x20_l != tp->pci_cfg_space.resv_0x20_l) { + printk(KERN_ERR "%s: resv_0x20_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_l, tp->pci_cfg_space.resv_0x20_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_4, tp->pci_cfg_space.resv_0x20_l); + tp->esd_flag |= BIT_6; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &resv_0x20_h); + if (resv_0x20_h != tp->pci_cfg_space.resv_0x20_h) { + printk(KERN_ERR "%s: resv_0x20_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_h, tp->pci_cfg_space.resv_0x20_h); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, tp->pci_cfg_space.resv_0x20_h); + tp->esd_flag |= BIT_7; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &resv_0x24_l); + if (resv_0x24_l != tp->pci_cfg_space.resv_0x24_l) { + printk(KERN_ERR "%s: resv_0x24_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_l, tp->pci_cfg_space.resv_0x24_l); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_5, tp->pci_cfg_space.resv_0x24_l); + tp->esd_flag |= BIT_8; + } + + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &resv_0x24_h); + if (resv_0x24_h != tp->pci_cfg_space.resv_0x24_h) { + printk(KERN_ERR "%s: resv_0x24_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_h, tp->pci_cfg_space.resv_0x24_h); + pci_write_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, tp->pci_cfg_space.resv_0x24_h); + tp->esd_flag |= BIT_9; + } + + pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ilr); + if (ilr != tp->pci_cfg_space.ilr) { + printk(KERN_ERR "%s: ilr = 0x%02x, should be 0x%02x \n.", dev->name, ilr, tp->pci_cfg_space.ilr); + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, tp->pci_cfg_space.ilr); + tp->esd_flag |= BIT_10; + } + + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &resv_0x2c_l); + if (resv_0x2c_l != tp->pci_cfg_space.resv_0x2c_l) { + printk(KERN_ERR "%s: resv_0x2c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_l, tp->pci_cfg_space.resv_0x2c_l); + pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, tp->pci_cfg_space.resv_0x2c_l); + tp->esd_flag |= BIT_11; + } + + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &resv_0x2c_h); + if (resv_0x2c_h != tp->pci_cfg_space.resv_0x2c_h) { + printk(KERN_ERR "%s: resv_0x2c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_h, tp->pci_cfg_space.resv_0x2c_h); + pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, tp->pci_cfg_space.resv_0x2c_h); + tp->esd_flag |= BIT_12; + } + + if (tp->HwPcieSNOffset > 0) { + pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); + if (pci_sn_l != tp->pci_cfg_space.pci_sn_l) { + printk(KERN_ERR "%s: pci_sn_l = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_l, tp->pci_cfg_space.pci_sn_l); + rtl8125_csi_write(tp, tp->HwPcieSNOffset, tp->pci_cfg_space.pci_sn_l); + tp->esd_flag |= BIT_13; + } + + pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); + if (pci_sn_h != tp->pci_cfg_space.pci_sn_h) { + printk(KERN_ERR "%s: pci_sn_h = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_h, tp->pci_cfg_space.pci_sn_h); + rtl8125_csi_write(tp, tp->HwPcieSNOffset + 4, tp->pci_cfg_space.pci_sn_h); + tp->esd_flag |= BIT_14; + } + } + + if (tp->esd_flag != 0) { + printk(KERN_ERR "%s: esd_flag = 0x%04x\n.\n", dev->name, tp->esd_flag); + netif_tx_stop_all_queues(dev); + netif_carrier_off(dev); + rtl8125_hw_reset(dev); + rtl8125_tx_clear(tp); + rtl8125_rx_clear(tp); + rtl8125_init_ring(dev); + rtl8125_up(dev); + rtl8125_enable_hw_linkchg_interrupt(tp); + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + tp->esd_flag = 0; + } +} +/* +static void +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) +rtl8125_esd_timer(unsigned long __opaque) +#else +rtl8125_esd_timer(struct timer_list *t) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) + struct net_device *dev = (struct net_device *)__opaque; + struct rtl8125_private *tp = netdev_priv(dev); + struct timer_list *timer = &tp->esd_timer; +#else + struct rtl8125_private *tp = from_timer(tp, t, esd_timer); + //struct net_device *dev = tp->dev; + struct timer_list *timer = t; +#endif + rtl8125_esd_checker(tp); + + mod_timer(timer, jiffies + timeout); +} +*/ + +/* +static void +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) +rtl8125_link_timer(unsigned long __opaque) +#else +rtl8125_link_timer(struct timer_list *t) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) + struct net_device *dev = (struct net_device *)__opaque; + struct rtl8125_private *tp = netdev_priv(dev); + struct timer_list *timer = &tp->link_timer; +#else + struct rtl8125_private *tp = from_timer(tp, t, link_timer); + struct net_device *dev = tp->dev; + struct timer_list *timer = t; +#endif + rtl8125_check_link_status(dev); + + mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); +} +*/ + +int +rtl8125_enable_msix(struct rtl8125_private *tp) +{ + int i, nvecs = 0; + struct msix_entry msix_ent[R8125_MAX_MSIX_VEC]; + //struct net_device *dev = tp->dev; + //const int len = sizeof(tp->irq_tbl[0].name); + + for (i = 0; i < R8125_MAX_MSIX_VEC; i++) { + msix_ent[i].entry = i; + msix_ent[i].vector = 0; + } + + nvecs = pci_enable_msix_range(tp->pci_dev, msix_ent, + tp->min_irq_nvecs, tp->max_irq_nvecs); + if (nvecs < 0) + goto out; + + for (i = 0; i < nvecs; i++) { + struct r8125_irq *irq = &tp->irq_tbl[i]; + irq->vector = msix_ent[i].vector; + //snprintf(irq->name, len, "%s-%d", dev->name, i); + //irq->handler = rtl8125_interrupt_msix; + } + +out: + return nvecs; +} + +void rtl8125_dump_msix_tbl(struct rtl8125_private *tp) +{ + void __iomem *ioaddr; + + /* ioremap MMIO region */ + ioaddr = ioremap(pci_resource_start(tp->pci_dev, 4), pci_resource_len(tp->pci_dev, 4)); + if (ioaddr) { + int i = 0; + for (i=0; iirq_nvecs; i++) { + printk("entry 0x%d %08X %08X %08X %08X \n", + i, + readl(ioaddr + 16 * i), + readl(ioaddr + 16 * i + 4), + readl(ioaddr + 16 * i + 8), + readl(ioaddr + 16 * i + 12)); + } + iounmap(ioaddr); + } +} + +/* Cfg9346_Unlock assumed. */ +static int rtl8125_try_msi(struct rtl8125_private *tp) +{ + struct pci_dev *pdev = tp->pci_dev; + unsigned msi = 0; + int nvecs = 1; + + tp->max_irq_nvecs = 1; + tp->min_irq_nvecs = 1; +#ifndef DISABLE_MULTI_MSIX_VECTOR + switch (tp->mcfg) { + case CFG_METHOD_4: + case CFG_METHOD_5: + tp->max_irq_nvecs = R8125_MAX_MSIX_VEC_8125B; + tp->min_irq_nvecs = R8125_MIN_MSIX_VEC_8125B; + break; + } +#endif + +#if defined(RTL_USE_NEW_INTR_API) + if ((nvecs = pci_alloc_irq_vectors(pdev, tp->min_irq_nvecs, tp->max_irq_nvecs, PCI_IRQ_MSIX)) > 0) + msi |= RTL_FEATURE_MSIX; + else if ((nvecs = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES)) > 0 && + pci_dev_msi_enabled(pdev)) + msi |= RTL_FEATURE_MSI; +#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + if ((nvecs = rtl8125_enable_msix(tp)) > 0) + msi |= RTL_FEATURE_MSIX; + else if (!pci_enable_msi(pdev)) + msi |= RTL_FEATURE_MSI; +#endif + if (!(msi & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) + dev_info(&pdev->dev, "no MSI/MSI-X. Back to INTx.\n"); + + if (!(msi & RTL_FEATURE_MSIX) || nvecs < 1) + nvecs = 1; + + tp->irq_nvecs = nvecs; + + tp->features |= msi; + + return nvecs; +} + +static void rtl8125_disable_msi(struct pci_dev *pdev, struct rtl8125_private *tp) +{ +#if defined(RTL_USE_NEW_INTR_API) + if (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) + pci_free_irq_vectors(pdev); +#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + if (tp->features & (RTL_FEATURE_MSIX)) + pci_disable_msix(pdev); + else if (tp->features & (RTL_FEATURE_MSI)) + pci_disable_msi(pdev); +#endif + tp->features &= ~(RTL_FEATURE_MSI | RTL_FEATURE_MSIX); +} + +static int rtl8125_get_irq(struct pci_dev *pdev) +{ +#if defined(RTL_USE_NEW_INTR_API) + return pci_irq_vector(pdev, 0); +#else + return pdev->irq; +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +static const struct net_device_ops rtl8125_netdev_ops = { + .ndo_open = rtl8125_open, + .ndo_stop = rtl8125_close, + .ndo_get_stats = rtl8125_get_stats, + .ndo_start_xmit = rtl8125_start_xmit, + .ndo_tx_timeout = rtl8125_tx_timeout, + .ndo_change_mtu = rtl8125_change_mtu, + .ndo_set_mac_address = rtl8125_set_mac_address, + .ndo_do_ioctl = rtl8125_do_ioctl, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) + .ndo_set_multicast_list = rtl8125_set_rx_mode, +#else + .ndo_set_rx_mode = rtl8125_set_rx_mode, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) +#ifdef CONFIG_R8125_VLAN + .ndo_vlan_rx_register = rtl8125_vlan_rx_register, +#endif +#else + .ndo_fix_features = rtl8125_fix_features, + .ndo_set_features = rtl8125_set_features, +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = rtl8125_netpoll, +#endif +}; +#endif + + +#ifdef CONFIG_R8125_NAPI + +static int rtl8125_poll(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + unsigned int work_done = 0; + int i; + + for (i = 0; i < tp->num_rx_rings; i++) + work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); + + for (i = 0; i < tp->num_tx_rings; i++) + rtl8125_tx_interrupt(&tp->tx_ring[i], budget); + + RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); + + if (work_done < work_to_do) { +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + HandleDashInterrupt(tp->dev); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_done); +#endif + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + + rtl8125_switch_to_timer_interrupt(tp); + } + + return RTL_NAPI_RETURN_VALUE; +} + +#if 0 +static int rtl8125_poll_msix_ring(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + unsigned int work_done = 0; + const int message_id = r8125napi->index; + + work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); + + rtl8125_tx_interrupt_with_vector(tp, message_id, budget); + + RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); + + if (work_done < work_to_do) { +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH && message_id == 0) + HandleDashInterrupt(tp->dev); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_done); +#endif + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + + rtl8125_enable_hw_interrupt_v2(tp, message_id); + } + + return RTL_NAPI_RETURN_VALUE; +} +#endif + +static int rtl8125_poll_msix_tx(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + unsigned int work_done = 0; + const int message_id = r8125napi->index; + + //suppress unused variable + (void)(dev); + + rtl8125_tx_interrupt_with_vector(tp, message_id, budget); + + RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); + + if (work_done < work_to_do) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_done); +#endif + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + + rtl8125_enable_hw_interrupt_v2(tp, message_id); + } + + return RTL_NAPI_RETURN_VALUE; +} + +static int rtl8125_poll_msix_other(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + const int message_id = r8125napi->index; + + //suppress unused variable + (void)(dev); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); +#endif + + rtl8125_enable_hw_interrupt_v2(tp, message_id); + + return 1; +} + +static int rtl8125_poll_msix_rx(napi_ptr napi, napi_budget budget) +{ + struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); + struct rtl8125_private *tp = r8125napi->priv; + RTL_GET_NETDEV(tp) + unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); + unsigned int work_done = 0; + const int message_id = r8125napi->index; + + work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); + + RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); + + if (work_done < work_to_do) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) + if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; +#else + RTL_NETIF_RX_COMPLETE(dev, napi, work_done); +#endif + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + + rtl8125_enable_hw_interrupt_v2(tp, message_id); + } + + return RTL_NAPI_RETURN_VALUE; +} + +static void rtl8125_enable_napi(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + int i; + + for (i = 0; i < tp->irq_nvecs; i++) + RTL_NAPI_ENABLE(tp->dev, &tp->r8125napi[i].napi); +#endif +} + +static void rtl8125_disable_napi(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + int i; + + for (i = 0; i < tp->irq_nvecs; i++) + RTL_NAPI_DISABLE(tp->dev, &tp->r8125napi[i].napi); +#endif +} + +static void rtl8125_del_napi(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + int i; + + for (i = 0; i < tp->irq_nvecs; i++) + RTL_NAPI_DEL((&tp->r8125napi[i])); +#endif +} +#endif //CONFIG_R8125_NAPI + +static void rtl8125_init_napi(struct rtl8125_private *tp) +{ + int i; + + for (i=0; iirq_nvecs; i++) { + struct r8125_napi *r8125napi = &tp->r8125napi[i]; +#ifdef CONFIG_R8125_NAPI + int (*poll)(struct napi_struct *, int); + + if (tp->features & RTL_FEATURE_MSIX && + tp->HwCurrIsrVer == 2) { + if (i < R8125_MAX_RX_QUEUES_VEC_V3) + poll = rtl8125_poll_msix_rx; + else if (i == 16 || i == 18) + poll = rtl8125_poll_msix_tx; + else + poll = rtl8125_poll_msix_other; + } else { + poll = rtl8125_poll; + } + + RTL_NAPI_CONFIG(tp->dev, r8125napi, poll, R8125_NAPI_WEIGHT); +#endif + + r8125napi->priv = tp; + r8125napi->index = i; + } +} + +static int +rtl8125_set_real_num_queue(struct rtl8125_private *tp) +{ + int retval = 0; + + retval = netif_set_real_num_tx_queues(tp->dev, tp->num_tx_rings); + if (retval < 0) + goto exit; + + retval = netif_set_real_num_rx_queues(tp->dev, tp->num_rx_rings); + if (retval < 0) + goto exit; + +exit: + return retval; +} + +static int __devinit +rtl8125_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *dev = NULL; + struct rtl8125_private *tp; + void __iomem *ioaddr = NULL; + static int board_idx = -1; + + int rc; + + assert(pdev != NULL); + assert(ent != NULL); + + board_idx++; + + if (netif_msg_drv(&debug)) + printk(KERN_INFO "%s 2.5Gigabit Ethernet driver %s loaded\n", + MODULENAME, RTL8125_VERSION); + + rc = rtl8125_init_board(pdev, &dev, &ioaddr); + if (rc) + goto out; + + tp = netdev_priv(dev); + assert(ioaddr != NULL); + + tp->set_speed = rtl8125_set_speed_xmii; + tp->get_settings = rtl8125_gset_xmii; + tp->phy_reset_enable = rtl8125_xmii_reset_enable; + tp->phy_reset_pending = rtl8125_xmii_reset_pending; + tp->link_ok = rtl8125_xmii_link_ok; + + rc = rtl8125_try_msi(tp); + if (rc < 0) { + dev_err(&pdev->dev, "Can't allocate interrupt\n"); + goto err_out_1; + } + + rtl8125_init_software_variable(dev); + + RTL_NET_DEVICE_OPS(rtl8125_netdev_ops); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + SET_ETHTOOL_OPS(dev, &rtl8125_ethtool_ops); +#endif + + dev->watchdog_timeo = RTL8125_TX_TIMEOUT; + dev->irq = rtl8125_get_irq(pdev); + dev->base_addr = (unsigned long) ioaddr; + + rtl8125_init_napi(tp); + +#ifdef CONFIG_R8125_VLAN + if (tp->mcfg != CFG_METHOD_DEFAULT) { + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + dev->vlan_rx_kill_vid = rtl8125_vlan_rx_kill_vid; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + } +#endif + + /* There has been a number of reports that using SG/TSO results in + * tx timeouts. However for a lot of people SG/TSO works fine. + * Therefore disable both features by default, but allow users to + * enable them. Use at own risk! + */ + tp->cp_cmd |= RTL_R16(tp, CPlusCmd); + if (tp->mcfg != CFG_METHOD_DEFAULT) { + dev->features |= NETIF_F_IP_CSUM; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + tp->cp_cmd |= RxChkSum; +#else + dev->features |= NETIF_F_RXCSUM; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_HIGHDMA; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) + dev->hw_features |= NETIF_F_RXALL; + dev->hw_features |= NETIF_F_RXFCS; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + dev->features |= NETIF_F_IPV6_CSUM; + netif_set_gso_max_size(dev, LSO_64K); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) + dev->gso_max_segs = NIC_MAX_PHYS_BUF_COUNT_LSO2; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + dev->gso_min_segs = NIC_MIN_PHYS_BUF_COUNT; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) + +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + +#ifdef ENABLE_RSS_SUPPORT + if (tp->EnableRss) { + dev->hw_features |= NETIF_F_RXHASH; + dev->features |= NETIF_F_RXHASH; + } +#endif + } + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) + AllocateDashShareMemory(dev); +#endif + +#ifdef ENABLE_LIB_SUPPORT + ATOMIC_INIT_NOTIFIER_HEAD(&tp->lib_nh); +#endif + rtl8125_init_all_schedule_work(tp); + + rc = rtl8125_set_real_num_queue(tp); + if (rc < 0) + goto err_out; + + rtl8125_exit_oob(dev); + + rtl8125_powerup_pll(dev); + + rtl8125_hw_init(dev); + + rtl8125_hw_reset(dev); + + /* Get production from EEPROM */ + rtl8125_eeprom_type(tp); + + if (tp->eeprom_type == EEPROM_TYPE_93C46 || tp->eeprom_type == EEPROM_TYPE_93C56) + rtl8125_set_eeprom_sel_low(tp); + + rtl8125_get_mac_address(dev); + + tp->fw_name = rtl_chip_fw_infos[tp->mcfg].fw_name; + + tp->tally_vaddr = dma_alloc_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), + &tp->tally_paddr, GFP_KERNEL); + if (!tp->tally_vaddr) { + rc = -ENOMEM; + goto err_out; + } + + rtl8125_tally_counter_clear(tp); + + pci_set_drvdata(pdev, dev); + + rc = register_netdev(dev); + if (rc) + goto err_out; + + printk(KERN_INFO "%s: This product is covered by one or more of the following patents: US6,570,884, US6,115,776, and US6,327,625.\n", MODULENAME); + + rtl8125_disable_rxdvgate(dev); + + device_set_wakeup_enable(&pdev->dev, tp->wol_enabled); + + netif_carrier_off(dev); + + printk("%s", GPL_CLAIM); + +out: + return rc; + +err_out: + if (tp->tally_vaddr != NULL) { + dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, + tp->tally_paddr); + + tp->tally_vaddr = NULL; + } +#ifdef CONFIG_R8125_NAPI + rtl8125_del_napi(tp); +#endif + rtl8125_disable_msi(pdev, tp); + +err_out_1: + rtl8125_release_board(pdev, dev); + + goto out; +} + +static void __devexit +rtl8125_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rtl8125_private *tp = netdev_priv(dev); + + assert(dev != NULL); + assert(tp != NULL); + + set_bit(R8125_FLAG_DOWN, tp->task_flags); + + rtl8125_cancel_all_schedule_work(tp); + +#ifdef CONFIG_R8125_NAPI + rtl8125_del_napi(tp); +#endif + if (tp->DASH) + rtl8125_driver_stop(tp); + + unregister_netdev(dev); + rtl8125_disable_msi(pdev, tp); +#ifdef ENABLE_R8125_PROCFS + rtl8125_proc_remove(dev); +#endif + if (tp->tally_vaddr != NULL) { + dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, tp->tally_paddr); + tp->tally_vaddr = NULL; + } + + rtl8125_release_board(pdev, dev); + +#ifdef ENABLE_USE_FIRMWARE_FILE + rtl8125_release_firmware(tp); +#endif + + pci_set_drvdata(pdev, NULL); +} + +static void +rtl8125_set_rxbufsize(struct rtl8125_private *tp, + struct net_device *dev) +{ + unsigned int mtu = dev->mtu; + + tp->rx_buf_sz = (mtu > ETH_DATA_LEN) ? mtu + ETH_HLEN + 8 + 1 : RX_BUF_SIZE; +} + +static void rtl8125_free_irq(struct rtl8125_private *tp) +{ + int i; + + for (i=0; iirq_nvecs; i++) { + struct r8125_irq *irq = &tp->irq_tbl[i]; + struct r8125_napi *r8125napi = &tp->r8125napi[i]; + + if (irq->requested) { + irq->requested = 0; +#if defined(RTL_USE_NEW_INTR_API) + pci_free_irq(tp->pci_dev, i, r8125napi); +#else + free_irq(irq->vector, r8125napi); +#endif + } + } +} + +static int rtl8125_alloc_irq(struct rtl8125_private *tp) +{ + struct net_device *dev = tp->dev; + int rc = 0; + struct r8125_irq *irq; + struct r8125_napi *r8125napi; + int i = 0; + const int len = sizeof(tp->irq_tbl[0].name); + +#if defined(RTL_USE_NEW_INTR_API) + for (i=0; iirq_nvecs; i++) { + irq = &tp->irq_tbl[i]; + if (tp->features & RTL_FEATURE_MSIX && + tp->HwCurrIsrVer == 2) + irq->handler = rtl8125_interrupt_msix; + else + irq->handler = rtl8125_interrupt; + + r8125napi = &tp->r8125napi[i]; + snprintf(irq->name, len, "%s-%d", dev->name, i); + rc = pci_request_irq(tp->pci_dev, i, irq->handler, NULL, r8125napi, + irq->name); + if (rc) + break; + + irq->vector = pci_irq_vector(tp->pci_dev, i); + irq->requested = 1; + } +#else + unsigned long irq_flags = 0; +#ifdef ENABLE_LIB_SUPPORT + irq_flags |= IRQF_NO_SUSPEND; +#endif + if (tp->features & RTL_FEATURE_MSIX && + tp->HwCurrIsrVer == 2) { + for (i=0; iirq_nvecs; i++) { + irq = &tp->irq_tbl[i]; + irq->handler = rtl8125_interrupt_msix; + r8125napi = &tp->r8125napi[i]; + snprintf(irq->name, len, "%s-%d", dev->name, i); + rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); + + if (rc) + break; + + irq->requested = 1; + } + } else { + irq = &tp->irq_tbl[0]; + irq->handler = rtl8125_interrupt; + r8125napi = &tp->r8125napi[0]; + snprintf(irq->name, len, "%s-0", dev->name); + if (!(tp->features & RTL_FEATURE_MSIX)) + irq->vector = dev->irq; + irq_flags |= (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) ? 0 : SA_SHIRQ; + rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); + + if (rc == 0) + irq->requested = 1; + } +#endif + if (rc) + rtl8125_free_irq(tp); + + return rc; +} + +static int rtl8125_alloc_tx_desc(struct rtl8125_private *tp) +{ + struct rtl8125_tx_ring *ring; + struct pci_dev *pdev = tp->pci_dev; + int i; + + for (i = 0; i < tp->num_tx_rings; i++) { + ring = &tp->tx_ring[i]; + ring->TxDescArray = dma_alloc_coherent(&pdev->dev, R8125_TX_RING_BYTES, + &ring->TxPhyAddr, GFP_KERNEL); + + if (!ring->TxDescArray) + return -1; + } + + return 0; +} + +static int rtl8125_alloc_rx_desc(struct rtl8125_private *tp) +{ + struct rtl8125_rx_ring *ring; + struct pci_dev *pdev = tp->pci_dev; + int i; + + for (i = 0; i < tp->num_rx_rings; i++) { + ring = &tp->rx_ring[i]; + ring->RxDescArray = dma_alloc_coherent(&pdev->dev, tp->RxDescRingLength, + &ring->RxPhyAddr, GFP_KERNEL); + + if (!ring->RxDescArray) + return -1; + } + + return 0; +} + +static void rtl8125_free_tx_desc(struct rtl8125_private *tp) +{ + struct rtl8125_tx_ring *ring; + struct pci_dev *pdev = tp->pci_dev; + int i; + + for (i = 0; i < tp->num_tx_rings; i++) { + ring = &tp->tx_ring[i]; + if (ring->TxDescArray) { + dma_free_coherent(&pdev->dev, R8125_TX_RING_BYTES, ring->TxDescArray, + ring->TxPhyAddr); + ring->TxDescArray = NULL; + } + } +} + +static void rtl8125_free_rx_desc(struct rtl8125_private *tp) +{ + struct rtl8125_rx_ring *ring; + struct pci_dev *pdev = tp->pci_dev; + int i; + + for (i = 0; i < tp->num_rx_rings; i++) { + ring = &tp->rx_ring[i]; + if (ring->RxDescArray) { + dma_free_coherent(&pdev->dev, tp->RxDescRingLength, ring->RxDescArray, + ring->RxPhyAddr); + ring->RxDescArray = NULL; + } + } +} + +static void rtl8125_free_alloc_resources(struct rtl8125_private *tp) +{ + rtl8125_free_rx_desc(tp); + + rtl8125_free_tx_desc(tp); +} + +#ifdef ENABLE_USE_FIRMWARE_FILE +static void rtl8125_request_firmware(struct rtl8125_private *tp) +{ + struct rtl8125_fw *rtl_fw; + + /* firmware loaded already or no firmware available */ + if (tp->rtl_fw || !tp->fw_name) + return; + + rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); + if (!rtl_fw) + return; + + rtl_fw->phy_write = rtl8125_mdio_write; + rtl_fw->phy_read = rtl8125_mdio_read; + rtl_fw->mac_mcu_write = mac_mcu_write; + rtl_fw->mac_mcu_read = mac_mcu_read; + rtl_fw->fw_name = tp->fw_name; + rtl_fw->dev = tp_to_dev(tp); + + if (rtl8125_fw_request_firmware(rtl_fw)) + kfree(rtl_fw); + else + tp->rtl_fw = rtl_fw; +} +#endif + +int rtl8125_open(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int retval; + + retval = -ENOMEM; + +#ifdef ENABLE_R8125_PROCFS + rtl8125_proc_init(dev); +#endif + rtl8125_set_rxbufsize(tp, dev); + /* + * Rx and Tx descriptors needs 256 bytes alignment. + * pci_alloc_consistent provides more. + */ + if (rtl8125_alloc_tx_desc(tp) < 0 || rtl8125_alloc_rx_desc(tp) < 0) + goto err_free_all_allocated_mem; + + retval = rtl8125_init_ring(dev); + if (retval < 0) + goto err_free_all_allocated_mem; + + retval = rtl8125_alloc_irq(tp); + if (retval < 0) + goto err_free_all_allocated_mem; + + if (netif_msg_probe(tp)) { + printk(KERN_INFO "%s: 0x%lx, " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " + "IRQ %d\n", + dev->name, + dev->base_addr, + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5], dev->irq); + } + +#ifdef ENABLE_USE_FIRMWARE_FILE + rtl8125_request_firmware(tp); +#endif + pci_set_master(tp->pci_dev); + +#ifdef CONFIG_R8125_NAPI + rtl8125_enable_napi(tp); +#endif + + rtl8125_exit_oob(dev); + + rtl8125_up(dev); + +#ifdef ENABLE_PTP_SUPPORT + if (tp->EnablePtp) + rtl8125_ptp_init(tp); +#endif + clear_bit(R8125_FLAG_DOWN, tp->task_flags); + + if (tp->resume_not_chg_speed) + rtl8125_check_link_status(dev); + else + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + + if (tp->esd_flag == 0) { + //rtl8125_request_esd_timer(dev); + + rtl8125_schedule_esd_work(tp); + } + + //rtl8125_request_link_timer(dev); + + rtl8125_enable_hw_linkchg_interrupt(tp); + +out: + + return retval; + +err_free_all_allocated_mem: + rtl8125_free_alloc_resources(tp); + + goto out; +} + +static void +set_offset70F(struct rtl8125_private *tp, u8 setting) +{ + u32 csi_tmp; + u32 temp = (u32)setting; + temp = temp << 24; + /*set PCI configuration space offset 0x70F to setting*/ + /*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/ + + csi_tmp = rtl8125_csi_read(tp, 0x70c) & 0x00ffffff; + rtl8125_csi_write(tp, 0x70c, csi_tmp | temp); +} + +static void +set_offset79(struct rtl8125_private *tp, u8 setting) +{ + //Set PCI configuration space offset 0x79 to setting + + struct pci_dev *pdev = tp->pci_dev; + u8 device_control; + + if (hwoptimize & HW_PATCH_SOC_LAN) return; + + pci_read_config_byte(pdev, 0x79, &device_control); + device_control &= ~0x70; + device_control |= setting; + pci_write_config_byte(pdev, 0x79, device_control); +} + +void +rtl8125_hw_set_rx_packet_filter(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + u32 mc_filter[2]; /* Multicast hash filter */ + int rx_mode; + u32 tmp = 0; + + if (dev->flags & IFF_PROMISC) { + /* Unconditionally log net taps. */ + if (netif_msg_link(tp)) + printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", + dev->name); + + rx_mode = + AcceptBroadcast | AcceptMulticast | AcceptMyPhys | + AcceptAllPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; + } else if ((netdev_mc_count(dev) > multicast_filter_limit) + || (dev->flags & IFF_ALLMULTI)) { + /* Too many to filter perfectly -- accept all multicasts. */ + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; + } else { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) + struct dev_mc_list *mclist; + unsigned int i; + + rx_mode = AcceptBroadcast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0; + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) { + int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); + rx_mode |= AcceptMulticast; + } +#else + struct netdev_hw_addr *ha; + + rx_mode = AcceptBroadcast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0; + netdev_for_each_mc_addr(ha, dev) { + int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); + rx_mode |= AcceptMulticast; + } +#endif + } + + if (dev->features & NETIF_F_RXALL) + rx_mode |= (AcceptErr | AcceptRunt); + + tmp = mc_filter[0]; + mc_filter[0] = swab32(mc_filter[1]); + mc_filter[1] = swab32(tmp); + + tmp = tp->rtl8125_rx_config | rx_mode | (RTL_R32(tp, RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); + + RTL_W32(tp, RxConfig, tmp); + RTL_W32(tp, MAR0 + 0, mc_filter[0]); + RTL_W32(tp, MAR0 + 4, mc_filter[1]); +} + +static void +rtl8125_set_rx_mode(struct net_device *dev) +{ + rtl8125_hw_set_rx_packet_filter(dev); +} + +void +rtl8125_set_rx_q_num(struct rtl8125_private *tp, + unsigned int num_rx_queues) +{ + u16 q_ctrl; + u16 rx_q_num; + + rx_q_num = (u16)ilog2(num_rx_queues); + rx_q_num &= (BIT_0 | BIT_1 | BIT_2); + rx_q_num <<= 2; + q_ctrl = RTL_R16(tp, Q_NUM_CTRL_8125); + q_ctrl &= ~(BIT_2 | BIT_3 | BIT_4); + q_ctrl |= rx_q_num; + RTL_W16(tp, Q_NUM_CTRL_8125, q_ctrl); +} + +void +rtl8125_set_tx_q_num(struct rtl8125_private *tp, + unsigned int num_tx_queues) +{ + u16 mac_ocp_data; + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); + mac_ocp_data &= ~(BIT_11 | BIT_10); + mac_ocp_data |= ((ilog2(num_tx_queues) & 0x03) << 10); + rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); +} + +void +rtl8125_hw_config(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + struct pci_dev *pdev = tp->pci_dev; + u16 mac_ocp_data; + int i; + + RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); + + rtl8125_hw_reset(dev); + + rtl8125_enable_cfg9346_write(tp); + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + break; + } + + //clear io_rdy_l23 + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~BIT_1); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + //IntMITI_0-IntMITI_31 + for (i=0xA00; i<0xB00; i+=4) + RTL_W32(tp, i, 0x00000000); + break; + } + + //keep magic packet only + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B6); + mac_ocp_data &= BIT_0; + rtl8125_mac_ocp_write(tp, 0xC0B6, mac_ocp_data); + break; + } + + rtl8125_tally_counter_addr_fill(tp); + + rtl8125_enable_extend_tally_couter(tp); + + rtl8125_desc_addr_fill(tp); + + /* Set DMA burst size and Interframe Gap Time */ + RTL_W32(tp, TxConfig, (TX_DMA_BURST_unlimited << TxDMAShift) | + (InterFrameGap << TxInterFrameGapShift)); + + if (tp->EnableTxNoClose) + RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_6)); + + if (tp->mcfg == CFG_METHOD_2 || + tp->mcfg == CFG_METHOD_3 || + tp->mcfg == CFG_METHOD_4 || + tp->mcfg == CFG_METHOD_5) { + set_offset70F(tp, 0x27); + set_offset79(tp, 0x50); + + RTL_W16(tp, 0x382, 0x221B); + +#ifdef ENABLE_RSS_SUPPORT + rtl8125_config_rss(tp); +#else + RTL_W32(tp, RSS_CTRL_8125, 0x00); +#endif + rtl8125_set_rx_q_num(tp, rtl8125_tot_rx_rings(tp)); + + RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10); + + rtl8125_mac_ocp_write(tp, 0xC140, 0xFFFF); + rtl8125_mac_ocp_write(tp, 0xC142, 0xFFFF); + + //new tx desc format + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB58); + mac_ocp_data |= (BIT_0); + rtl8125_mac_ocp_write(tp, 0xEB58, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE614); + mac_ocp_data &= ~( BIT_10 | BIT_9 | BIT_8); + if (tp->mcfg == CFG_METHOD_4 || tp->mcfg == CFG_METHOD_5) { + mac_ocp_data |= ((2 & 0x07) << 8); + } else { + if (tp->DASH && !(rtl8125_csi_fun0_read_byte(tp, 0x79) & BIT_0)) + mac_ocp_data |= ((3 & 0x07) << 8); + else + mac_ocp_data |= ((4 & 0x07) << 8); + } + rtl8125_mac_ocp_write(tp, 0xE614, mac_ocp_data); + + rtl8125_set_tx_q_num(tp, rtl8125_tot_tx_rings(tp)); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); + mac_ocp_data &= ~(BIT_5 | BIT_4); + if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) + mac_ocp_data |= ((0x02 & 0x03) << 4); + rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); + mac_ocp_data &= ~BIT_0; + rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); + mac_ocp_data |= BIT_0; + rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); + mac_ocp_data |= (BIT_3|BIT_2); + rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB6A); + mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); + mac_ocp_data |= (BIT_5 | BIT_4 | BIT_1 | BIT_0); + rtl8125_mac_ocp_write(tp, 0xEB6A, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB50); + mac_ocp_data &= ~(BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5); + mac_ocp_data |= (BIT_6); + rtl8125_mac_ocp_write(tp, 0xEB50, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE056); + mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4); + //mac_ocp_data |= (BIT_4 | BIT_5); + rtl8125_mac_ocp_write(tp, 0xE056, mac_ocp_data); + + RTL_W8(tp, TDFNR, 0x10); + + RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE040); + mac_ocp_data &= ~(BIT_12); + rtl8125_mac_ocp_write(tp, 0xE040, mac_ocp_data); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); + mac_ocp_data &= ~(BIT_1 | BIT_0); + mac_ocp_data |= (BIT_0); + rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); + + rtl8125_mac_ocp_write(tp, 0xE0C0, 0x4000); + + SetMcuAccessRegBit(tp, 0xE052, (BIT_6 | BIT_5)); + ClearMcuAccessRegBit(tp, 0xE052, BIT_3 | BIT_7); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xD430); + mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); + mac_ocp_data |= 0x45F; + rtl8125_mac_ocp_write(tp, 0xD430, mac_ocp_data); + + //rtl8125_mac_ocp_write(tp, 0xE0C0, 0x4F87); + if (!tp->DASH) + RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6 | BIT_7); + else + RTL_W8(tp, 0xD0, (RTL_R8(tp, 0xD0) & ~BIT_6) | BIT_7); + + if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3) + RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | BIT_0); + + rtl8125_disable_eee_plus(tp); + + mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); + mac_ocp_data &= ~(BIT_2); + rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); + + SetMcuAccessRegBit(tp, 0xEB54, BIT_0); + udelay(1); + ClearMcuAccessRegBit(tp, 0xEB54, BIT_0); + RTL_W16(tp, 0x1880, RTL_R16(tp, 0x1880) & ~(BIT_4 | BIT_5)); + } + + /* csum offload command for RTL8125 */ + tp->tx_tcp_csum_cmd = TxTCPCS_C; + tp->tx_udp_csum_cmd = TxUDPCS_C; + tp->tx_ip_csum_cmd = TxIPCS_C; + tp->tx_ipv6_csum_cmd = TxIPV6F_C; + + /* config interrupt type for RTL8125B */ + if (tp->HwSuppIsrVer == 2) + rtl8125_hw_set_interrupt_type(tp, tp->HwCurrIsrVer); + + //other hw parameters + rtl8125_hw_clear_timer_int(dev); + + rtl8125_hw_clear_int_miti(dev); + + if (tp->use_timer_interrrupt && + (tp->HwCurrIsrVer == 2) && + (tp->HwSuppIntMitiVer == 4) && + (tp->features & RTL_FEATURE_MSIX)) { + int i; + for (i = 0; i < tp->irq_nvecs; i++) + rtl8125_hw_set_timer_int_8125(tp, i, timer_count_v2); + } + + rtl8125_enable_exit_l1_mask(tp); + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + rtl8125_mac_ocp_write(tp, 0xE098, 0xC302); + break; + } + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + if (aspm) { + rtl8125_init_pci_offset_99(tp); + } + break; + } + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + if (aspm) { + rtl8125_init_pci_offset_180(tp); + } + break; + } + + tp->cp_cmd &= ~(EnableBist | Macdbgo_oe | Force_halfdup | + Force_rxflow_en | Force_txflow_en | Cxpl_dbg_sel | + ASF | Macdbgo_sel); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + RTL_W16(tp, CPlusCmd, tp->cp_cmd); +#else + rtl8125_hw_set_features(dev, dev->features); +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: { + int timeout; + for (timeout = 0; timeout < 10; timeout++) { + if ((rtl8125_mac_ocp_read(tp, 0xE00E) & BIT_13)==0) + break; + mdelay(1); + } + } + break; + } + + RTL_W16(tp, RxMaxSize, tp->rx_buf_sz); + + rtl8125_disable_rxdvgate(dev); + + if (!tp->pci_cfg_is_read) { + pci_read_config_byte(pdev, PCI_COMMAND, &tp->pci_cfg_space.cmd); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &tp->pci_cfg_space.io_base_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, &tp->pci_cfg_space.io_base_h); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &tp->pci_cfg_space.mem_base_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &tp->pci_cfg_space.mem_base_h); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &tp->pci_cfg_space.resv_0x1c_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &tp->pci_cfg_space.resv_0x1c_h); + pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tp->pci_cfg_space.ilr); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &tp->pci_cfg_space.resv_0x20_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &tp->pci_cfg_space.resv_0x20_h); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &tp->pci_cfg_space.resv_0x24_l); + pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &tp->pci_cfg_space.resv_0x24_h); + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->pci_cfg_space.resv_0x2c_l); + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &tp->pci_cfg_space.resv_0x2c_h); + if (tp->HwPcieSNOffset > 0) { + tp->pci_cfg_space.pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); + tp->pci_cfg_space.pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); + } + + tp->pci_cfg_is_read = 1; + } + + /* Set Rx packet filter */ + rtl8125_hw_set_rx_packet_filter(dev); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH && !tp->dash_printer_enabled) + NICChkTypeEnableDashInterrupt(tp); +#endif + + switch (tp->mcfg) { + case CFG_METHOD_2: + case CFG_METHOD_3: + case CFG_METHOD_4: + case CFG_METHOD_5: + if (aspm) { + RTL_W8(tp, Config5, RTL_R8(tp, Config5) | BIT_0); + RTL_W8(tp, Config2, RTL_R8(tp, Config2) | BIT_7); + } else { + RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); + RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); + } + break; + } + + rtl8125_disable_cfg9346_write(tp); + + udelay(10); +} + +void +rtl8125_hw_start(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); + + rtl8125_enable_hw_interrupt(tp); + + rtl8125_lib_reset_complete(tp); +} + +static int +rtl8125_change_mtu(struct net_device *dev, + int new_mtu) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret = 0; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) + if (new_mtu < ETH_MIN_MTU) + return -EINVAL; + else if (new_mtu > tp->max_jumbo_frame_size) + new_mtu = tp->max_jumbo_frame_size; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) + + dev->mtu = new_mtu; + + if (!netif_running(dev)) + goto out; + + rtl8125_down(dev); + + rtl8125_set_rxbufsize(tp, dev); + + ret = rtl8125_init_ring(dev); + + if (ret < 0) + goto err_out; + +#ifdef CONFIG_R8125_NAPI + rtl8125_enable_napi(tp); +#endif//CONFIG_R8125_NAPI + + //netif_tx_stop_all_queues(dev); + //netif_carrier_off(dev); + rtl8125_hw_config(dev); + rtl8125_enable_hw_linkchg_interrupt(tp); + + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + + //mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); + //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); +out: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) + netdev_update_features(dev); +#endif + +err_out: + return ret; +} + +static void +rtl8125_free_rx_skb(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct sk_buff **sk_buff, + struct RxDesc *desc, + const u32 cur_rx) +{ + struct pci_dev *pdev = tp->pci_dev; + + dma_unmap_single(&pdev->dev, ring->RxDescPhyAddr[cur_rx], tp->rx_buf_sz, + DMA_FROM_DEVICE); + dev_kfree_skb(*sk_buff); + *sk_buff = NULL; + rtl8125_make_unusable_by_asic(tp, desc); +} + +static inline void +rtl8125_mark_to_asic_v3(struct RxDescV3 *descv3, + u32 rx_buf_sz) +{ + u32 eor = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1) & RingEnd; + + WRITE_ONCE(descv3->RxDescNormalDDWord4.opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); +} + +void +rtl8125_mark_to_asic(struct rtl8125_private *tp, + struct RxDesc *desc, + u32 rx_buf_sz) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + rtl8125_mark_to_asic_v3((struct RxDescV3 *)desc, rx_buf_sz); + else { + u32 eor = le32_to_cpu(desc->opts1) & RingEnd; + + WRITE_ONCE(desc->opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); + } +} + +static inline void +rtl8125_map_to_asic(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct RxDesc *desc, + dma_addr_t mapping, + u32 rx_buf_sz, + const u32 cur_rx) +{ + ring->RxDescPhyAddr[cur_rx] = mapping; + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + ((struct RxDescV3 *)desc)->addr = cpu_to_le64(mapping); + else + desc->addr = cpu_to_le64(mapping); + wmb(); + rtl8125_mark_to_asic(tp, desc, rx_buf_sz); +} + +static int +rtl8125_alloc_rx_skb(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct sk_buff **sk_buff, + struct RxDesc *desc, + int rx_buf_sz, + const u32 cur_rx, + u8 in_intr) +{ + struct sk_buff *skb; + dma_addr_t mapping; + int ret = 0; + + if (in_intr) + skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, rx_buf_sz + RTK_RX_ALIGN); + else + skb = dev_alloc_skb(rx_buf_sz + RTK_RX_ALIGN); + + if (unlikely(!skb)) + goto err_out; + + skb_reserve(skb, RTK_RX_ALIGN); + + mapping = dma_map_single(tp_to_dev(tp), skb->data, rx_buf_sz, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { + if (unlikely(net_ratelimit())) + netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); + goto err_out; + } + + *sk_buff = skb; + rtl8125_map_to_asic(tp, ring, desc, mapping, rx_buf_sz, cur_rx); +out: + return ret; + +err_out: + if (skb) + dev_kfree_skb(skb); + ret = -ENOMEM; + rtl8125_make_unusable_by_asic(tp, desc); + goto out; +} + +static void +_rtl8125_rx_clear(struct rtl8125_private *tp, struct rtl8125_rx_ring *ring) +{ + int i; + + for (i = 0; i < NUM_RX_DESC; i++) { + if (ring->Rx_skbuff[i]) { + rtl8125_free_rx_skb(tp, + ring, + ring->Rx_skbuff + i, + rtl8125_get_rxdesc(tp, ring->RxDescArray, i), + i); + ring->Rx_skbuff[i] = NULL; + } + } +} + +void +rtl8125_rx_clear(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_rx_rings; i++) + _rtl8125_rx_clear(tp, &tp->rx_ring[i]); +} + +static u32 +rtl8125_rx_fill(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct net_device *dev, + u32 start, + u32 end, + u8 in_intr) +{ + u32 cur; + + for (cur = start; end - cur > 0; cur++) { + int ret, i = cur % NUM_RX_DESC; + + if (ring->Rx_skbuff[i]) + continue; + + ret = rtl8125_alloc_rx_skb(tp, + ring, + ring->Rx_skbuff + i, + rtl8125_get_rxdesc(tp, ring->RxDescArray, i), + tp->rx_buf_sz, + i, + in_intr + ); + if (ret < 0) + break; + } + return cur - start; +} + +static inline void +rtl8125_mark_as_last_descriptor_8125(struct RxDescV3 *descv3) +{ + descv3->RxDescNormalDDWord4.opts1 |= cpu_to_le32(RingEnd); +} + +static inline void +rtl8125_mark_as_last_descriptor(struct rtl8125_private *tp, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + rtl8125_mark_as_last_descriptor_8125((struct RxDescV3 *)desc); + else + desc->opts1 |= cpu_to_le32(RingEnd); +} + +static void +rtl8125_desc_addr_fill(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_tx_rings; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + RTL_W32(tp, ring->tdsar_reg, ((u64)ring->TxPhyAddr & DMA_BIT_MASK(32))); + RTL_W32(tp, ring->tdsar_reg + 4, ((u64)ring->TxPhyAddr >> 32)); + } + + for (i = 0; i < tp->num_rx_rings; i++) { + struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; + RTL_W32(tp, ring->rdsar_reg, ((u64)ring->RxPhyAddr & DMA_BIT_MASK(32))); + RTL_W32(tp, ring->rdsar_reg + 4, ((u64)ring->RxPhyAddr >> 32)); + } +} + +static void +rtl8125_tx_desc_init(struct rtl8125_private *tp) +{ + int i = 0; + + for (i = 0; i < tp->num_tx_rings; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + memset(ring->TxDescArray, 0x0, R8125_TX_RING_BYTES); + + ring->TxDescArray[NUM_TX_DESC - 1].opts1 = cpu_to_le32(RingEnd); + } +} + +static void +rtl8125_rx_desc_init(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_rx_rings; i++) { + struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; + memset(ring->RxDescArray, 0x0, tp->RxDescRingLength); + } +} + +int +rtl8125_init_ring(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + + rtl8125_init_ring_indexes(tp); + + rtl8125_tx_desc_init(tp); + rtl8125_rx_desc_init(tp); + + for (i = 0; i < tp->num_tx_rings; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + memset(ring->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); + } + + for (i = 0; i < tp->num_rx_rings; i++) { + struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; + + memset(ring->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); + if (rtl8125_rx_fill(tp, ring, dev, 0, NUM_RX_DESC, 0) != NUM_RX_DESC) + goto err_out; + + rtl8125_mark_as_last_descriptor(tp, rtl8125_get_rxdesc(tp, ring->RxDescArray, NUM_RX_DESC - 1)); + } + + return 0; + +err_out: + rtl8125_rx_clear(tp); + return -ENOMEM; +} + +static void +rtl8125_unmap_tx_skb(struct pci_dev *pdev, + struct ring_info *tx_skb, + struct TxDesc *desc) +{ + unsigned int len = tx_skb->len; + + dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); + + desc->opts1 = cpu_to_le32(RTK_MAGIC_DEBUG_VALUE); + desc->opts2 = 0x00; + desc->addr = RTL8125_MAGIC_NUMBER; + tx_skb->len = 0; +} + +static void +rtl8125_tx_clear_range(struct rtl8125_private *tp, + struct rtl8125_tx_ring *ring, + u32 start, + unsigned int n) +{ + unsigned int i; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + struct net_device *dev = tp->dev; +#endif + + for (i = 0; i < n; i++) { + unsigned int entry = (start + i) % NUM_TX_DESC; + struct ring_info *tx_skb = ring->tx_skb + entry; + unsigned int len = tx_skb->len; + + if (len) { + struct sk_buff *skb = tx_skb->skb; + + rtl8125_unmap_tx_skb(tp->pci_dev, tx_skb, + ring->TxDescArray + entry); + if (skb) { + RTLDEV->stats.tx_dropped++; + dev_kfree_skb_any(skb); + tx_skb->skb = NULL; + } + } + } +} + +void +rtl8125_tx_clear(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_tx_rings; i++) { + struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; + rtl8125_tx_clear_range(tp, ring, ring->dirty_tx, NUM_TX_DESC); + ring->cur_tx = ring->dirty_tx = 0; + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_schedule_reset_work(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + set_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags); + schedule_delayed_work(&tp->reset_task, 4); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) +} + +static void rtl8125_schedule_esd_work(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + set_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags); + schedule_delayed_work(&tp->esd_task, RTL8125_ESD_TIMEOUT); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) +} + +static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + set_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags); + schedule_delayed_work(&tp->linkchg_task, 4); +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) +} + +#define rtl8125_cancel_schedule_reset_work(a) +#define rtl8125_cancel_schedule_esd_work(a) +#define rtl8125_cancel_schedule_linkchg_work(a) + +#else +static void rtl8125_schedule_reset_work(struct rtl8125_private *tp) +{ + set_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags); + schedule_delayed_work(&tp->reset_task, 4); +} + +static void rtl8125_cancel_schedule_reset_work(struct rtl8125_private *tp) +{ + struct work_struct *work = &tp->reset_task.work; + + if (!work->func) return; + + cancel_delayed_work_sync(&tp->reset_task); +} + +static void rtl8125_schedule_esd_work(struct rtl8125_private *tp) +{ + set_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags); + schedule_delayed_work(&tp->esd_task, RTL8125_ESD_TIMEOUT); +} + +static void rtl8125_cancel_schedule_esd_work(struct rtl8125_private *tp) +{ + struct work_struct *work = &tp->esd_task.work; + + if (!work->func) return; + + cancel_delayed_work_sync(&tp->esd_task); +} + +static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp) +{ + set_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags); + schedule_delayed_work(&tp->linkchg_task, RTL8125_ESD_TIMEOUT); +} + +static void rtl8125_cancel_schedule_linkchg_work(struct rtl8125_private *tp) +{ + struct work_struct *work = &tp->linkchg_task.work; + + if (!work->func) return; + + cancel_delayed_work_sync(&tp->linkchg_task); +} +#endif + +static void rtl8125_init_all_schedule_work(struct rtl8125_private *tp) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + INIT_WORK(&tp->reset_task, rtl8125_reset_task, dev); + INIT_WORK(&tp->esd_task, rtl8125_esd_task, dev); + INIT_WORK(&tp->linkchg_task, rtl8125_linkchg_task, dev); +#else + INIT_DELAYED_WORK(&tp->reset_task, rtl8125_reset_task); + INIT_DELAYED_WORK(&tp->esd_task, rtl8125_esd_task); + INIT_DELAYED_WORK(&tp->linkchg_task, rtl8125_linkchg_task); +#endif +} + +static void rtl8125_cancel_all_schedule_work(struct rtl8125_private *tp) +{ + rtl8125_cancel_schedule_reset_work(tp); + rtl8125_cancel_schedule_esd_work(tp); + rtl8125_cancel_schedule_linkchg_work(tp); +} + +static void +rtl8125_wait_for_irq_complete(struct rtl8125_private *tp) +{ + if (tp->features & RTL_FEATURE_MSIX) { + int i; + for (i = 0; i < tp->irq_nvecs; i++) + synchronize_irq(tp->irq_tbl[i].vector); + } else { + synchronize_irq(tp->dev->irq); + } +} + +static void +_rtl8125_wait_for_quiescence(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + /* Wait for any pending NAPI task to complete */ +#ifdef CONFIG_R8125_NAPI + rtl8125_disable_napi(tp); +#endif//CONFIG_R8125_NAPI + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,67) + /* Give a racing hard_start_xmit a few cycles to complete. */ + synchronize_net(); +#endif + + rtl8125_irq_mask_and_ack(tp); + + rtl8125_wait_for_irq_complete(tp); +} + +static void +rtl8125_wait_for_quiescence(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + //suppress unused variable + (void)(tp); + + _rtl8125_wait_for_quiescence(dev); + +#ifdef CONFIG_R8125_NAPI + rtl8125_enable_napi(tp); +#endif//CONFIG_R8125_NAPI +} + +static int rtl8125_rx_nostuck(struct rtl8125_private *tp) +{ + int i, ret = 1; + for (i = 0; i < tp->num_rx_rings; i++) + ret &= (tp->rx_ring[i].dirty_rx == tp->rx_ring[i].cur_rx); + return ret; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_reset_task(void *_data) +{ + struct net_device *dev = _data; + struct rtl8125_private *tp = netdev_priv(dev); +#else +static void rtl8125_reset_task(struct work_struct *work) +{ + struct rtl8125_private *tp = + container_of(work, struct rtl8125_private, reset_task.work); + struct net_device *dev = tp->dev; +#endif + u32 budget = ~(u32)0; + int i; + + rtnl_lock(); + + if (!netif_running(dev) || + test_bit(R8125_FLAG_DOWN, tp->task_flags) || + !test_and_clear_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags)) + goto out_unlock; + + rtl8125_wait_for_quiescence(dev); + + for (i = 0; i < tp->num_rx_rings; i++) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], &budget); +#else + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + } + + netif_tx_stop_all_queues(dev); + netif_carrier_off(dev); + rtl8125_hw_reset(dev); + + rtl8125_tx_clear(tp); + + if (rtl8125_rx_nostuck(tp)) { + rtl8125_rx_clear(tp); + rtl8125_init_ring(dev); +#ifdef ENABLE_PTP_SUPPORT + rtl8125_ptp_reset(tp); +#endif + if (tp->resume_not_chg_speed) { + _rtl8125_check_link_status(dev); + + tp->resume_not_chg_speed = 0; + } else { + rtl8125_enable_hw_linkchg_interrupt(tp); + + rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); + } + } else { + if (unlikely(net_ratelimit())) { + struct rtl8125_private *tp = netdev_priv(dev); + + if (netif_msg_intr(tp)) { + printk(PFX KERN_EMERG + "%s: Rx buffers shortage\n", dev->name); + } + } + rtl8125_schedule_reset_work(tp); + } + +out_unlock: + rtnl_unlock(); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_esd_task(void *_data) +{ + struct net_device *dev = _data; + struct rtl8125_private *tp = netdev_priv(dev); +#else +static void rtl8125_esd_task(struct work_struct *work) +{ + struct rtl8125_private *tp = + container_of(work, struct rtl8125_private, esd_task.work); + struct net_device *dev = tp->dev; +#endif + rtnl_lock(); + + if (!netif_running(dev) || + test_bit(R8125_FLAG_DOWN, tp->task_flags) || + !test_and_clear_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags)) + goto out_unlock; + + rtl8125_esd_checker(tp); + + rtl8125_schedule_esd_work(tp); + +out_unlock: + rtnl_unlock(); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void rtl8125_linkchg_task(void *_data) +{ + struct net_device *dev = _data; + //struct rtl8125_private *tp = netdev_priv(dev); +#else +static void rtl8125_linkchg_task(struct work_struct *work) +{ + struct rtl8125_private *tp = + container_of(work, struct rtl8125_private, linkchg_task.work); + struct net_device *dev = tp->dev; +#endif + rtnl_lock(); + + if (!netif_running(dev) || + test_bit(R8125_FLAG_DOWN, tp->task_flags) || + !test_and_clear_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags)) + goto out_unlock; + + rtl8125_check_link_status(dev); + +out_unlock: + rtnl_unlock(); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +static void +rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue) +#else +static void +rtl8125_tx_timeout(struct net_device *dev) +#endif +{ + struct rtl8125_private *tp = netdev_priv(dev); + + /* Let's wait a bit while any (async) irq lands on */ + rtl8125_schedule_reset_work(tp); +} + +static u32 +rtl8125_get_txd_opts1(u32 opts1, u32 len, unsigned int entry) +{ + u32 status = opts1 | len; + + if (entry == NUM_TX_DESC - 1) + status |= RingEnd; + + return status; +} + +static int +rtl8125_xmit_frags(struct rtl8125_private *tp, + struct rtl8125_tx_ring *ring, + struct sk_buff *skb, + const u32 *opts) +{ + struct skb_shared_info *info = skb_shinfo(skb); + unsigned int cur_frag, entry; + struct TxDesc *txd = NULL; + const unsigned char nr_frags = info->nr_frags; + unsigned long PktLenCnt = 0; + bool LsoPatchEnabled = FALSE; + + entry = ring->cur_tx; + for (cur_frag = 0; cur_frag < nr_frags; cur_frag++) { + skb_frag_t *frag = info->frags + cur_frag; + dma_addr_t mapping; + u32 status, len; + void *addr; + + entry = (entry + 1) % NUM_TX_DESC; + + txd = ring->TxDescArray + entry; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) + len = frag->size; + addr = ((void *) page_address(frag->page)) + frag->page_offset; +#else + len = skb_frag_size(frag); + addr = skb_frag_address(frag); +#endif + if (tp->RequireLSOPatch && + (cur_frag == nr_frags - 1) && + (opts[0] & (GiantSendv4|GiantSendv6)) && + PktLenCnt < ETH_FRAME_LEN && + len > 1) { + len -= 1; + mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { + if (unlikely(net_ratelimit())) + netif_err(tp, drv, tp->dev, + "Failed to map TX fragments DMA!\n"); + goto err_out; + } + + /* anti gcc 2.95.3 bugware (sic) */ + status = rtl8125_get_txd_opts1(opts[0], len, entry); + + txd->addr = cpu_to_le64(mapping); + + ring->tx_skb[entry].len = len; + + txd->opts2 = cpu_to_le32(opts[1]); + wmb(); + txd->opts1 = cpu_to_le32(status); + + //second txd + addr += len; + len = 1; + entry = (entry + 1) % NUM_TX_DESC; + txd = ring->TxDescArray + entry; + cur_frag += 1; + + LsoPatchEnabled = TRUE; + } + + mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { + if (unlikely(net_ratelimit())) + netif_err(tp, drv, tp->dev, + "Failed to map TX fragments DMA!\n"); + goto err_out; + } + + /* anti gcc 2.95.3 bugware (sic) */ + status = rtl8125_get_txd_opts1(opts[0], len, entry); + if (cur_frag == (nr_frags - 1) || LsoPatchEnabled == TRUE) { + //ring->tx_skb[entry].skb = skb; + status |= LastFrag; + } + + txd->addr = cpu_to_le64(mapping); + + ring->tx_skb[entry].len = len; + + txd->opts2 = cpu_to_le32(opts[1]); + wmb(); + txd->opts1 = cpu_to_le32(status); + + PktLenCnt += len; + } + + return cur_frag; + +err_out: + rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, cur_frag); + return -EIO; +} + +static inline +__be16 get_protocol(struct sk_buff *skb) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) + return vlan_get_protocol(skb); +#else + __be16 protocol; + + if (skb->protocol == htons(ETH_P_8021Q)) + protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; + else + protocol = skb->protocol; + + return protocol; +#endif +} + +static inline +u8 rtl8125_get_l4_protocol(struct sk_buff *skb) +{ + int no = skb_network_offset(skb); + struct ipv6hdr *i6h, _i6h; + struct iphdr *ih, _ih; + u8 ip_protocol = IPPROTO_RAW; + + switch (get_protocol(skb)) { + case __constant_htons(ETH_P_IP): + ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih); + if (ih) + ip_protocol = ih->protocol; + break; + case __constant_htons(ETH_P_IPV6): + i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h); + if (i6h) + ip_protocol = i6h->nexthdr; + break; + } + + return ip_protocol; +} + +static bool rtl8125_skb_pad_with_len(struct sk_buff *skb, unsigned int len) +{ + if (skb_padto(skb, len)) + return false; + skb_put(skb, len - skb->len); + return true; +} + +static bool rtl8125_skb_pad(struct sk_buff *skb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) + return rtl8125_skb_pad_with_len(skb, ETH_ZLEN); +#else + return !eth_skb_pad(skb); +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) +/* msdn_giant_send_check() + * According to the document of microsoft, the TCP Pseudo Header excludes the + * packet length for IPv6 TCP large packets. + */ +static int msdn_giant_send_check(struct sk_buff *skb) +{ + const struct ipv6hdr *ipv6h; + struct tcphdr *th; + int ret; + + ret = skb_cow_head(skb, 0); + if (ret) + return ret; + + ipv6h = ipv6_hdr(skb); + th = tcp_hdr(skb); + + th->check = 0; + th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0); + + return ret; +} +#endif + +#define MIN_PATCH_LEN (47) +static u32 +rtl8125_get_patch_pad_len(struct sk_buff *skb) +{ + u32 pad_len = 0; + int trans_data_len; + u32 hdr_len; + u32 pkt_len = skb->len; + u8 ip_protocol; + bool has_trans = skb_transport_header_was_set(skb); + + if (!(has_trans && (pkt_len < 175))) //128 + MIN_PATCH_LEN + goto no_padding; + + ip_protocol = rtl8125_get_l4_protocol(skb); + if (!(ip_protocol == IPPROTO_TCP || ip_protocol == IPPROTO_UDP)) + goto no_padding; + + trans_data_len = pkt_len - + (skb->transport_header - + skb_headroom(skb)); + if (ip_protocol == IPPROTO_UDP) { + if (trans_data_len > 3 && trans_data_len < MIN_PATCH_LEN) { + u16 dest_port = 0; + + skb_copy_bits(skb, skb->transport_header - skb_headroom(skb) + 2, &dest_port, 2); + dest_port = ntohs(dest_port); + + if (dest_port == 0x13f || + dest_port == 0x140) { + pad_len = MIN_PATCH_LEN - trans_data_len; + goto out; + } + } + } + + hdr_len = 0; + if (ip_protocol == IPPROTO_TCP) + hdr_len = 20; + else if (ip_protocol == IPPROTO_UDP) + hdr_len = 8; + if (trans_data_len < hdr_len) + pad_len = hdr_len - trans_data_len; + +out: + if ((pkt_len + pad_len) < ETH_ZLEN) + pad_len = ETH_ZLEN - pkt_len; + + return pad_len; + +no_padding: + + return 0; +} + +static bool +rtl8125_tso_csum(struct sk_buff *skb, + struct net_device *dev, + u32 *opts) +{ + struct rtl8125_private *tp = netdev_priv(dev); + unsigned long large_send = 0; + u32 csum_cmd = 0; + u8 sw_calc_csum = false; + u8 check_patch_required = true; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) + u32 mss = skb_shinfo(skb)->tso_size; +#else + u32 mss = skb_shinfo(skb)->gso_size; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) + + /* TCP Segmentation Offload (or TCP Large Send) */ + if (mss) { + u32 transport_offset = (u32)skb_transport_offset(skb); + assert((transport_offset%2) == 0); + switch (get_protocol(skb)) { + case __constant_htons(ETH_P_IP): + if (transport_offset <= GTTCPHO_MAX) { + opts[0] |= GiantSendv4; + opts[0] |= transport_offset << GTTCPHO_SHIFT; + opts[1] |= min(mss, MSS_MAX) << 18; + large_send = 1; + } + break; + case __constant_htons(ETH_P_IPV6): +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) + if (msdn_giant_send_check(skb)) + return false; +#endif + if (transport_offset <= GTTCPHO_MAX) { + opts[0] |= GiantSendv6; + opts[0] |= transport_offset << GTTCPHO_SHIFT; + opts[1] |= min(mss, MSS_MAX) << 18; + large_send = 1; + } + break; + default: + if (unlikely(net_ratelimit())) + dprintk("tso proto=%x!\n", skb->protocol); + break; + } + + if (large_send == 0) + return false; + + return true; + } + } +#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + const struct iphdr *ip = skb->nh.iph; + + if (dev->features & NETIF_F_IP_CSUM) { + if (ip->protocol == IPPROTO_TCP) + csum_cmd = tp->tx_ip_csum_cmd | tp->tx_tcp_csum_cmd; + else if (ip->protocol == IPPROTO_UDP) + csum_cmd = tp->tx_ip_csum_cmd | tp->tx_udp_csum_cmd; + else if (ip->protocol == IPPROTO_IP) + csum_cmd = tp->tx_ip_csum_cmd; + } +#else + u8 ip_protocol = IPPROTO_RAW; + + switch (get_protocol(skb)) { + case __constant_htons(ETH_P_IP): + if (dev->features & NETIF_F_IP_CSUM) { + ip_protocol = ip_hdr(skb)->protocol; + csum_cmd = tp->tx_ip_csum_cmd; + } + break; + case __constant_htons(ETH_P_IPV6): + if (dev->features & NETIF_F_IPV6_CSUM) { + u32 transport_offset = (u32)skb_transport_offset(skb); + if (transport_offset > 0 && transport_offset <= TCPHO_MAX) { + ip_protocol = ipv6_hdr(skb)->nexthdr; + csum_cmd = tp->tx_ipv6_csum_cmd; + csum_cmd |= transport_offset << TCPHO_SHIFT; + } + } + break; + default: + if (unlikely(net_ratelimit())) + dprintk("checksum_partial proto=%x!\n", skb->protocol); + break; + } + + if (ip_protocol == IPPROTO_TCP) + csum_cmd |= tp->tx_tcp_csum_cmd; + else if (ip_protocol == IPPROTO_UDP) + csum_cmd |= tp->tx_udp_csum_cmd; +#endif + if (csum_cmd == 0) { + sw_calc_csum = true; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + WARN_ON(1); /* we need a WARN() */ +#endif + } + + if (ip_protocol == IPPROTO_TCP) + check_patch_required = false; + } + + if (check_patch_required) { + u32 pad_len = rtl8125_get_patch_pad_len(skb); + + if (pad_len > 0) { + if (!rtl8125_skb_pad_with_len(skb, skb->len + pad_len)) + return false; + + if (csum_cmd != 0) + sw_calc_csum = true; + } + } + + if (skb->len < ETH_ZLEN) { + if (tp->UseSwPaddingShortPkt || + (tp->ShortPacketSwChecksum && csum_cmd != 0)) { + if (!rtl8125_skb_pad(skb)) + return false; + + if (csum_cmd != 0) + sw_calc_csum = true; + } + } + + if (sw_calc_csum) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) + skb_checksum_help(&skb, 0); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) + skb_checksum_help(skb, 0); +#else + skb_checksum_help(skb); +#endif + } else + opts[1] |= csum_cmd; + + return true; +} + +static bool rtl8125_tx_slots_avail(struct rtl8125_private *tp, + struct rtl8125_tx_ring *ring) +{ + unsigned int slots_avail = READ_ONCE(ring->dirty_tx) + NUM_TX_DESC + - READ_ONCE(ring->cur_tx); + + /* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ + return slots_avail > MAX_SKB_FRAGS; +} + +static netdev_tx_t +rtl8125_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + unsigned int entry; + struct TxDesc *txd; + dma_addr_t mapping; + u32 len; + u32 opts[2]; + netdev_tx_t ret = NETDEV_TX_OK; + int frags; + u8 EnableTxNoClose = tp->EnableTxNoClose; + const u16 queue_mapping = skb_get_queue_mapping(skb); + struct rtl8125_tx_ring *ring; + bool stop_queue; + + assert(queue_mapping < tp->num_tx_queues); + + ring = &tp->tx_ring[queue_mapping]; + + if (unlikely(!rtl8125_tx_slots_avail(tp, ring))) { + if (netif_msg_drv(tp)) { + printk(KERN_ERR + "%s: BUG! Tx Ring[%d] full when queue awake!\n", + dev->name, + queue_mapping); + } + goto err_stop; + } + + entry = ring->cur_tx % NUM_TX_DESC; + txd = ring->TxDescArray + entry; + + if (!EnableTxNoClose) { + if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) { + if (netif_msg_drv(tp)) { + printk(KERN_ERR + "%s: BUG! Tx Desc is own by hardware!\n", + dev->name); + } + goto err_stop; + } + } + + opts[0] = DescOwn; + opts[1] = rtl8125_tx_vlan_tag(tp, skb); + + if (unlikely(!rtl8125_tso_csum(skb, dev, opts))) + goto err_dma_0; + + frags = rtl8125_xmit_frags(tp, ring, skb, opts); + if (unlikely(frags < 0)) + goto err_dma_0; + if (frags) { + len = skb_headlen(skb); + opts[0] |= FirstFrag; + } else { + len = skb->len; + + //ring->tx_skb[entry].skb = skb; + + opts[0] |= FirstFrag | LastFrag; + } + + opts[0] = rtl8125_get_txd_opts1(opts[0], len, entry); + mapping = dma_map_single(tp_to_dev(tp), skb->data, len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { + if (unlikely(net_ratelimit())) + netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); + goto err_dma_1; + } + ring->tx_skb[entry].len = len; +#ifdef ENABLE_PTP_SUPPORT + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + if (tp->hwtstamp_config.tx_type == HWTSTAMP_TX_ON && + !tp->ptp_tx_skb) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + + tp->ptp_tx_skb = skb_get(skb); + tp->ptp_tx_start = jiffies; + schedule_work(&tp->ptp_tx_work); + } else { + tp->tx_hwtstamp_skipped++; + } + } +#endif + ring->tx_skb[entry].skb = skb; + txd->addr = cpu_to_le64(mapping); + txd->opts2 = cpu_to_le32(opts[1]); + wmb(); + txd->opts1 = cpu_to_le32(opts[0]); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) + dev->trans_start = jiffies; +#else + skb_tx_timestamp(skb); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) + + /* rtl_tx needs to see descriptor changes before updated tp->cur_tx */ + smp_wmb(); + + WRITE_ONCE(ring->cur_tx, ring->cur_tx + frags + 1); + + stop_queue = !rtl8125_tx_slots_avail(tp, ring); + if (unlikely(stop_queue)) { + /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must + * not miss a ring update when it notices a stopped queue. + */ + smp_wmb(); + netif_stop_subqueue(dev, queue_mapping); + } + + if (EnableTxNoClose) + RTL_W16(tp, ring->sw_tail_ptr_reg, ring->cur_tx % MAX_TX_NO_CLOSE_DESC_PTR_V2); + else + RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); /* set polling bit */ + + if (unlikely(stop_queue)) { + /* Sync with rtl_tx: + * - publish queue status and cur_tx ring index (write barrier) + * - refresh dirty_tx ring index (read barrier). + * May the current thread have a pessimistic view of the ring + * status and forget to wake up queue, a racing rtl_tx thread + * can't. + */ + smp_mb(); + if (rtl8125_tx_slots_avail(tp, ring)) + netif_start_subqueue(dev, queue_mapping); + } +out: + return ret; +err_dma_1: + ring->tx_skb[entry].skb = NULL; + rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, frags); +err_dma_0: + RTLDEV->stats.tx_dropped++; + dev_kfree_skb_any(skb); + ret = NETDEV_TX_OK; + goto out; +err_stop: + netif_stop_subqueue(dev, queue_mapping); + ret = NETDEV_TX_BUSY; + RTLDEV->stats.tx_dropped++; + goto out; +} + +static inline u32 +rtl8125_fast_mod(const u32 input, const u32 ceil) +{ + return input >= ceil ? input % ceil : input; +} + +static int +rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget) +{ + struct rtl8125_private *tp = ring->priv; + struct net_device *dev = tp->dev; + unsigned int dirty_tx, tx_left; + unsigned int count = 0; + u8 EnableTxNoClose = tp->EnableTxNoClose; + + dirty_tx = ring->dirty_tx; + smp_rmb(); + tx_left = READ_ONCE(ring->cur_tx) - dirty_tx; + if (EnableTxNoClose) { + unsigned int tx_desc_closed; + u32 NextHwDesCloPtr = RTL_R16(tp, ring->hw_clo_ptr_reg); + ring->NextHwDesCloPtr = NextHwDesCloPtr; + smp_rmb(); + tx_desc_closed = rtl8125_fast_mod(NextHwDesCloPtr - ring->BeginHwDesCloPtr, MAX_TX_NO_CLOSE_DESC_PTR_V2); + if(tx_left > tx_desc_closed) tx_left = tx_desc_closed; + ring->BeginHwDesCloPtr = NextHwDesCloPtr; + } + + while (tx_left > 0) { + unsigned int entry = dirty_tx % NUM_TX_DESC; + struct ring_info *tx_skb = ring->tx_skb + entry; + + if (!EnableTxNoClose && + (le32_to_cpu(ring->TxDescArray[entry].opts1) & DescOwn)) + break; + + RTLDEV->stats.tx_bytes += tx_skb->len; + RTLDEV->stats.tx_packets++; + + rtl8125_unmap_tx_skb(tp->pci_dev, + tx_skb, + ring->TxDescArray + entry); + + if (tx_skb->skb != NULL) { + RTL_NAPI_CONSUME_SKB_ANY(tx_skb->skb, budget); + tx_skb->skb = NULL; + } + dirty_tx++; + tx_left--; + } + + if (ring->dirty_tx != dirty_tx) { + count = dirty_tx - ring->dirty_tx; + WRITE_ONCE(ring->dirty_tx, dirty_tx); + smp_wmb(); + if (__netif_subqueue_stopped(dev, ring->index) && + (rtl8125_tx_slots_avail(tp, ring))) { + netif_start_subqueue(dev, ring->index); + } + smp_rmb(); + if (!EnableTxNoClose && (ring->cur_tx != dirty_tx)) { + RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); + } + } + + return count; +} + +static int +rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, + const int message_id, + int budget) +{ + int count = 0; + + if (message_id == 16) + count += rtl8125_tx_interrupt(&tp->tx_ring[0], budget); +#ifdef ENABLE_MULTIPLE_TX_QUEUE + else if (message_id == 18) + count += rtl8125_tx_interrupt(&tp->tx_ring[1], budget); +#endif + + return count; +} + +static inline int +rtl8125_fragmented_frame(struct rtl8125_private *tp, u32 status) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + return (status & (FirstFrag_V3 | LastFrag_V3)) != (FirstFrag_V3 | LastFrag_V3); + else + return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); +} + +static inline int +rtl8125_rx_desc_type(u32 status) +{ + return ((status >> 26) & 0x0F); +} + +static inline void +rtl8125_rx_v3_csum(struct rtl8125_private *tp, + struct sk_buff *skb, + struct RxDescV3 *descv3) +{ + //u32 opts1 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1); + u32 opts2 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts2); + + /* rx csum offload for RTL8125 */ + if (((opts2 & RxV4F_v3) && !(opts2 & RxIPF_v3)) || (opts2 & RxV6F_v3)) { + if (((opts2 & RxTCPT_v3) && !(opts2 & RxTCPF_v3)) || + ((opts2 & RxUDPT_v3) && !(opts2 & RxUDPF_v3))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + } else + skb->ip_summed = CHECKSUM_NONE; +} + +static inline void +rtl8125_rx_csum(struct rtl8125_private *tp, + struct sk_buff *skb, + struct RxDesc *desc) +{ + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) + rtl8125_rx_v3_csum(tp, skb, (struct RxDescV3 *)desc); + else { + u32 opts1 = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); + u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); + + /* rx csum offload for RTL8125 */ + if (((opts2 & RxV4F) && !(opts1 & RxIPF)) || (opts2 & RxV6F)) { + if (((opts1 & RxTCPT) && !(opts1 & RxTCPF)) || + ((opts1 & RxUDPT) && !(opts1 & RxUDPF))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + } else + skb->ip_summed = CHECKSUM_NONE; + } +} + +static inline int +rtl8125_try_rx_copy(struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + struct sk_buff **sk_buff, + int pkt_size, + struct RxDesc *desc, + int rx_buf_sz) +{ + int ret = -1; + + if (pkt_size < rx_copybreak) { + struct sk_buff *skb; + + skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, pkt_size + RTK_RX_ALIGN); + if (skb) { + u8 *data; + + data = sk_buff[0]->data; + skb_reserve(skb, RTK_RX_ALIGN); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) + prefetch(data - RTK_RX_ALIGN); +#endif + eth_copy_and_sum(skb, data, pkt_size, 0); + *sk_buff = skb; + rtl8125_mark_to_asic(tp, desc, rx_buf_sz); + ret = 0; + } + } + return ret; +} + +static inline void +rtl8125_rx_skb(struct rtl8125_private *tp, + struct sk_buff *skb, + u32 ring_index) +{ +#ifdef CONFIG_R8125_NAPI +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + netif_receive_skb(skb); +#else + napi_gro_receive(&tp->r8125napi[ring_index].napi, skb); +#endif +#else + netif_rx(skb); +#endif +} + +static int +rtl8125_check_rx_desc_error(struct net_device *dev, + struct rtl8125_private *tp, + u32 status) +{ + int ret = 0; + + if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { + if (unlikely(status & RxRES_V3)) { + if (status & (RxRWT_V3 | RxRUNT_V3)) + RTLDEV->stats.rx_length_errors++; + if (status & RxCRC_V3) + RTLDEV->stats.rx_crc_errors++; + + ret = -1; + } + } else { + if (unlikely(status & RxRES)) { + if (status & (RxRWT | RxRUNT)) + RTLDEV->stats.rx_length_errors++; + if (status & RxCRC) + RTLDEV->stats.rx_crc_errors++; + + ret = -1; + } + } + + return ret; +} + +static int +rtl8125_rx_interrupt(struct net_device *dev, + struct rtl8125_private *tp, + struct rtl8125_rx_ring *ring, + napi_budget budget) +{ + unsigned int cur_rx, rx_left; + unsigned int delta, count = 0; + unsigned int entry; + struct RxDesc *desc; + u32 status; + u32 rx_quota; + u64 rx_buf_phy_addr; + u32 ring_index = ring->index; + + assert(dev != NULL); + assert(tp != NULL); + + if ((ring->RxDescArray == NULL)) + goto rx_out; + + rx_quota = RTL_RX_QUOTA(budget); + cur_rx = ring->cur_rx; + entry = cur_rx % NUM_RX_DESC; + desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); + rx_left = NUM_RX_DESC + ring->dirty_rx - cur_rx; + rx_left = rtl8125_rx_quota(rx_left, (u32)rx_quota); + + for (; rx_left > 0; rx_left--) { + rmb(); + status = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); + if (status & DescOwn) + break; + + if (unlikely(rtl8125_check_rx_desc_error(dev, tp, status) < 0)) { + if (netif_msg_rx_err(tp)) { + printk(KERN_INFO + "%s: Rx ERROR. status = %08x\n", + dev->name, status); + } + + RTLDEV->stats.rx_errors++; + + if (dev->features & NETIF_F_RXALL) + goto process_pkt; + + rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); + } else { + struct sk_buff *skb; + int pkt_size; + +process_pkt: + if (likely(!(dev->features & NETIF_F_RXFCS))) + pkt_size = (status & 0x00003fff) - 4; + else + pkt_size = status & 0x00003fff; + + /* + * The driver does not support incoming fragmented + * frames. They are seen as a symptom of over-mtu + * sized frames. + */ + if (unlikely(rtl8125_fragmented_frame(tp, status))) { + RTLDEV->stats.rx_dropped++; + RTLDEV->stats.rx_length_errors++; + rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); + continue; + } + + skb = ring->Rx_skbuff[entry]; + + if (!skb) + break; + +#ifdef ENABLE_PTP_SUPPORT + if (tp->EnablePtp) { + u8 desc_type; + + desc_type = rtl8125_rx_desc_type(status); + if (desc_type == RXDESC_TYPE_NEXT && rx_left > 0) { + u32 status_next; + struct RxDescV3 *desc_next; + unsigned int entry_next; + struct sk_buff *skb_next; + + entry_next = (cur_rx + 1) % NUM_RX_DESC; + desc_next = (struct RxDescV3 *)rtl8125_get_rxdesc(tp, ring->RxDescArray, entry_next); + rmb(); + status_next = le32_to_cpu(desc_next->RxDescNormalDDWord4.opts1); + if (unlikely(status_next & DescOwn)) { + udelay(1); + rmb(); + status_next = le32_to_cpu(desc_next->RxDescNormalDDWord4.opts1); + if (unlikely(status_next & DescOwn)) { + if (netif_msg_rx_err(tp)) { + printk(KERN_ERR + "%s: Rx Next Desc ERROR. status = %08x\n", + dev->name, status_next); + } + break; + } + } + + cur_rx++; + rx_left--; + desc_type = rtl8125_rx_desc_type(status_next); + if (desc_type == RXDESC_TYPE_PTP) + rtl8125_rx_ptp_pktstamp(tp, skb, desc_next); + else + WARN_ON(1); + + rx_buf_phy_addr = ring->RxDescPhyAddr[entry_next]; + dma_unmap_single(tp_to_dev(tp), rx_buf_phy_addr, + tp->rx_buf_sz, DMA_FROM_DEVICE); + skb_next = ring->Rx_skbuff[entry_next]; + dev_kfree_skb_any(skb_next); + ring->Rx_skbuff[entry_next] = NULL; + } else + WARN_ON(desc_type != RXDESC_TYPE_NORMAL); + } +#endif + rx_buf_phy_addr = ring->RxDescPhyAddr[entry]; + dma_sync_single_for_cpu(tp_to_dev(tp), + rx_buf_phy_addr, tp->rx_buf_sz, + DMA_FROM_DEVICE); + + if (rtl8125_try_rx_copy(tp, ring, &skb, pkt_size, + desc, tp->rx_buf_sz)) { + ring->Rx_skbuff[entry] = NULL; + dma_unmap_single(tp_to_dev(tp), rx_buf_phy_addr, + tp->rx_buf_sz, DMA_FROM_DEVICE); + } else { + dma_sync_single_for_device(tp_to_dev(tp), rx_buf_phy_addr, + tp->rx_buf_sz, DMA_FROM_DEVICE); + } + +#ifdef ENABLE_RSS_SUPPORT + rtl8125_rx_hash(tp, (struct RxDescV3 *)desc, skb); +#endif + + if (tp->cp_cmd & RxChkSum) + rtl8125_rx_csum(tp, skb, desc); + + skb->dev = dev; + skb_put(skb, pkt_size); + skb->protocol = eth_type_trans(skb, dev); + + if (skb->pkt_type == PACKET_MULTICAST) + RTLDEV->stats.multicast++; + + if (rtl8125_rx_vlan_skb(tp, desc, skb) < 0) + rtl8125_rx_skb(tp, skb, ring_index); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) + dev->last_rx = jiffies; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) + RTLDEV->stats.rx_bytes += pkt_size; + RTLDEV->stats.rx_packets++; + } + + cur_rx++; + entry = cur_rx % NUM_RX_DESC; + desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) + prefetch(desc); +#endif + } + + count = cur_rx - ring->cur_rx; + ring->cur_rx = cur_rx; + + delta = rtl8125_rx_fill(tp, ring, dev, ring->dirty_rx, ring->cur_rx, 1); + if (!delta && count && netif_msg_intr(tp)) + printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); + ring->dirty_rx += delta; + + /* + * FIXME: until there is periodic timer to try and refill the ring, + * a temporary shortage may definitely kill the Rx process. + * - disable the asic to try and avoid an overflow and kick it again + * after refill ? + * - how do others driver handle this condition (Uh oh...). + */ + if ((ring->dirty_rx + NUM_RX_DESC == ring->cur_rx) && netif_msg_intr(tp)) + printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); + +rx_out: + return count; +} + +static bool +rtl8125_linkchg_interrupt(struct rtl8125_private *tp, u32 status) +{ + if (tp->HwCurrIsrVer == 2) + return status & ISRIMR_V2_LINKCHG; + + return status & LinkChg; +} + +/* + *The interrupt handler does all of the Rx thread work and cleans up after + *the Tx thread. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +#else +static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance) +#endif +{ + struct r8125_napi *r8125napi = dev_instance; + struct rtl8125_private *tp = r8125napi->priv; + struct net_device *dev = tp->dev; + u32 status; + int handled = 0; + + do { + status = RTL_R32(tp, tp->isr_reg[0]); + + if (!(tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) { + /* hotplug/major error/no more work/shared irq */ + if (!status) + break; + + if ((status == 0xFFFFFFFF)) + break; + + if (!(status & (tp->intr_mask | tp->timer_intr_mask))) + break; + } + + handled = 1; + +#if defined(RTL_USE_NEW_INTR_API) + if (!tp->irq_tbl[0].requested) + break; +#endif + rtl8125_disable_hw_interrupt(tp); + + RTL_W32(tp, tp->isr_reg[0], status&~RxFIFOOver); + + if (rtl8125_linkchg_interrupt(tp, status)) + rtl8125_schedule_linkchg_work(tp); + +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + if (HW_DASH_SUPPORT_TYPE_3(tp)) { + u8 DashIntType2Status; + + if (status & ISRIMR_DASH_INTR_CMAC_RESET) + tp->CmacResetIntr = TRUE; + + DashIntType2Status = RTL_CMAC_R8(tp, CMAC_IBISR0); + if (DashIntType2Status & ISRIMR_DASH_TYPE2_ROK) { + tp->RcvFwDashOkEvt = TRUE; + } + if (DashIntType2Status & ISRIMR_DASH_TYPE2_TOK) { + tp->SendFwHostOkEvt = TRUE; + } + if (DashIntType2Status & ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE) { + tp->DashFwDisableRx = TRUE; + } + + RTL_CMAC_W8(tp, CMAC_IBISR0, DashIntType2Status); + } + } +#endif + +#ifdef CONFIG_R8125_NAPI + if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { + if (status & tp->intr_mask) + tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; + + if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &tp->r8125napi[0].napi))) + __RTL_NETIF_RX_SCHEDULE(dev, &tp->r8125napi[0].napi); + else if (netif_msg_intr(tp)) + printk(KERN_INFO "%s: interrupt %04x in poll\n", + dev->name, status); + } else { + tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; + rtl8125_switch_to_hw_interrupt(tp); + } +#else + if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { + u32 budget = ~(u32)0; + int i; + + if (status & tp->intr_mask) + tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], &budget); +#else + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], budget); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + + for (i = 0; i < tp->num_tx_rings; i++) + rtl8125_tx_interrupt(&tp->tx_ring[i], ~(u32)0); +#ifdef ENABLE_DASH_SUPPORT + if (tp->DASH) { + struct net_device *dev = tp->dev; + + HandleDashInterrupt(dev); + } +#endif + + rtl8125_switch_to_timer_interrupt(tp); + } else { + tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; + rtl8125_switch_to_hw_interrupt(tp); + } +#endif + } while (false); + + return IRQ_RETVAL(handled); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs) +#else +static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance) +#endif +{ + struct r8125_napi *r8125napi = dev_instance; + struct rtl8125_private *tp = r8125napi->priv; + struct net_device *dev = tp->dev; + int message_id = r8125napi->index; +#ifndef CONFIG_R8125_NAPI + u32 budget = ~(u32)0; +#endif + + do { +#if defined(RTL_USE_NEW_INTR_API) + if (!tp->irq_tbl[message_id].requested) + break; +#endif + rtl8125_disable_hw_interrupt_v2(tp, message_id); + + rtl8125_clear_hw_isr_v2(tp, message_id); + + //link change + if (message_id == 21) { + rtl8125_schedule_linkchg_work(tp); + break; + } + +#ifdef CONFIG_R8125_NAPI + if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &r8125napi->napi))) + __RTL_NETIF_RX_SCHEDULE(dev, &r8125napi->napi); + else if (netif_msg_intr(tp)) + printk(KERN_INFO "%s: interrupt message id %d in poll_msix\n", + dev->name, message_id); +#else + if (message_id < tp->num_rx_rings) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], &budget); +#else + rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + } + + rtl8125_tx_interrupt_with_vector(tp, message_id, ~(u32)0); + + rtl8125_enable_hw_interrupt_v2(tp, message_id); +#endif + + } while (false); + + return IRQ_HANDLED; +} + +static void rtl8125_down(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + //rtl8125_delete_esd_timer(dev, &tp->esd_timer); + + //rtl8125_delete_link_timer(dev, &tp->link_timer); + + netif_tx_disable(dev); + + _rtl8125_wait_for_quiescence(dev); + + netif_carrier_off(dev); + + rtl8125_hw_reset(dev); + + rtl8125_tx_clear(tp); + + rtl8125_rx_clear(tp); +} + +static int rtl8125_resource_freed(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < tp->num_tx_rings; i++) + if (tp->tx_ring[i].TxDescArray) return 0; + + for (i = 0; i < tp->num_rx_rings; i++) + if (tp->rx_ring[i].RxDescArray) return 0; + + return 1; +} + +int rtl8125_close(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + if (!rtl8125_resource_freed(tp)) { + set_bit(R8125_FLAG_DOWN, tp->task_flags); + + rtl8125_down(dev); + + pci_clear_master(tp->pci_dev); + +#ifdef ENABLE_PTP_SUPPORT + rtl8125_ptp_stop(tp); +#endif + rtl8125_hw_d3_para(dev); + + rtl8125_powerdown_pll(dev, 0); + + rtl8125_free_irq(tp); + + rtl8125_free_alloc_resources(tp); + } else { + rtl8125_hw_d3_para(dev); + + rtl8125_powerdown_pll(dev, 0); + } + + return 0; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) +static void rtl8125_shutdown(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rtl8125_private *tp = netdev_priv(dev); + + rtnl_lock(); + + if (tp->DASH) + rtl8125_driver_stop(tp); + + rtl8125_set_bios_setting(dev); + if (s5_keep_curr_mac == 0 && tp->random_mac == 0) + rtl8125_rar_set(tp, tp->org_mac_addr); + + if (s5wol == 0) + tp->wol_enabled = WOL_DISABLED; + + rtl8125_close(dev); + rtl8125_disable_msi(pdev, tp); + + rtnl_unlock(); + + if (system_state == SYSTEM_POWER_OFF) { + pci_clear_master(tp->pci_dev); + pci_wake_from_d3(pdev, tp->wol_enabled); + pci_set_power_state(pdev, PCI_D3hot); + } +} +#endif + +/** + * rtl8125_get_stats - Get rtl8125 read/write statistics + * @dev: The Ethernet Device to get statistics for + * + * Get TX/RX statistics for rtl8125 + */ +static struct +net_device_stats *rtl8125_get_stats(struct net_device *dev) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + struct rtl8125_private *tp = netdev_priv(dev); +#endif + return &RTLDEV->stats; +} + +#ifdef CONFIG_PM + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) +static int +rtl8125_suspend(struct pci_dev *pdev, u32 state) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +static int +rtl8125_suspend(struct device *device) +#else +static int +rtl8125_suspend(struct pci_dev *pdev, pm_message_t state) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + struct pci_dev *pdev = to_pci_dev(device); + struct net_device *dev = pci_get_drvdata(pdev); +#else + struct net_device *dev = pci_get_drvdata(pdev); +#endif + struct rtl8125_private *tp = netdev_priv(dev); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + u32 pci_pm_state = pci_choose_state(pdev, state); +#endif + if (!netif_running(dev)) + goto out; + + //rtl8125_cancel_all_schedule_work(tp); + + //rtl8125_delete_esd_timer(dev, &tp->esd_timer); + + //rtl8125_delete_link_timer(dev, &tp->link_timer); + + rtnl_lock(); + + set_bit(R8125_FLAG_DOWN, tp->task_flags); + + netif_tx_disable(dev); + + netif_carrier_off(dev); + + netif_device_detach(dev); + +#ifdef ENABLE_PTP_SUPPORT + rtl8125_ptp_suspend(tp); +#endif + rtl8125_hw_reset(dev); + + pci_clear_master(pdev); + + rtl8125_hw_d3_para(dev); + + rtl8125_powerdown_pll(dev, 1); + + if (tp->DASH) + rtl8125_driver_stop(tp); + + rtnl_unlock(); +out: + + pci_disable_device(pdev); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + pci_save_state(pdev, &pci_pm_state); +#else + pci_save_state(pdev); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); +#endif + + pci_prepare_to_sleep(pdev); + + return 0; +} + +static int +rtl8125_hw_d3_not_power_off(struct net_device *dev) +{ + return rtl8125_check_hw_phy_mcu_code_ver(dev); +} + +static int rtl8125_wait_phy_nway_complete_sleep(struct rtl8125_private *tp) +{ + int i, val; + + for (i = 0; i < 30; i++) { + val = rtl8125_mdio_read(tp, MII_BMSR) & BMSR_ANEGCOMPLETE; + if (val) + return 0; + + msleep(100); + } + + return -1; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +static int +rtl8125_resume(struct pci_dev *pdev) +#else +static int +rtl8125_resume(struct device *device) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + struct pci_dev *pdev = to_pci_dev(device); + struct net_device *dev = pci_get_drvdata(pdev); +#else + struct net_device *dev = pci_get_drvdata(pdev); +#endif + struct rtl8125_private *tp = netdev_priv(dev); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + u32 pci_pm_state = PCI_D0; +#endif + u32 err; + + rtnl_lock(); + + err = pci_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "Cannot enable PCI device from suspend\n"); + goto out_unlock; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + pci_restore_state(pdev, &pci_pm_state); +#else + pci_restore_state(pdev); +#endif + pci_enable_wake(pdev, PCI_D0, 0); + + /* restore last modified mac address */ + rtl8125_rar_set(tp, dev->dev_addr); + + tp->resume_not_chg_speed = 0; + if (tp->check_keep_link_speed && + //tp->link_ok(dev) && + rtl8125_hw_d3_not_power_off(dev) && + rtl8125_wait_phy_nway_complete_sleep(tp) == 0) + tp->resume_not_chg_speed = 1; + + if (!netif_running(dev)) + goto out_unlock; + + pci_set_master(pdev); + + rtl8125_exit_oob(dev); + + rtl8125_up(dev); + + clear_bit(R8125_FLAG_DOWN, tp->task_flags); + + rtl8125_schedule_reset_work(tp); + + rtl8125_schedule_esd_work(tp); + + //mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); + //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); +out_unlock: + netif_device_attach(dev); + + rtnl_unlock(); + + return err; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + +static struct dev_pm_ops rtl8125_pm_ops = { + .suspend = rtl8125_suspend, + .resume = rtl8125_resume, + .freeze = rtl8125_suspend, + .thaw = rtl8125_resume, + .poweroff = rtl8125_suspend, + .restore = rtl8125_resume, +}; + +#define RTL8125_PM_OPS (&rtl8125_pm_ops) + +#endif + +#else /* !CONFIG_PM */ + +#define RTL8125_PM_OPS NULL + +#endif /* CONFIG_PM */ + +static struct pci_driver rtl8125_pci_driver = { + .name = MODULENAME, + .id_table = rtl8125_pci_tbl, + .probe = rtl8125_init_one, + .remove = __devexit_p(rtl8125_remove_one), +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) + .shutdown = rtl8125_shutdown, +#endif +#ifdef CONFIG_PM +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + .suspend = rtl8125_suspend, + .resume = rtl8125_resume, +#else + .driver.pm = RTL8125_PM_OPS, +#endif +#endif +}; + +static int __init +rtl8125_init_module(void) +{ + int ret = 0; +#ifdef ENABLE_R8125_PROCFS + rtl8125_proc_module_init(); +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + + ret = pci_register_driver(&rtl8125_pci_driver); +#else + ret = pci_module_init(&rtl8125_pci_driver); +#endif + + return ret; +} + +static void __exit +rtl8125_cleanup_module(void) +{ + pci_unregister_driver(&rtl8125_pci_driver); + +#ifdef ENABLE_R8125_PROCFS + if (rtl8125_proc) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + remove_proc_subtree(MODULENAME, init_net.proc_net); +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) + remove_proc_entry(MODULENAME, init_net.proc_net); +#else + remove_proc_entry(MODULENAME, proc_net); +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + rtl8125_proc = NULL; + } +#endif +} + +module_init(rtl8125_init_module); +module_exit(rtl8125_cleanup_module); diff --git a/r8125/src/r8125_ptp.c b/r8125/src/r8125_ptp.c new file mode 100755 index 000000000..e1102b76d --- /dev/null +++ b/r8125/src/r8125_ptp.c @@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "r8125.h" +#include "r8125_ptp.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) +{ + return *(const struct timespec *)&ts64; +} + +static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) +{ + return *(const struct timespec64 *)&ts; +} +#endif + +static int _rtl8125_phc_gettime(struct rtl8125_private *tp, struct timespec64 *ts64) +{ + //get local time + RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_LATCHED_LOCAL_TIME | PTP_EXEC_CMD)); + + /* nanoseconds */ + //0x6808[29:0] + ts64->tv_nsec = (RTL_R32(tp, PTP_SOFT_CONFIG_Time_NS_8125) & 0x3fffffff) + + tp->ptp_adjust; + + /* seconds */ + //0x680C[47:0] + ts64->tv_sec = RTL_R16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4); + ts64->tv_sec <<= 32; + ts64->tv_sec |= RTL_R32(tp, PTP_SOFT_CONFIG_Time_S_8125); + + return 0; +} + +static int _rtl8125_phc_settime(struct rtl8125_private *tp, const struct timespec64 *ts64) +{ + /* nanoseconds */ + //0x6808[29:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, (ts64->tv_nsec & 0x3fffffff)); + + /* seconds */ + //0x680C[47:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, ts64->tv_sec); + RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (ts64->tv_sec >> 32)); + + //set local time + RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); + + return 0; +} + +#if 0 +static int _rtl8125_phc_adjtime(struct rtl8125_private *tp, s64 delta) +{ + struct timespec64 now, then = ns_to_timespec64(delta); + u32 nsec; + u64 sec; + + _rtl8125_phc_gettime(tp, &now); + now = timespec64_add(now, then); + + nsec = now.tv_nsec & 0x3fffffff; + sec = now.tv_sec & 0x0000ffffffffffff; + + /* nanoseconds */ + //0x6808[29:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, nsec); + + /* seconds */ + //0x680C[47:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, sec); + RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (sec >> 32)); + + //adjust local time + //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); + RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); + + return 0; +} +#endif + +static int rtl8125_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + unsigned long flags; + //int ret = 0; + + //netif_info(tp, drv, tp->dev, "phc adjust time\n"); + + spin_lock_irqsave(&tp->lock, flags); + //ret = _rtl8125_phc_adjtime(tp, delta); + tp->ptp_adjust += delta; + spin_unlock_irqrestore(&tp->lock, flags); + + return 0; +} + +/* +1ppm means every 125MHz plus 125Hz. It also means every 8ns minus 8ns*10^(-6) + +1ns=2^30 sub_ns + +8ns*10^(-6) = 8 * 2^30 sub_ns * 10^(-6) = 2^33 sub_ns * 10^(-6) = 8590 = 0x218E sub_ns + +1ppb means every 125MHz plus 0.125Hz. It also means every 8ns minus 8ns*10^(-9) + +1ns=2^30 sub_ns + +8ns*10^(-9) = 8 * 2^30 sub_ns * 10^(-9) = 2^33 sub_ns * 10^(-9) = 8.59 sub_ns = 9 sub_ns +*/ +static int _rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + bool negative = false; + u32 sub_ns; + + if (ppb < 0) { + negative = true; + ppb = -ppb; + } + + sub_ns = ppb * 9; + if (negative) { + sub_ns = -sub_ns; + sub_ns &= 0x3fffffff; + sub_ns |= PTP_ADJUST_TIME_NS_NEGATIVE; + } else + sub_ns &= 0x3fffffff; + + /* nanoseconds */ + //0x6808[29:0] + RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, sub_ns); + + //adjust local time + RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); + //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); + + return 0; +} + +static int rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) +{ + //struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + + //netif_info(tp, drv, tp->dev, "phc adjust freq\n"); + + if (delta > ptp->max_adj || delta < -ptp->max_adj) + return -EINVAL; + + _rtl8125_phc_adjfreq(ptp, delta); + + return 0; +} + +static int rtl8125_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + unsigned long flags; + int ret; + + //netif_info(tp, drv, tp->dev, "phc get ts\n"); + + spin_lock_irqsave(&tp->lock, flags); + ret = _rtl8125_phc_gettime(tp, ts64); + spin_unlock_irqrestore(&tp->lock, flags); + + return ret; +} + +static int rtl8125_phc_settime(struct ptp_clock_info *ptp, + const struct timespec64 *ts64) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + unsigned long flags; + int ret; + + //netif_info(tp, drv, tp->dev, "phc set ts\n"); + + spin_lock_irqsave(&tp->lock, flags); + ret = _rtl8125_phc_settime(tp, ts64); + tp->ptp_adjust = 0; + spin_unlock_irqrestore(&tp->lock, flags); + + return ret; +} + +static int rtl8125_phc_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); + unsigned long flags; + u16 ptp_ctrl; + + //netif_info(tp, drv, tp->dev, "phc enable type %x on %d\n", rq->type, on); + + switch (rq->type) { + case PTP_CLK_REQ_PPS: + spin_lock_irqsave(&tp->lock, flags); + ptp_ctrl = RTL_R16(tp, PTP_CTRL_8125); + ptp_ctrl &= ~BIT_15; + if (on) + ptp_ctrl |= BIT_14; + else + ptp_ctrl &= ~BIT_14; + RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); + spin_unlock_irqrestore(&tp->lock, flags); + return 0; + default: + return -EOPNOTSUPP; + } +} + +int rtl8125_get_ts_info(struct net_device *netdev, + struct ethtool_ts_info *info) +{ + struct rtl8125_private *tp = netdev_priv(netdev); + + /* we always support timestamping disabled */ + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); + + if (tp->HwSuppPtpVer == 0) + return ethtool_op_get_ts_info(netdev, info); + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + if (tp->ptp_clock) + info->phc_index = ptp_clock_index(tp->ptp_clock); + else + info->phc_index = -1; + + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); + + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | + BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); + + return 0; +} + +static const struct ptp_clock_info rtl_ptp_clock_info = { + .owner = THIS_MODULE, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 0, + .n_pins = 0, + .pps = 1, + .adjfreq = rtl8125_phc_adjfreq, + .adjtime = rtl8125_phc_adjtime, + .gettime64 = rtl8125_phc_gettime, + .settime64 = rtl8125_phc_settime, + .enable = rtl8125_phc_enable, +}; + +static int rtl8125_get_tx_ptp_pkt_tstamp(struct rtl8125_private *tp, struct timespec64 *ts64) +{ + return _rtl8125_phc_gettime(tp, ts64); +} + +static void rtl8125_ptp_tx_hwtstamp(struct rtl8125_private *tp) +{ + struct sk_buff *skb = tp->ptp_tx_skb; + struct skb_shared_hwtstamps shhwtstamps = {0}; + struct timespec64 ts64; + + RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); + + rtl8125_get_tx_ptp_pkt_tstamp(tp, &ts64); + + /* Upper 32 bits contain s, lower 32 bits contain ns. */ + shhwtstamps.hwtstamp = ktime_set(ts64.tv_sec, + ts64.tv_nsec); + + /* Clear the lock early before calling skb_tstamp_tx so that + * applications are not woken up before the lock bit is clear. We use + * a copy of the skb pointer to ensure other threads can't change it + * while we're notifying the stack. + */ + tp->ptp_tx_skb = NULL; + + /* Notify the stack and free the skb after we've unlocked */ + skb_tstamp_tx(skb, &shhwtstamps); + dev_kfree_skb_any(skb); +} + +#define RTL8125_PTP_TX_TIMEOUT (HZ * 15) +static void rtl8125_ptp_tx_work(struct work_struct *work) +{ + struct rtl8125_private *tp = container_of(work, struct rtl8125_private, + ptp_tx_work); + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + + if (!tp->ptp_tx_skb) + goto Exit; + + if (time_is_before_jiffies(tp->ptp_tx_start + + RTL8125_PTP_TX_TIMEOUT)) { + dev_kfree_skb_any(tp->ptp_tx_skb); + tp->ptp_tx_skb = NULL; + tp->tx_hwtstamp_timeouts++; + /* Clear the tx valid bit in TSYNCTXCTL register to enable + * interrupt + */ + RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); + goto Exit; + } + + if (RTL_R8(tp, PTP_ISR_8125) & (PTP_ISR_TOK)) + rtl8125_ptp_tx_hwtstamp(tp); + else + /* reschedule to check later */ + schedule_work(&tp->ptp_tx_work); + +Exit: + spin_unlock_irqrestore(&tp->lock, flags); +} + +static int rtl8125_hwtstamp_enable(struct rtl8125_private *tp, bool enable) +{ + RTL_W16(tp, PTP_CTRL_8125, 0); + if (enable) { + u16 ptp_ctrl; + struct timespec64 ts64; + + //clear ptp isr + RTL_W8(tp, PTP_ISR_8125, 0xff); + //ptp source 0:gphy 1:mac + rtl8125_mac_ocp_write(tp, 0xDC00, rtl8125_mac_ocp_read(tp, 0xDC00) | BIT_6); + //enable ptp + ptp_ctrl = (BIT_0 | BIT_3 | BIT_4 | BIT_6 | BIT_10 | BIT_12 | BIT_13); + if (tp->ptp_master_mode) { + ptp_ctrl &= ~BIT_13; + ptp_ctrl |= BIT_1; + } + RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); + + //set system time + /* + if (ktime_to_timespec64_cond(ktime_get_real(), &ts64)) + _rtl8125_phc_settime(tp, timespec64_to_timespec(ts64)); + */ + ktime_get_real_ts64(&ts64); + ts64.tv_nsec += tp->ptp_adjust; + _rtl8125_phc_settime(tp, &ts64); + tp->ptp_adjust = 0; + } + + return 0; +} + +static long rtl8125_ptp_create_clock(struct rtl8125_private *tp) +{ + struct net_device *netdev = tp->dev; + long err; + + if (!IS_ERR_OR_NULL(tp->ptp_clock)) + return 0; + + if (tp->HwSuppPtpVer == 0) { + tp->ptp_clock = NULL; + return -EOPNOTSUPP; + } + + tp->ptp_clock_info = rtl_ptp_clock_info; + snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name), + "%pm", tp->dev->dev_addr); + tp->ptp_clock_info.max_adj = 119304647; + tp->ptp_clock = ptp_clock_register(&tp->ptp_clock_info, &tp->pci_dev->dev); + if (IS_ERR(tp->ptp_clock)) { + err = PTR_ERR(tp->ptp_clock); + tp->ptp_clock = NULL; + netif_err(tp, drv, tp->dev, "ptp_clock_register failed\n"); + return err; + } else + netif_info(tp, drv, tp->dev, "registered PHC device on %s\n", netdev->name); + + return 0; +} + +void rtl8125_ptp_reset(struct rtl8125_private *tp) +{ + if (!tp->ptp_clock) + return; + + netif_info(tp, drv, tp->dev, "reset PHC clock\n"); + + rtl8125_hwtstamp_enable(tp, false); +} + +void rtl8125_ptp_init(struct rtl8125_private *tp) +{ + /* obtain a PTP device, or re-use an existing device */ + if (rtl8125_ptp_create_clock(tp)) + return; + + /* we have a clock so we can initialize work now */ + INIT_WORK(&tp->ptp_tx_work, rtl8125_ptp_tx_work); + + tp->ptp_adjust = 0; + + /* reset the PTP related hardware bits */ + rtl8125_ptp_reset(tp); + + return; +} + +void rtl8125_ptp_suspend(struct rtl8125_private *tp) +{ + if (!tp->ptp_clock) + return; + + netif_info(tp, drv, tp->dev, "suspend PHC clock\n"); + + rtl8125_hwtstamp_enable(tp, false); + + /* ensure that we cancel any pending PTP Tx work item in progress */ + cancel_work_sync(&tp->ptp_tx_work); +} + +void rtl8125_ptp_stop(struct rtl8125_private *tp) +{ + struct net_device *netdev = tp->dev; + + netif_info(tp, drv, tp->dev, "stop PHC clock\n"); + + /* first, suspend PTP activity */ + rtl8125_ptp_suspend(tp); + + /* disable the PTP clock device */ + if (tp->ptp_clock) { + ptp_clock_unregister(tp->ptp_clock); + tp->ptp_clock = NULL; + netif_info(tp, drv, tp->dev, "removed PHC on %s\n", + netdev->name); + } +} + +static int rtl8125_set_tstamp(struct net_device *netdev, struct ifreq *ifr) +{ + struct rtl8125_private *tp = netdev_priv(netdev); + struct hwtstamp_config config; + bool hwtstamp = 0; + + //netif_info(tp, drv, tp->dev, "ptp set ts\n"); + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + return -EFAULT; + + if (config.flags) + return -EINVAL; + + switch (config.tx_type) { + case HWTSTAMP_TX_ON: + hwtstamp = 1; + case HWTSTAMP_TX_OFF: + break; + case HWTSTAMP_TX_ONESTEP_SYNC: + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; + hwtstamp = 1; + case HWTSTAMP_FILTER_NONE: + break; + default: + return -ERANGE; + } + + if (tp->hwtstamp_config.tx_type != config.tx_type || + tp->hwtstamp_config.rx_filter != config.rx_filter) { + tp->hwtstamp_config = config; + rtl8125_hwtstamp_enable(tp, hwtstamp); + } + + return copy_to_user(ifr->ifr_data, &config, + sizeof(config)) ? -EFAULT : 0; +} + +static int rtl8125_get_tstamp(struct net_device *netdev, struct ifreq *ifr) +{ + struct rtl8125_private *tp = netdev_priv(netdev); + + //netif_info(tp, drv, tp->dev, "ptp get ts\n"); + + return copy_to_user(ifr->ifr_data, &tp->hwtstamp_config, + sizeof(tp->hwtstamp_config)) ? -EFAULT : 0; +} + +int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct rtl8125_private *tp = netdev_priv(netdev); + int ret; + unsigned long flags; + + //netif_info(tp, drv, tp->dev, "ptp ioctl\n"); + + ret = 0; + switch (cmd) { +#ifdef ENABLE_PTP_SUPPORT + case SIOCSHWTSTAMP: + spin_lock_irqsave(&tp->lock, flags); + ret = rtl8125_set_tstamp(netdev, ifr); + spin_unlock_irqrestore(&tp->lock, flags); + break; + case SIOCGHWTSTAMP: + spin_lock_irqsave(&tp->lock, flags); + ret = rtl8125_get_tstamp(netdev, ifr); + spin_unlock_irqrestore(&tp->lock, flags); + break; +#endif + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, + struct RxDescV3 *descv3) +{ + time64_t tv_sec; + long tv_nsec; + + tv_sec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampHigh) + + ((u64)le32_to_cpu(descv3->RxDescPTPDDWord4.TimeStampHHigh) << 32); + tv_nsec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampLow) + tp->ptp_adjust; + + skb_hwtstamps(skb)->hwtstamp = ktime_set(tv_sec, tv_nsec); +} diff --git a/r8125/src/r8125_ptp.h b/r8125/src/r8125_ptp.h new file mode 100755 index 000000000..a324ff382 --- /dev/null +++ b/r8125/src/r8125_ptp.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_rtl8125_PTP_H +#define _LINUX_rtl8125_PTP_H + +#include +#include +#include +#include +#include + +struct rtl8125_ptp_info { + s64 time_sec; + u32 time_ns; + u16 ts_info; +}; + +#ifndef _STRUCT_TIMESPEC +#define _STRUCT_TIMESPEC +struct timespec { + __kernel_old_time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; +#endif + +enum PTP_CMD_TYPE { + PTP_CMD_SET_LOCAL_TIME = 0, + PTP_CMD_DRIFT_LOCAL_TIME, + PTP_CMD_LATCHED_LOCAL_TIME, +}; + + +struct rtl8125_private; +struct RxDescV3; + +int rtl8125_get_ts_info(struct net_device *netdev, + struct ethtool_ts_info *info); + +void rtl8125_ptp_reset(struct rtl8125_private *tp); +void rtl8125_ptp_init(struct rtl8125_private *tp); +void rtl8125_ptp_suspend(struct rtl8125_private *tp); +void rtl8125_ptp_stop(struct rtl8125_private *tp); + +int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); + +void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, + struct RxDescV3 *descv3); + +#endif /* _LINUX_rtl8125_PTP_H */ diff --git a/r8125/src/r8125_realwow.h b/r8125/src/r8125_realwow.h new file mode 100755 index 000000000..352e3270f --- /dev/null +++ b/r8125/src/r8125_realwow.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_R8125_REALWOW_H +#define _LINUX_R8125_REALWOW_H + +#define SIOCDEVPRIVATE_RTLREALWOW SIOCDEVPRIVATE+3 + +#define MAX_RealWoW_KCP_SIZE (100) +#define MAX_RealWoW_Payload (64) + +#define KA_TX_PACKET_SIZE (100) +#define KA_WAKEUP_PATTERN_SIZE (120) + +//HwSuppKeepAliveOffloadVer +#define HW_SUPPORT_KCP_OFFLOAD(_M) ((_M)->HwSuppKCPOffloadVer > 0) + +enum rtl_realwow_cmd { + + RTL_REALWOW_SET_KCP_DISABLE=0, + RTL_REALWOW_SET_KCP_INFO, + RTL_REALWOW_SET_KCP_CONTENT, + + RTL_REALWOW_SET_KCP_ACKPKTINFO, + RTL_REALWOW_SET_KCP_WPINFO, + RTL_REALWOW_SET_KCPDHCP_TIMEOUT, + + RTLT_REALWOW_COMMAND_INVALID +}; + +struct rtl_realwow_ioctl_struct { + __u32 cmd; + __u32 offset; + __u32 len; + union { + __u32 data; + void *data_buffer; + }; +}; + +typedef struct _MP_KCPInfo { + u8 DIPv4[4]; + u8 MacID[6]; + u16 UdpPort[2]; + u8 PKTLEN[2]; + + u16 ackLostCnt; + u8 KCP_WakePattern[MAX_RealWoW_Payload]; + u8 KCP_AckPacket[MAX_RealWoW_Payload]; + u32 KCP_interval; + u8 KCP_WakePattern_Len; + u8 KCP_AckPacket_Len; + u8 KCP_TxPacket[2][KA_TX_PACKET_SIZE]; +} MP_KCP_INFO, *PMP_KCP_INFO; + +typedef struct _KCPInfo { + u32 nId; // = id + u8 DIPv4[4]; + u8 MacID[6]; + u16 UdpPort; + u16 PKTLEN; +} KCPInfo, *PKCPInfo; + +typedef struct _KCPContent { + u32 id; // = id + u32 mSec; // = msec + u32 size; // =size + u8 bPacket[MAX_RealWoW_KCP_SIZE]; // put packet here +} KCPContent, *PKCPContent; + +typedef struct _RealWoWAckPktInfo { + u16 ackLostCnt; + u16 patterntSize; + u8 pattern[MAX_RealWoW_Payload]; +} RealWoWAckPktInfo,*PRealWoWAckPktInfo; + +typedef struct _RealWoWWPInfo { + u16 patterntSize; + u8 pattern[MAX_RealWoW_Payload]; +} RealWoWWPInfo,*PRealWoWWPInfo; + +int rtl8125_realwow_ioctl(struct net_device *dev, struct ifreq *ifr); +void rtl8125_realwow_hw_init(struct net_device *dev); +void rtl8125_get_realwow_hw_version(struct net_device *dev); +void rtl8125_set_realwow_d3_para(struct net_device *dev); + +#endif /* _LINUX_R8125_REALWOW_H */ diff --git a/r8125/src/r8125_rss.c b/r8125/src/r8125_rss.c new file mode 100755 index 000000000..78e53f514 --- /dev/null +++ b/r8125/src/r8125_rss.c @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8168 is the Linux device driver released for Realtek Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include "r8125.h" + +enum rtl8125_rss_register_content { + /* RSS */ + RSS_CTRL_TCP_IPV4_SUPP = (1 << 0), + RSS_CTRL_IPV4_SUPP = (1 << 1), + RSS_CTRL_TCP_IPV6_SUPP = (1 << 2), + RSS_CTRL_IPV6_SUPP = (1 << 3), + RSS_HALF_SUPP = (1 << 7), + RSS_CTRL_UDP_IPV4_SUPP = (1 << 11), + RSS_CTRL_UDP_IPV6_SUPP = (1 << 12), + RSS_QUAD_CPU_EN = (1 << 16), + RSS_HQ_Q_SUP_R = (1 << 31), +}; + +static int rtl8125_get_rss_hash_opts(struct rtl8125_private *tp, + struct ethtool_rxnfc *cmd) +{ + cmd->data = 0; + + /* Report default options for RSS */ + switch (cmd->flow_type) { + case TCP_V4_FLOW: + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fallthrough */ + case UDP_V4_FLOW: + if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fallthrough */ + case IPV4_FLOW: + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + break; + case TCP_V6_FLOW: + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fallthrough */ + case UDP_V6_FLOW: + if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fallthrough */ + case IPV6_FLOW: + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + break; + default: + return -EINVAL; + } + + return 0; +} + +int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret = -EOPNOTSUPP; + + netif_info(tp, drv, tp->dev, "rss get rxnfc\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return ret; + + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data = rtl8125_tot_rx_rings(tp); + ret = 0; + break; + case ETHTOOL_GRXFH: + ret = rtl8125_get_rss_hash_opts(tp, cmd); + break; + default: + break; + } + + return ret; +} + +u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp) +{ + return tp->HwSuppIndirTblEntries; +} + +#define RSS_MASK_BITS_OFFSET (8) +#define RSS_CPU_NUM_OFFSET (16) +#define RTL8125_UDP_RSS_FLAGS (RTL_8125_RSS_FLAG_HASH_UDP_IPV4 | \ + RTL_8125_RSS_FLAG_HASH_UDP_IPV6) +static int _rtl8125_set_rss_hash_opt(struct rtl8125_private *tp) +{ + u32 rss_flags = tp->rss_flags; + u32 hash_mask_len; + u32 rss_ctrl; + + rss_ctrl = ilog2(rtl8125_tot_rx_rings(tp)); + rss_ctrl &= (BIT_0 | BIT_1 | BIT_2); + rss_ctrl <<= RSS_CPU_NUM_OFFSET; + + /* Perform hash on these packet types */ + rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP + | RSS_CTRL_IPV4_SUPP + | RSS_CTRL_IPV6_SUPP + | RSS_CTRL_TCP_IPV6_SUPP; + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) + rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) + rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; + + hash_mask_len = ilog2(rtl8125_rss_indir_tbl_entries(tp)); + hash_mask_len &= (BIT_0 | BIT_1 | BIT_2); + rss_ctrl |= hash_mask_len << RSS_MASK_BITS_OFFSET; + + RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); + + return 0; +} + +static int rtl8125_set_rss_hash_opt(struct rtl8125_private *tp, + struct ethtool_rxnfc *nfc) +{ + u32 rss_flags = tp->rss_flags; + + netif_info(tp, drv, tp->dev, "rss set hash\n"); + + /* + * RSS does not support anything other than hashing + * to queues on src and dst IPs and ports + */ + if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) + return -EINVAL; + + switch (nfc->flow_type) { + case TCP_V4_FLOW: + case TCP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST) || + !(nfc->data & RXH_L4_B_0_1) || + !(nfc->data & RXH_L4_B_2_3)) + return -EINVAL; + break; + case UDP_V4_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST)) + return -EINVAL; + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV4; + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV4; + break; + default: + return -EINVAL; + } + break; + case UDP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST)) + return -EINVAL; + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV6; + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV6; + break; + default: + return -EINVAL; + } + break; + case SCTP_V4_FLOW: + case AH_ESP_V4_FLOW: + case AH_V4_FLOW: + case ESP_V4_FLOW: + case SCTP_V6_FLOW: + case AH_ESP_V6_FLOW: + case AH_V6_FLOW: + case ESP_V6_FLOW: + case IP_USER_FLOW: + case ETHER_FLOW: + /* RSS is not supported for these protocols */ + if (nfc->data) { + netif_err(tp, drv, tp->dev, "Command parameters not supported\n"); + return -EINVAL; + } + return 0; + break; + default: + return -EINVAL; + } + + /* if we changed something we need to update flags */ + if (rss_flags != tp->rss_flags) { + u32 rss_ctrl = RTL_R32(tp, RSS_CTRL_8125); + + if ((rss_flags & RTL8125_UDP_RSS_FLAGS) && + !(tp->rss_flags & RTL8125_UDP_RSS_FLAGS)) + netdev_warn(tp->dev, + "enabling UDP RSS: fragmented packets may " + "arrive out of order to the stack above\n"); + + tp->rss_flags = rss_flags; + + /* Perform hash on these packet types */ + rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP + | RSS_CTRL_IPV4_SUPP + | RSS_CTRL_IPV6_SUPP + | RSS_CTRL_TCP_IPV6_SUPP; + + rss_ctrl &= ~(RSS_CTRL_UDP_IPV4_SUPP | + RSS_CTRL_UDP_IPV6_SUPP); + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) + rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) + rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; + + RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); + } + + return 0; +} + +int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int ret = -EOPNOTSUPP; + + netif_info(tp, drv, tp->dev, "rss set rxnfc\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return ret; + + switch (cmd->cmd) { + case ETHTOOL_SRXFH: + ret = rtl8125_set_rss_hash_opt(tp, cmd); + break; + default: + break; + } + + return ret; +} + +static u32 _rtl8125_get_rxfh_key_size(struct rtl8125_private *tp) +{ + return sizeof(tp->rss_key); +} + +u32 rtl8125_get_rxfh_key_size(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + netif_info(tp, drv, tp->dev, "rss get key size\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return 0; + + return _rtl8125_get_rxfh_key_size(tp); +} + +u32 rtl8125_rss_indir_size(struct net_device *dev) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + netif_info(tp, drv, tp->dev, "rss get indir tbl size\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return 0; + + return rtl8125_rss_indir_tbl_entries(tp); +} + +static void rtl8125_get_reta(struct rtl8125_private *tp, u32 *indir) +{ + int i, reta_size = rtl8125_rss_indir_tbl_entries(tp); + + for (i = 0; i < reta_size; i++) + indir[i] = tp->rss_indir_tbl[i]; +} + +int rtl8125_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, + u8 *hfunc) +{ + struct rtl8125_private *tp = netdev_priv(dev); + + netif_info(tp, drv, tp->dev, "rss get rxfh\n"); + + if (!(dev->features & NETIF_F_RXHASH)) + return -EOPNOTSUPP; + + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + + if (indir) + rtl8125_get_reta(tp, indir); + + if (key) + memcpy(key, tp->rss_key, rtl8125_get_rxfh_key_size(dev)); + + return 0; +} + +static u32 rtl8125_rss_key_reg(struct rtl8125_private *tp) +{ + return RSS_KEY_8125; +} + +static u32 rtl8125_rss_indir_tbl_reg(struct rtl8125_private *tp) +{ + return RSS_INDIRECTION_TBL_8125_V2; +} + +static void rtl8125_store_reta(struct rtl8125_private *tp) +{ + u16 indir_tbl_reg = rtl8125_rss_indir_tbl_reg(tp); + u32 i, reta_entries = rtl8125_rss_indir_tbl_entries(tp); + u32 reta = 0; + u8 *indir_tbl = tp->rss_indir_tbl; + + /* Write redirection table to HW */ + for (i = 0; i < reta_entries; i++) { + reta |= indir_tbl[i] << (i & 0x3) * 8; + if ((i & 3) == 3) { + RTL_W32(tp, indir_tbl_reg, reta); + + indir_tbl_reg += 4; + reta = 0; + } + } +} + +static void rtl8125_store_rss_key(struct rtl8125_private *tp) +{ + const u16 rss_key_reg = rtl8125_rss_key_reg(tp); + u32 i, rss_key_size = _rtl8125_get_rxfh_key_size(tp); + u32 *rss_key = (u32*)tp->rss_key; + + /* Write redirection table to HW */ + for (i = 0; i < rss_key_size; i+=4) + RTL_W32(tp, rss_key_reg + i, *rss_key++); +} + +int rtl8125_set_rxfh(struct net_device *dev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct rtl8125_private *tp = netdev_priv(dev); + int i; + u32 reta_entries = rtl8125_rss_indir_tbl_entries(tp); + + netif_info(tp, drv, tp->dev, "rss set rxfh\n"); + + /* We require at least one supported parameter to be changed and no + * change in any of the unsupported parameters + */ + if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + + /* Fill out the redirection table */ + if (indir) { + int max_queues = tp->num_rx_rings; + + /* Verify user input. */ + for (i = 0; i < reta_entries; i++) + if (indir[i] >= max_queues) + return -EINVAL; + + for (i = 0; i < reta_entries; i++) + tp->rss_indir_tbl[i] = indir[i]; + } + + /* Fill out the rss hash key */ + if (key) + memcpy(tp->rss_key, key, rtl8125_get_rxfh_key_size(dev)); + + rtl8125_store_reta(tp); + + rtl8125_store_rss_key(tp); + + return 0; +} + +static u32 rtl8125_get_rx_desc_hash(struct rtl8125_private *tp, + struct RxDescV3 *descv3) +{ + return le32_to_cpu(descv3->RxDescNormalDDWord2.RSSResult); +} + +#define RXS_8125B_RSS_UDP BIT(9) +#define RXS_8125_RSS_IPV4 BIT(10) +#define RXS_8125_RSS_IPV6 BIT(12) +#define RXS_8125_RSS_TCP BIT(13) +#define RTL8125_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6) +#define RTL8125_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP) +void rtl8125_rx_hash(struct rtl8125_private *tp, + struct RxDescV3 *descv3, + struct sk_buff *skb) +{ + u16 rss_header_info; + + if (!(tp->dev->features & NETIF_F_RXHASH)) + return; + + rss_header_info = le16_to_cpu(descv3->RxDescNormalDDWord2.HeaderInfo); + + if (!(rss_header_info & RTL8125_RXS_RSS_L3_TYPE_MASK)) + return; + + skb_set_hash(skb, rtl8125_get_rx_desc_hash(tp, descv3), + (RTL8125_RXS_RSS_L4_TYPE_MASK & rss_header_info) ? + PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); +} + +void rtl8125_disable_rss(struct rtl8125_private *tp) +{ + RTL_W32(tp, RSS_CTRL_8125, 0x00); +} + +void _rtl8125_config_rss(struct rtl8125_private *tp) +{ + _rtl8125_set_rss_hash_opt(tp); + + rtl8125_store_reta(tp); + + rtl8125_store_rss_key(tp); +} + +void rtl8125_config_rss(struct rtl8125_private *tp) +{ + if (!tp->EnableRss) { + rtl8125_disable_rss(tp); + return; + } + + _rtl8125_config_rss(tp); +} + +void rtl8125_init_rss(struct rtl8125_private *tp) +{ + int i; + + for (i = 0; i < rtl8125_rss_indir_tbl_entries(tp); i++) + tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings); + + netdev_rss_key_fill(tp->rss_key, RTL8125_RSS_KEY_SIZE); +} diff --git a/r8125/src/r8125_rss.h b/r8125/src/r8125_rss.h new file mode 100755 index 000000000..90e280902 --- /dev/null +++ b/r8125/src/r8125_rss.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_rtl8125_RSS_H +#define _LINUX_rtl8125_RSS_H + +#include +#include + +#define RTL8125_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */ +#define RTL8125_MAX_INDIRECTION_TABLE_ENTRIES 128 + +enum rtl8125_rss_flag { + RTL_8125_RSS_FLAG_HASH_UDP_IPV4 = (1 << 0), + RTL_8125_RSS_FLAG_HASH_UDP_IPV6 = (1 << 1), +}; + +struct rtl8125_private; + +int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs); +int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); +u32 rtl8125_get_rxfh_key_size(struct net_device *netdev); +u32 rtl8125_rss_indir_size(struct net_device *netdev); +int rtl8125_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, + u8 *hfunc); +int rtl8125_set_rxfh(struct net_device *netdev, const u32 *indir, + const u8 *key, const u8 hfunc); +void rtl8125_rx_hash(struct rtl8125_private *tp, + struct RxDescV3 *descv3, + struct sk_buff *skb); +void _rtl8125_config_rss(struct rtl8125_private *tp); +void rtl8125_config_rss(struct rtl8125_private *tp); +void rtl8125_init_rss(struct rtl8125_private *tp); +u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp); +void rtl8125_disable_rss(struct rtl8125_private *tp); + +#endif /* _LINUX_rtl8125_RSS_H */ diff --git a/r8125/src/rtl_eeprom.c b/r8125/src/rtl_eeprom.c new file mode 100755 index 000000000..866ae5f33 --- /dev/null +++ b/r8125/src/rtl_eeprom.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "r8125.h" +#include "rtl_eeprom.h" + +//------------------------------------------------------------------- +//rtl8125_eeprom_type(): +// tell the eeprom type +//return value: +// 0: the eeprom type is 93C46 +// 1: the eeprom type is 93C56 or 93C66 +//------------------------------------------------------------------- +void rtl8125_eeprom_type(struct rtl8125_private *tp) +{ + u16 magic = 0; + + if (tp->mcfg == CFG_METHOD_DEFAULT) + goto out_no_eeprom; + + if(RTL_R8(tp, 0xD2)&0x04) { + //not support + //tp->eeprom_type = EEPROM_TWSI; + //tp->eeprom_len = 256; + goto out_no_eeprom; + } else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) { + tp->eeprom_type = EEPROM_TYPE_93C56; + tp->eeprom_len = 256; + } else { + tp->eeprom_type = EEPROM_TYPE_93C46; + tp->eeprom_len = 128; + } + + magic = rtl8125_eeprom_read_sc(tp, 0); + +out_no_eeprom: + if ((magic != 0x8129) && (magic != 0x8128)) { + tp->eeprom_type = EEPROM_TYPE_NONE; + tp->eeprom_len = 0; + } +} + +void rtl8125_eeprom_cleanup(struct rtl8125_private *tp) +{ + u8 x; + + x = RTL_R8(tp, Cfg9346); + x &= ~(Cfg9346_EEDI | Cfg9346_EECS); + + RTL_W8(tp, Cfg9346, x); + + rtl8125_raise_clock(tp, &x); + rtl8125_lower_clock(tp, &x); +} + +int rtl8125_eeprom_cmd_done(struct rtl8125_private *tp) +{ + u8 x; + int i; + + rtl8125_stand_by(tp); + + for (i = 0; i < 50000; i++) { + x = RTL_R8(tp, Cfg9346); + + if (x & Cfg9346_EEDO) { + udelay(RTL_CLOCK_RATE * 2 * 3); + return 0; + } + udelay(1); + } + + return -1; +} + +//------------------------------------------------------------------- +//rtl8125_eeprom_read_sc(): +// read one word from eeprom +//------------------------------------------------------------------- +u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg) +{ + int addr_sz = 6; + u8 x; + u16 data; + + if(tp->eeprom_type == EEPROM_TYPE_NONE) { + return -1; + } + + if (tp->eeprom_type==EEPROM_TYPE_93C46) + addr_sz = 6; + else if (tp->eeprom_type==EEPROM_TYPE_93C56) + addr_sz = 8; + + x = Cfg9346_EEM1 | Cfg9346_EECS; + RTL_W8(tp, Cfg9346, x); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3); + rtl8125_shift_out_bits(tp, reg, addr_sz); + + data = rtl8125_shift_in_bits(tp); + + rtl8125_eeprom_cleanup(tp); + + RTL_W8(tp, Cfg9346, 0); + + return data; +} + +//------------------------------------------------------------------- +//rtl8125_eeprom_write_sc(): +// write one word to a specific address in the eeprom +//------------------------------------------------------------------- +void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data) +{ + u8 x; + int addr_sz = 6; + int w_dummy_addr = 4; + + if(tp->eeprom_type == EEPROM_TYPE_NONE) { + return ; + } + + if (tp->eeprom_type==EEPROM_TYPE_93C46) { + addr_sz = 6; + w_dummy_addr = 4; + } else if (tp->eeprom_type==EEPROM_TYPE_93C56) { + addr_sz = 8; + w_dummy_addr = 6; + } + + x = Cfg9346_EEM1 | Cfg9346_EECS; + RTL_W8(tp, Cfg9346, x); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5); + rtl8125_shift_out_bits(tp, reg, w_dummy_addr); + rtl8125_stand_by(tp); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3); + rtl8125_shift_out_bits(tp, reg, addr_sz); + if (rtl8125_eeprom_cmd_done(tp) < 0) { + return; + } + rtl8125_stand_by(tp); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3); + rtl8125_shift_out_bits(tp, reg, addr_sz); + rtl8125_shift_out_bits(tp, data, 16); + if (rtl8125_eeprom_cmd_done(tp) < 0) { + return; + } + rtl8125_stand_by(tp); + + rtl8125_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5); + rtl8125_shift_out_bits(tp, reg, w_dummy_addr); + + rtl8125_eeprom_cleanup(tp); + RTL_W8(tp, Cfg9346, 0); +} + +void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x) +{ + *x = *x | Cfg9346_EESK; + RTL_W8(tp, Cfg9346, *x); + udelay(RTL_CLOCK_RATE); +} + +void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x) +{ + + *x = *x & ~Cfg9346_EESK; + RTL_W8(tp, Cfg9346, *x); + udelay(RTL_CLOCK_RATE); +} + +void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count) +{ + u8 x; + int mask; + + mask = 0x01 << (count - 1); + x = RTL_R8(tp, Cfg9346); + x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); + + do { + if (data & mask) + x |= Cfg9346_EEDI; + else + x &= ~Cfg9346_EEDI; + + RTL_W8(tp, Cfg9346, x); + udelay(RTL_CLOCK_RATE); + rtl8125_raise_clock(tp, &x); + rtl8125_lower_clock(tp, &x); + mask = mask >> 1; + } while(mask); + + x &= ~Cfg9346_EEDI; + RTL_W8(tp, Cfg9346, x); +} + +u16 rtl8125_shift_in_bits(struct rtl8125_private *tp) +{ + u8 x; + u16 d, i; + + x = RTL_R8(tp, Cfg9346); + x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); + + d = 0; + + for (i = 0; i < 16; i++) { + d = d << 1; + rtl8125_raise_clock(tp, &x); + + x = RTL_R8(tp, Cfg9346); + x &= ~Cfg9346_EEDI; + + if (x & Cfg9346_EEDO) + d |= 1; + + rtl8125_lower_clock(tp, &x); + } + + return d; +} + +void rtl8125_stand_by(struct rtl8125_private *tp) +{ + u8 x; + + x = RTL_R8(tp, Cfg9346); + x &= ~(Cfg9346_EECS | Cfg9346_EESK); + RTL_W8(tp, Cfg9346, x); + udelay(RTL_CLOCK_RATE); + + x |= Cfg9346_EECS; + RTL_W8(tp, Cfg9346, x); +} + +void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp) +{ + RTL_W8(tp, Cfg9346, Cfg9346_EEM1); + RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK); + + udelay(20); + + RTL_W8(tp, Cfg9346, Cfg9346_EEM1); +} diff --git a/r8125/src/rtl_eeprom.h b/r8125/src/rtl_eeprom.h new file mode 100755 index 000000000..b0c4a050b --- /dev/null +++ b/r8125/src/rtl_eeprom.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +//EEPROM opcodes +#define RTL_EEPROM_READ_OPCODE 06 +#define RTL_EEPROM_WRITE_OPCODE 05 +#define RTL_EEPROM_ERASE_OPCODE 07 +#define RTL_EEPROM_EWEN_OPCODE 19 +#define RTL_EEPROM_EWDS_OPCODE 16 + +#define RTL_CLOCK_RATE 3 + +void rtl8125_eeprom_type(struct rtl8125_private *tp); +void rtl8125_eeprom_cleanup(struct rtl8125_private *tp); +u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg); +void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data); +void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count); +u16 rtl8125_shift_in_bits(struct rtl8125_private *tp); +void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x); +void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x); +void rtl8125_stand_by(struct rtl8125_private *tp); +void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp); diff --git a/r8125/src/rtltool.c b/r8125/src/rtltool.c new file mode 100755 index 000000000..ace717bde --- /dev/null +++ b/r8125/src/rtltool.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "r8125.h" +#include "rtl_eeprom.h" +#include "rtltool.h" + +int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr) +{ + struct rtltool_cmd my_cmd; + int ret; + + if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd))) + return -EFAULT; + + ret = 0; + switch (my_cmd.cmd) { + case RTLTOOL_READ_MAC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len==1) + my_cmd.data = readb(tp->mmio_addr+my_cmd.offset); + else if (my_cmd.len==2) + my_cmd.data = readw(tp->mmio_addr+(my_cmd.offset&~1)); + else if (my_cmd.len==4) + my_cmd.data = readl(tp->mmio_addr+(my_cmd.offset&~3)); + else { + ret = -EOPNOTSUPP; + break; + } + + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + break; + + case RTLTOOL_WRITE_MAC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len==1) + writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset); + else if (my_cmd.len==2) + writew(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~1)); + else if (my_cmd.len==4) + writel(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~3)); + else { + ret = -EOPNOTSUPP; + break; + } + + break; + + case RTLTOOL_READ_PHY: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = rtl8125_mdio_prot_read(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTLTOOL_WRITE_PHY: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_mdio_prot_write(tp, my_cmd.offset, my_cmd.data); + break; + + case RTLTOOL_READ_EPHY: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = rtl8125_ephy_read(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTLTOOL_WRITE_EPHY: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_ephy_write(tp, my_cmd.offset, my_cmd.data); + break; + + case RTLTOOL_READ_ERI: + my_cmd.data = 0; + if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { + my_cmd.data = rtl8125_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC); + } else { + ret = -EOPNOTSUPP; + break; + } + + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTLTOOL_WRITE_ERI: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { + rtl8125_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC); + } else { + ret = -EOPNOTSUPP; + break; + } + break; + + case RTLTOOL_READ_PCI: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = 0; + if (my_cmd.len==1) + pci_read_config_byte(tp->pci_dev, my_cmd.offset, + (u8 *)&my_cmd.data); + else if (my_cmd.len==2) + pci_read_config_word(tp->pci_dev, my_cmd.offset, + (u16 *)&my_cmd.data); + else if (my_cmd.len==4) + pci_read_config_dword(tp->pci_dev, my_cmd.offset, + &my_cmd.data); + else { + ret = -EOPNOTSUPP; + break; + } + + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + break; + + case RTLTOOL_WRITE_PCI: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len==1) + pci_write_config_byte(tp->pci_dev, my_cmd.offset, + my_cmd.data); + else if (my_cmd.len==2) + pci_write_config_word(tp->pci_dev, my_cmd.offset, + my_cmd.data); + else if (my_cmd.len==4) + pci_write_config_dword(tp->pci_dev, my_cmd.offset, + my_cmd.data); + else { + ret = -EOPNOTSUPP; + break; + } + + break; + + case RTLTOOL_READ_EEPROM: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = rtl8125_eeprom_read_sc(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTLTOOL_WRITE_EEPROM: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data); + break; + + case RTL_READ_OOB_MAC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_oob_mutex_lock(tp); + my_cmd.data = rtl8125_ocp_read(tp, my_cmd.offset, 4); + rtl8125_oob_mutex_unlock(tp); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + break; + + case RTL_WRITE_OOB_MAC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.len == 0 || my_cmd.len > 4) + return -EOPNOTSUPP; + + rtl8125_oob_mutex_lock(tp); + rtl8125_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data); + rtl8125_oob_mutex_unlock(tp); + break; + + case RTL_ENABLE_PCI_DIAG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + tp->rtk_enable_diag = 1; + + dprintk("enable rtk diag\n"); + break; + + case RTL_DISABLE_PCI_DIAG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + tp->rtk_enable_diag = 0; + + dprintk("disable rtk diag\n"); + break; + + case RTL_READ_MAC_OCP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (my_cmd.offset % 2) + return -EOPNOTSUPP; + + my_cmd.data = rtl8125_mac_ocp_read(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + break; + + case RTL_WRITE_MAC_OCP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if ((my_cmd.offset % 2) || (my_cmd.len != 2)) + return -EOPNOTSUPP; + + rtl8125_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data); + break; + + case RTL_DIRECT_READ_PHY_OCP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + my_cmd.data = rtl8125_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset); + if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { + ret = -EFAULT; + break; + } + + break; + + case RTL_DIRECT_WRITE_PHY_OCP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + rtl8125_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data); + break; + + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} diff --git a/r8125/src/rtltool.h b/r8125/src/rtltool.h new file mode 100755 index 000000000..fc8a10ca8 --- /dev/null +++ b/r8125/src/rtltool.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +################################################################################ +# +# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet +# controllers with PCI-Express interface. +# +# Copyright(c) 2021 Realtek Semiconductor Corp. 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. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . +# +# Author: +# Realtek NIC software team +# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan +# +################################################################################ +*/ + +/************************************************************************************ + * This product is covered by one or more of the following patents: + * US6,570,884, US6,115,776, and US6,327,625. + ***********************************************************************************/ + +#ifndef _LINUX_RTLTOOL_H +#define _LINUX_RTLTOOL_H + +#define SIOCRTLTOOL SIOCDEVPRIVATE+1 + +enum rtl_cmd { + RTLTOOL_READ_MAC=0, + RTLTOOL_WRITE_MAC, + RTLTOOL_READ_PHY, + RTLTOOL_WRITE_PHY, + RTLTOOL_READ_EPHY, + RTLTOOL_WRITE_EPHY, + RTLTOOL_READ_ERI, + RTLTOOL_WRITE_ERI, + RTLTOOL_READ_PCI, + RTLTOOL_WRITE_PCI, + RTLTOOL_READ_EEPROM, + RTLTOOL_WRITE_EEPROM, + + RTL_READ_OOB_MAC, + RTL_WRITE_OOB_MAC, + + RTL_ENABLE_PCI_DIAG, + RTL_DISABLE_PCI_DIAG, + + RTL_READ_MAC_OCP, + RTL_WRITE_MAC_OCP, + + RTL_DIRECT_READ_PHY_OCP, + RTL_DIRECT_WRITE_PHY_OCP, + + RTLTOOL_INVALID +}; + +struct rtltool_cmd { + __u32 cmd; + __u32 offset; + __u32 len; + __u32 data; +}; + +enum mode_access { + MODE_NONE=0, + MODE_READ, + MODE_WRITE +}; + +#ifdef __KERNEL__ +int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr); +#endif + +#endif /* _LINUX_RTLTOOL_H */ diff --git a/r8168/Makefile b/r8168/Makefile new file mode 100755 index 000000000..fd5977a5b --- /dev/null +++ b/r8168/Makefile @@ -0,0 +1,54 @@ +# +# Download realtek r8168 linux driver from official site: +# [https://www.realtek.com/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-pci-express-software] +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=r8168 +PKG_VERSION:=8.049.02 +PKG_RELEASE:=$(AUTORELEAE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/BROBIRD/openwrt-r8168.git +PKG_SOURCE_DATE:=2021-10-08 +PKG_SOURCE_VERSION:=2b969c15afe403a685fc7ee069620782241e3ad6 +PKG_MIRROR_HASH:=e4632c10d460f005eff76da8a183d7ff0c8819b0d099872589b7b06a9b8d9952 + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +MAKE_PATH:=src + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/r8168 + TITLE:=Driver for Realtek r8168 chipsets + SUBMENU:=Network Devices + VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) + FILES:= $(PKG_BUILD_DIR)/src/r8168.ko + AUTOLOAD:=$(call AutoProbe,r8168) + CONFLICTS:=kmod-r8169 +endef + +define Package/r8168/description + This package contains a driver for Realtek r8168 chipsets. +endef + +R8168_MAKEOPTS= -C $(PKG_BUILD_DIR)/src \ + PATH="$(TARGET_PATH)" \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + TARGET="$(HAL_TARGET)" \ + TOOLPREFIX="$(KERNEL_CROSS)" \ + TOOLPATH="$(KERNEL_CROSS)" \ + KERNELPATH="$(LINUX_DIR)" \ + KERNELDIR="$(LINUX_DIR)" \ + LDOPTS=" " \ + DOMULTI=1 + +define Build/Compile + $(MAKE) $(R8168_MAKEOPTS) modules +endef + +$(eval $(call KernelPackage,r8168)) diff --git a/r8168/patches/001-r8168-add-LED-configuration-from-OF.patch b/r8168/patches/001-r8168-add-LED-configuration-from-OF.patch new file mode 100755 index 000000000..62a352dd8 --- /dev/null +++ b/r8168/patches/001-r8168-add-LED-configuration-from-OF.patch @@ -0,0 +1,42 @@ +--- a/src/r8168_n.c ++++ b/src/r8168_n.c +@@ -47,6 +47,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -23482,6 +23483,22 @@ rtl8168_set_bios_setting(struct net_devi + } + } + ++static int rtl8168_led_configuration(struct rtl8168_private *tp) ++{ ++ u32 led_data; ++ int ret; ++ ++ ret = of_property_read_u32(tp->pci_dev->dev.of_node, ++ "realtek,led-data", &led_data); ++ ++ if (ret) ++ return ret; ++ ++ RTL_W16(tp, CustomLED, led_data); ++ ++ return 0; ++} ++ + static void + rtl8168_init_software_variable(struct net_device *dev) + { +@@ -24000,6 +24017,8 @@ rtl8168_init_software_variable(struct ne + tp->NotWrMcuPatchCode = TRUE; + } + ++ rtl8168_led_configuration(tp); ++ + tp->NicCustLedValue = RTL_R16(tp, CustomLED); + + rtl8168_get_hw_wol(dev); diff --git a/shortcut-fe/Makefile b/shortcut-fe/Makefile old mode 100644 new mode 100755 diff --git a/shortcut-fe/files/usr/bin/sfe_dump b/shortcut-fe/files/usr/bin/sfe_dump old mode 100644 new mode 100755 diff --git a/shortcut-fe/src/Kconfig b/shortcut-fe/src/Kconfig old mode 100644 new mode 100755 diff --git a/shortcut-fe/src/Makefile b/shortcut-fe/src/Makefile old mode 100644 new mode 100755 diff --git a/shortcut-fe/src/sfe.h b/shortcut-fe/src/sfe.h old mode 100644 new mode 100755 diff --git a/shortcut-fe/src/sfe_backport.h b/shortcut-fe/src/sfe_backport.h old mode 100644 new mode 100755 diff --git a/shortcut-fe/src/sfe_cm.c b/shortcut-fe/src/sfe_cm.c old mode 100644 new mode 100755 diff --git a/shortcut-fe/src/sfe_cm.h b/shortcut-fe/src/sfe_cm.h old mode 100644 new mode 100755 diff --git a/shortcut-fe/src/sfe_ipv4.c b/shortcut-fe/src/sfe_ipv4.c old mode 100644 new mode 100755 diff --git a/shortcut-fe/src/sfe_ipv6.c b/shortcut-fe/src/sfe_ipv6.c old mode 100644 new mode 100755 diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index 48f2f8197..f17adbf69 100755 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -12,8 +12,9 @@ PKG_NAME:=v2ray-core PKG_VERSION:=4.43.0 PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://github.com/v2fly/v2ray-core/archive/v$(PKG_VERSION) +#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE:=v$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://github.com/v2fly/v2ray-core/archive/refs/tags/ PKG_HASH:=f27b8fe8e1e102b0297339ee368c8b650fde0f949e0d90e1229ff6744f99ba0f PKG_LICENSE:=MIT diff --git a/xtables-addons/Makefile b/xtables-addons/Makefile old mode 100644 new mode 100755 diff --git a/xtables-addons/patches/001-fix-kernel-version-detection.patch b/xtables-addons/patches/001-fix-kernel-version-detection.patch old mode 100644 new mode 100755 diff --git a/xtables-addons/patches/100-add-rtsp-conntrack.patch b/xtables-addons/patches/100-add-rtsp-conntrack.patch old mode 100644 new mode 100755 diff --git a/xtables-addons/patches/200-add-lua-packetscript.patch b/xtables-addons/patches/200-add-lua-packetscript.patch old mode 100644 new mode 100755 diff --git a/xtables-addons/patches/201-fix-lua-packetscript.patch b/xtables-addons/patches/201-fix-lua-packetscript.patch old mode 100644 new mode 100755 diff --git a/xtables-addons/patches/210-freebsd-build-fix.patch b/xtables-addons/patches/210-freebsd-build-fix.patch old mode 100644 new mode 100755