From a2ad08b4895550bf0586a79612ea90ecfd6ca9b8 Mon Sep 17 00:00:00 2001 From: nico Date: Mon, 29 Mar 2010 13:06:19 +0000 Subject: [PATCH 01/45] [include] download.mk: fix bzr download method git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20582 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- include/download.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/download.mk b/include/download.mk index c924ca051..9dd26a744 100644 --- a/include/download.mk +++ b/include/download.mk @@ -104,10 +104,10 @@ define DownloadMethod/bzr cd $(TMP_DIR)/dl && \ rm -rf $(SUBDIR) && \ [ \! -d $(SUBDIR) ] && \ - bzr export -r$(VERSION) $(URL) $(SUBDIR) && \ + bzr export -r$(VERSION) $(SUBDIR) $(URL) && \ echo "Packing checkout..." && \ $(call dl_pack,$(TMP_DIR)/dl/$(FILE),$(SUBDIR)) && \ - mv $(TMP_DIR)/dl/$(FILE) $(DL_DIR)/ && + mv $(TMP_DIR)/dl/$(FILE) $(DL_DIR)/ && \ rm -rf $(SUBDIR); \ ) endef From ff1723ec3adaeb3922bbd020e6c3aa9e128c44ab Mon Sep 17 00:00:00 2001 From: nbd Date: Mon, 29 Mar 2010 15:16:17 +0000 Subject: [PATCH 02/45] fix kernel-headers build git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20584 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- toolchain/kernel-headers/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/toolchain/kernel-headers/Makefile b/toolchain/kernel-headers/Makefile index 47e7b245b..394e1d109 100644 --- a/toolchain/kernel-headers/Makefile +++ b/toolchain/kernel-headers/Makefile @@ -21,6 +21,7 @@ PKG_SOURCE_URL:=$(LINUX_SITE) HOST_BUILD_DIR:=$(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION) PKG_MD5SUM:=$(LINUX_KERNEL_MD5SUM) LINUX_DIR := $(HOST_BUILD_DIR) +FILES_DIR := include $(INCLUDE_DIR)/toolchain-build.mk include $(INCLUDE_DIR)/kernel-defaults.mk From e25d070c9be8c36b6cbf98c8757c729907e7775f Mon Sep 17 00:00:00 2001 From: hauke Date: Mon, 29 Mar 2010 18:33:48 +0000 Subject: [PATCH 03/45] mac80211: fix mesh. This fixes #6774 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20585 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/mac80211/patches/300-fix-mesh.patch | 45 +++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 package/mac80211/patches/300-fix-mesh.patch diff --git a/package/mac80211/patches/300-fix-mesh.patch b/package/mac80211/patches/300-fix-mesh.patch new file mode 100644 index 000000000..554565615 --- /dev/null +++ b/package/mac80211/patches/300-fix-mesh.patch @@ -0,0 +1,45 @@ +From 181ce6f71d907f42ab73376ce154015a835a6d8a Mon Sep 17 00:00:00 2001 +From: Javier Cardona +Date: Mon, 29 Mar 2010 11:00:20 -0700 +Subject: [PATCH] mac80211: Handle mesh action frames in ieee80211_rx_h_action + +This fixes the problem introduced in commit +8404080568613d93ad7cf0a16dfb68 which broke mesh peer link establishment. + +changes: +v2 Added missing break (Johannes) +v3 Broke original patch into two (Johannes) + +Signed-off-by: Javier Cardona +Signed-off-by: Hauke Mehrtens +--- + net/mac80211/mesh.c | 3 --- + net/mac80211/rx.c | 5 +++++ + 2 files changed, 5 insertions(+), 3 deletions(-) + +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -749,9 +749,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_ + + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_ACTION: +- if (skb->len < IEEE80211_MIN_ACTION_SIZE) +- return RX_DROP_MONITOR; +- /* fall through */ + case IEEE80211_STYPE_PROBE_RESP: + case IEEE80211_STYPE_BEACON: + skb_queue_tail(&ifmsh->skb_queue, skb); +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1964,6 +1964,11 @@ ieee80211_rx_h_action(struct ieee80211_r + goto handled; + } + break; ++ case MESH_PLINK_CATEGORY: ++ case MESH_PATH_SEL_CATEGORY: ++ if (ieee80211_vif_is_mesh(&sdata->vif)) ++ return ieee80211_mesh_rx_mgmt(sdata, rx->skb); ++ break; + } + + /* From 348cb2f61ed561ba5cbcfd0eb861e98dd9cf5a3c Mon Sep 17 00:00:00 2001 From: hauke Date: Mon, 29 Mar 2010 21:02:14 +0000 Subject: [PATCH 04/45] kernel: fix dependencies for x86 target kmod-hid and kmod-input-core are directly build into the kernel for the x86 target. No package on x86 should depend on it. This fixes #6963 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20590 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/kernel/modules/other.mk | 14 +++++++------- package/kernel/modules/usb.mk | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package/kernel/modules/other.mk b/package/kernel/modules/other.mk index 8d51f90d2..48bf1ab99 100644 --- a/package/kernel/modules/other.mk +++ b/package/kernel/modules/other.mk @@ -261,7 +261,7 @@ $(eval $(call KernelPackage,ssb)) define KernelPackage/bluetooth SUBMENU:=$(OTHER_MENU) TITLE:=Bluetooth support - DEPENDS:=@USB_SUPPORT +kmod-usb-core +kmod-hid + DEPENDS:=@USB_SUPPORT +kmod-usb-core +!TARGET_x86:kmod-hid KCONFIG:= \ CONFIG_BLUEZ \ CONFIG_BLUEZ_L2CAP \ @@ -651,7 +651,7 @@ $(eval $(call KernelPackage,sc520-wdt)) define KernelPackage/input-core SUBMENU:=$(OTHER_MENU) TITLE:=Input device core - DEPENDS:=@LINUX_2_6 + DEPENDS:=@LINUX_2_6 @!TARGET_x86 KCONFIG:=CONFIG_INPUT FILES:=$(LINUX_DIR)/drivers/input/input-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,19,input-core) @@ -667,7 +667,7 @@ $(eval $(call KernelPackage,input-core)) define KernelPackage/input-evdev SUBMENU:=$(OTHER_MENU) TITLE:=Input event device - DEPENDS:=+kmod-input-core + DEPENDS:=+!TARGET_x86:kmod-input-core KCONFIG:=CONFIG_INPUT_EVDEV FILES:=$(LINUX_DIR)/drivers/input/evdev.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,60,evdev) @@ -683,7 +683,7 @@ $(eval $(call KernelPackage,input-evdev)) define KernelPackage/hid SUBMENU:=$(OTHER_MENU) TITLE:=HID Devices - DEPENDS:=+kmod-input-core +kmod-input-evdev + DEPENDS:=+kmod-input-core +kmod-input-evdev @!TARGET_x86 KCONFIG:=CONFIG_HID FILES:=$(LINUX_DIR)/drivers/hid/hid.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,61,hid) @@ -699,7 +699,7 @@ $(eval $(call KernelPackage,hid)) define KernelPackage/input-polldev SUBMENU:=$(OTHER_MENU) TITLE:=Polled Input device support - DEPENDS:=+kmod-input-core @LINUX_2_6 + DEPENDS:=+!TARGET_x86:kmod-input-core @LINUX_2_6 KCONFIG:=CONFIG_INPUT_POLLDEV FILES:=$(LINUX_DIR)/drivers/input/input-polldev.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,20,input-polldev) @@ -715,7 +715,7 @@ $(eval $(call KernelPackage,input-polldev)) define KernelPackage/input-gpio-keys SUBMENU:=$(OTHER_MENU) TITLE:=GPIO key support - DEPENDS:= @GPIO_SUPPORT +kmod-input-core + DEPENDS:= @GPIO_SUPPORT +!TARGET_x86:kmod-input-core KCONFIG:=CONFIG_KEYBOARD_GPIO FILES:=$(LINUX_DIR)/drivers/input/keyboard/gpio_keys.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,60,gpio_keys) @@ -749,7 +749,7 @@ $(eval $(call KernelPackage,input-gpio-buttons)) define KernelPackage/input-joydev SUBMENU:=$(OTHER_MENU) TITLE:=Joystick device support - DEPENDS:=+kmod-input-core + DEPENDS:=+!TARGET_x86:kmod-input-core KCONFIG:=CONFIG_INPUT_JOYDEV FILES:=$(LINUX_DIR)/drivers/input/joydev.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,62,joydev) diff --git a/package/kernel/modules/usb.mk b/package/kernel/modules/usb.mk index 322c62398..c962e340e 100644 --- a/package/kernel/modules/usb.mk +++ b/package/kernel/modules/usb.mk @@ -777,7 +777,7 @@ $(eval $(call KernelPackage,usb-net-rndis)) define KernelPackage/usb-hid -$(call KernelPackage/usb/Depends,@LINUX_2_6 +kmod-input-core +kmod-input-evdev +kmod-hid) +$(call KernelPackage/usb/Depends,@LINUX_2_6 +!TARGET_x86:kmod-input-core +kmod-input-evdev +!TARGET_x86:kmod-hid) TITLE:=Support for USB Human Input Devices KCONFIG:=CONFIG_HID_SUPPORT=y CONFIG_USB_HID FILES:=$(LINUX_DIR)/drivers/$(USBHID_DIR)/usbhid.ko @@ -793,7 +793,7 @@ $(eval $(call KernelPackage,usb-hid)) define KernelPackage/usb-yealink -$(call KernelPackage/usb/Depends,@LINUX_2_6 +kmod-input-core +kmod-input-evdev) +$(call KernelPackage/usb/Depends,@LINUX_2_6 +!TARGET_x86:kmod-input-core +kmod-input-evdev) TITLE:=USB Yealink VOIP phone KCONFIG:=CONFIG_USB_YEALINK CONFIG_INPUT_YEALINK CONFIG_INPUT=m CONFIG_INPUT_MISC=y FILES:=$(LINUX_DIR)/drivers/$(USBINPUT_DIR)/yealink.ko @@ -808,7 +808,7 @@ $(eval $(call KernelPackage,usb-yealink)) define KernelPackage/usb-cm109 -$(call KernelPackage/usb/Depends,@LINUX_2_6 +kmod-input-core +kmod-input-evdev) +$(call KernelPackage/usb/Depends,@LINUX_2_6 +!TARGET_x86:kmod-input-core +kmod-input-evdev) TITLE:=Support for CM109 device KCONFIG:=CONFIG_USB_CM109 CONFIG_INPUT_CM109 CONFIG_INPUT=m CONFIG_INPUT_MISC=y FILES:=$(LINUX_DIR)/drivers/$(USBINPUT_DIR)/cm109.ko From 52fc6ae252b1d2812d889824df99f243fc73dbb7 Mon Sep 17 00:00:00 2001 From: florian Date: Mon, 29 Mar 2010 21:20:36 +0000 Subject: [PATCH 05/45] [package] fix ndisc compilation failure (#6984) git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20591 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../generic-2.4/patches/629-netlink_types_h.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/target/linux/generic-2.4/patches/629-netlink_types_h.patch b/target/linux/generic-2.4/patches/629-netlink_types_h.patch index 8347d170b..9c5b45df6 100644 --- a/target/linux/generic-2.4/patches/629-netlink_types_h.patch +++ b/target/linux/generic-2.4/patches/629-netlink_types_h.patch @@ -9,3 +9,14 @@ #define NETLINK_ROUTE 0 /* Routing/device hook */ #define NETLINK_SKIP 1 /* Reserved for ENskip */ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ +--- a/include/linux/filter.h 2010-02-01 22:04:46.000000000 +0100 ++++ b/include/linux/filter.h 2010-03-29 20:57:08.000000000 +0200 +@@ -5,6 +5,8 @@ + #ifndef __LINUX_FILTER_H__ + #define __LINUX_FILTER_H__ + ++#include ++ + /* + * Current version of the filter code architecture. + */ From bdaa1830146059a3d43d2e45a3620641ea28794a Mon Sep 17 00:00:00 2001 From: jow Date: Mon, 29 Mar 2010 23:14:47 +0000 Subject: [PATCH 06/45] [package] openssl: add patch for CVE-2010-0740 ("Record of death") vulnerability git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20592 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/openssl/Makefile | 2 +- package/openssl/patches/400-cve-2010-0740.patch | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 package/openssl/patches/400-cve-2010-0740.patch diff --git a/package/openssl/Makefile b/package/openssl/Makefile index e7a74905f..9f80a98f3 100644 --- a/package/openssl/Makefile +++ b/package/openssl/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openssl PKG_VERSION:=0.9.8m -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.openssl.org/source/ \ diff --git a/package/openssl/patches/400-cve-2010-0740.patch b/package/openssl/patches/400-cve-2010-0740.patch new file mode 100644 index 000000000..4c893eb38 --- /dev/null +++ b/package/openssl/patches/400-cve-2010-0740.patch @@ -0,0 +1,15 @@ +--- a/ssl/s3_pkt.c ++++ b/ssl/s3_pkt.c +@@ -291,9 +291,9 @@ again: + if (version != s->version) + { + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); +- /* Send back error using their +- * version number :-) */ +- s->version=version; ++ if ((s->version & 0xFF00) == (version & 0xFF00)) ++ /* Send back error using their minor version number :-) */ ++ s->version = (unsigned short)version; + al=SSL_AD_PROTOCOL_VERSION; + goto f_err; + } From f8877972dac9f83921b8a460467a4c0caa2de4ec Mon Sep 17 00:00:00 2001 From: nico Date: Tue, 30 Mar 2010 04:04:47 +0000 Subject: [PATCH 07/45] fix path to libgcc.a in LIBGCC_S git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20593 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules.mk b/rules.mk index f913d9856..0cb72ac6b 100644 --- a/rules.mk +++ b/rules.mk @@ -104,7 +104,7 @@ TARGET_PATH:=$(STAGING_DIR_HOST)/bin:$(PATH) TARGET_CFLAGS:=$(TARGET_OPTIMIZATION)$(if $(CONFIG_DEBUG), -g3) TARGET_CPPFLAGS:=-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include TARGET_LDFLAGS:=-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib -LIBGCC_S=$(if $(wildcard $(TOOLCHAIN_DIR)/lib/libgcc_s.so),-L$(TOOLCHAIN_DIR)/lib -lgcc_s,$(wildcard $(TOOLCHAIN_DIR)/lib/gcc/*/*/libgcc.a)) +LIBGCC_S=$(if $(wildcard $(TOOLCHAIN_DIR)/lib/libgcc_s.so),-L$(TOOLCHAIN_DIR)/lib -lgcc_s,$(wildcard $(TOOLCHAIN_DIR)/usr/lib/gcc/*/*/libgcc.a)) ifndef DUMP ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),) From c8998c07093cb17557e609c24a880247c59ed34b Mon Sep 17 00:00:00 2001 From: juhosg Date: Tue, 30 Mar 2010 08:01:35 +0000 Subject: [PATCH 08/45] toolchain/binutils: building gas for arm-*-uclibc systems requires linking with -lm git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20594 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../2.18/112-arm-uclibc-gas-needs-libm.patch | 38 +++++++++++++++++++ .../112-arm-uclibc-gas-needs-libm.patch | 38 +++++++++++++++++++ .../112-arm-uclibc-gas-needs-libm.patch | 38 +++++++++++++++++++ .../112-arm-uclibc-gas-needs-libm.patch | 38 +++++++++++++++++++ .../2.20/112-arm-uclibc-gas-needs-libm.patch | 38 +++++++++++++++++++ 5 files changed, 190 insertions(+) create mode 100644 toolchain/binutils/patches/2.18/112-arm-uclibc-gas-needs-libm.patch create mode 100644 toolchain/binutils/patches/2.19.1+cs/112-arm-uclibc-gas-needs-libm.patch create mode 100644 toolchain/binutils/patches/2.19.1/112-arm-uclibc-gas-needs-libm.patch create mode 100644 toolchain/binutils/patches/2.20.1/112-arm-uclibc-gas-needs-libm.patch create mode 100644 toolchain/binutils/patches/2.20/112-arm-uclibc-gas-needs-libm.patch diff --git a/toolchain/binutils/patches/2.18/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.18/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..2f46afbd4 --- /dev/null +++ b/toolchain/binutils/patches/2.18/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -411,6 +411,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + diff --git a/toolchain/binutils/patches/2.19.1+cs/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.19.1+cs/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..f7731613f --- /dev/null +++ b/toolchain/binutils/patches/2.19.1+cs/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -415,6 +415,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + diff --git a/toolchain/binutils/patches/2.19.1/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.19.1/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..f7731613f --- /dev/null +++ b/toolchain/binutils/patches/2.19.1/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -415,6 +415,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + diff --git a/toolchain/binutils/patches/2.20.1/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.20.1/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..abc8117e2 --- /dev/null +++ b/toolchain/binutils/patches/2.20.1/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -431,6 +431,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | microblaze | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + diff --git a/toolchain/binutils/patches/2.20/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.20/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..abc8117e2 --- /dev/null +++ b/toolchain/binutils/patches/2.20/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -431,6 +431,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | microblaze | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + From 37bcda62c00cb40d73bcee1ba10adfdea432dc7a Mon Sep 17 00:00:00 2001 From: blogic Date: Tue, 30 Mar 2010 10:06:05 +0000 Subject: [PATCH 09/45] [ramips] Fix the base address of the wireless card. Otherwise it is not possible to register a platform wireless device as it overlaps with something else. Signed-off-by: Helmut Schaa git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20596 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../files/arch/mips/include/asm/mach-ralink/rt305x_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h index 4056b163d..6e7b9e8e6 100644 --- a/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h +++ b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h @@ -28,7 +28,7 @@ #define RT305X_UART1_BASE 0x10000c00 #define RT305X_FE_BASE 0x10100000 #define RT305X_SWITCH_BASE 0x10110000 -#define RT305X_WMAC_BASE 0x00180000 +#define RT305X_WMAC_BASE 0x10180000 #define RT305X_OTG_BASE 0x101c0000 #define RT305X_ROM_BASE 0x00400000 #define RT305X_FLASH1_BASE 0x1b000000 From 87d817ac8c7259389f321d5f707e8c223c3dd487 Mon Sep 17 00:00:00 2001 From: nico Date: Tue, 30 Mar 2010 11:41:51 +0000 Subject: [PATCH 10/45] imagebuilder: various fixes * only copy host tools from $(STAGING_DIR_HOST)/bin * remove more target patches, and also target files * combine the 3 find commands into a single one git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20597 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/imagebuilder/Makefile | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/target/imagebuilder/Makefile b/target/imagebuilder/Makefile index 923c1e94b..e0b64ead4 100644 --- a/target/imagebuilder/Makefile +++ b/target/imagebuilder/Makefile @@ -31,17 +31,15 @@ $(BIN_DIR)/$(IB_NAME).tar.bz2: clean $(TMP_DIR)/.packageinfo \ $(PKG_BUILD_DIR)/ $(CP) $(PACKAGE_DIR) $(PKG_BUILD_DIR)/packages - $(CP) $(TOOLCHAIN_DIR)/bin $(PKG_BUILD_DIR)/staging_dir/host/ - $(CP) $(STAGING_DIR_HOST)/bin/* $(PKG_BUILD_DIR)/staging_dir/host/bin/ + $(CP) $(STAGING_DIR_HOST)/bin $(PKG_BUILD_DIR)/staging_dir/host/ $(CP) $(TOPDIR)/target/linux $(PKG_BUILD_DIR)/target/ rm -rf \ - $(PKG_BUILD_DIR)/target/linux/*/patches \ - $(PKG_BUILD_DIR)/target/linux/*/*/patches + $(PKG_BUILD_DIR)/target/linux/*/files{,-*} \ + $(PKG_BUILD_DIR)/target/linux/*/patches{,-*} -cp $(KERNEL_BUILD_DIR)/* $(IB_KDIR)/ # don't copy subdirectories here echo REVISION:="$(REVISION)" > $(PKG_BUILD_DIR)/include/version.mk - find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf - find $(PKG_BUILD_DIR) -name CVS | $(XARGS) rm -rf - find $(PKG_BUILD_DIR) -name .git | $(XARGS) rm -rf + find $(PKG_BUILD_DIR) -name CVS -o -name .git -o -name .svn \ + | $(XARGS) rm -rf $(TAR) c -C $(BUILD_DIR) $(IB_NAME) | bzip2 -c > $@ download: From af50db9d92e486050f50ffe5ffc9be8997620fbd Mon Sep 17 00:00:00 2001 From: nico Date: Tue, 30 Mar 2010 11:42:41 +0000 Subject: [PATCH 11/45] imagebuilder: don't disable on uml git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20598 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/imagebuilder/Config.in | 1 - 1 file changed, 1 deletion(-) diff --git a/target/imagebuilder/Config.in b/target/imagebuilder/Config.in index a31526599..23a418bf5 100644 --- a/target/imagebuilder/Config.in +++ b/target/imagebuilder/Config.in @@ -1,7 +1,6 @@ config IB bool "Build the OpenWrt Image Builder" depends !TARGET_ROOTFS_INITRAMFS - depends !TARGET_uml depends !PROFILE_KCONFIG depends !EXTERNAL_TOOLCHAIN help From 0f85365209e075c6969b4157eb1137be37ccaeeb Mon Sep 17 00:00:00 2001 From: blogic Date: Tue, 30 Mar 2010 12:04:05 +0000 Subject: [PATCH 12/45] The ralink rt305x board has a wireless card that can be used with the rt2800pci driver (it does not work yet but basically should). Hence, register the appropriate platform device to allow developing/testing the rt2800pci driver. Signed-off-by: Helmut Schaa git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20599 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../files/arch/mips/ralink/rt305x/devices.c | 26 +++++++++++++++++++ .../files/arch/mips/ralink/rt305x/devices.h | 1 + 2 files changed, 27 insertions(+) diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c index 6a810a3a0..4ee0d4f1b 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c @@ -136,3 +136,29 @@ void __init rt305x_register_ethernet(void) platform_device_register(&rt305x_eth_device); } + +static struct resource rt305x_wifi_resources[] = { + { + .start = RT305X_WMAC_BASE, + .end = RT305X_WMAC_BASE + 0x3FFFF, + .flags = IORESOURCE_MEM, + }, { + .start = RT305X_CPU_IRQ_WNIC, + .end = RT305X_CPU_IRQ_WNIC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device rt305x_wifi_device = { + .name = "rt2800_wmac", + .resource = rt305x_wifi_resources, + .num_resources = ARRAY_SIZE(rt305x_wifi_resources), + .dev = { + .platform_data = NULL, + } +}; + +void __init rt305x_register_wifi(void) +{ + platform_device_register(&rt305x_wifi_device); +} diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h index 3d6210e0e..7e2144c16 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h @@ -16,6 +16,7 @@ struct physmap_flash_data; extern void rt305x_register_flash(unsigned int id, struct physmap_flash_data *pdata) __init; extern void rt305x_register_ethernet(void); +extern void rt305x_register_wifi(void); #endif /* __RT305X_DEVICES_H */ From ed42a8a32363683414d3aeba3bbbd242831b6adb Mon Sep 17 00:00:00 2001 From: ralph Date: Tue, 30 Mar 2010 13:49:42 +0000 Subject: [PATCH 13/45] adding httpd - failsafe patch flash write routine is not functional yet add configuration (board & dram) git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20603 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/uboot-lantiq/Makefile | 18 +++- .../files/board/infineon/easy50712/danube.c | 102 ++++++++++++++++++ .../files/include/configs/easy50712.h | 2 + 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/package/uboot-lantiq/Makefile b/package/uboot-lantiq/Makefile index 3ffe8846e..48f468316 100644 --- a/package/uboot-lantiq/Makefile +++ b/package/uboot-lantiq/Makefile @@ -35,12 +35,20 @@ define Build/Prepare find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf endef -UBOOT_CONFIG:=easy50712_DDR166M +UBOOT_CONFIG:=$(call qstrip,$(CONFIG_UBOOT_CONFIG)) +UBOOT_DDR_CONFIG:=$(call qstrip,$(CONFIG_UBOOT_DDR_CONFIG)) + UBOOT_MAKE_OPTS:= \ CROSS_COMPILE=$(TARGET_CROSS) \ ENDIANNESS= \ V=1 +define Package/uboot-lantiq/config + menu "configuration" + source "$(SOURCE)/Config.in" + endmenu +endef + define Build/Configure/Target $(MAKE) -s -C $(PKG_BUILD_DIR) \ $(UBOOT_MAKE_OPTS) \ @@ -50,7 +58,9 @@ endef define Build/Configure $(call Build/Configure/Target,$(UBOOT_CONFIG)) +ifeq ($(CONFIG_UBOOT_RAMBOOT),y) $(call Build/Configure/Target,$(UBOOT_CONFIG)_ramboot) +endif endef define Build/Compile/Target @@ -62,7 +72,9 @@ endef define Build/Compile $(call Build/Compile/Target,$(UBOOT_CONFIG)) +ifeq ($(CONFIG_UBOOT_RAMBOOT),y) $(call Build/Compile/Target,$(UBOOT_CONFIG)_ramboot) +endif endef define Package/uboot-lantiq/install @@ -71,12 +83,14 @@ define Package/uboot-lantiq/install if=$(PKG_BUILD_DIR)/$(UBOOT_CONFIG)/u-boot.bin \ of=$(1)/$(UBOOT_CONFIG)/u-boot.bin \ bs=64k conv=sync +ifeq ($(CONFIG_UBOOT_RAMBOOT),y) if [ -e $(UBOOT_CONFIG).conf ]; then \ perl ./gct \ - $(UBOOT_CONFIG).conf \ + $(UBOOT_DDR_CONFIG) \ $(PKG_BUILD_DIR)/$(UBOOT_CONFIG)_ramboot/u-boot.srec \ $(1)/$(UBOOT_CONFIG)/u-boot.asc; \ fi +endif endef $(eval $(call BuildPackage,uboot-lantiq)) diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/danube.c b/package/uboot-lantiq/files/board/infineon/easy50712/danube.c index 473436692..f9b2b7626 100644 --- a/package/uboot-lantiq/files/board/infineon/easy50712/danube.c +++ b/package/uboot-lantiq/files/board/infineon/easy50712/danube.c @@ -32,6 +32,9 @@ #include #include #include +#if defined(CONFIG_CMD_HTTPD) +#include +#endif extern ulong ifx_get_ddr_hz(void); extern ulong ifx_get_cpuclk(void); @@ -336,3 +339,102 @@ int board_eth_init(bd_t *bis) return 0; } +#if defined(CONFIG_CMD_HTTPD) +static int image_info (ulong addr) +{ + void *hdr = (void *)addr; + + printf ("\n## Checking Image at %08lx ...\n", addr); + + switch (genimg_get_format (hdr)) { + case IMAGE_FORMAT_LEGACY: + puts (" Legacy image found\n"); + if (!image_check_magic (hdr)) { + puts (" Bad Magic Number\n"); + return 1; + } + + if (!image_check_hcrc (hdr)) { + puts (" Bad Header Checksum\n"); + return 1; + } + + image_print_contents (hdr); + + puts (" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + puts (" Bad Data CRC\n"); + return 1; + } + puts ("OK\n"); + return 0; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + puts (" FIT image found\n"); + + if (!fit_check_format (hdr)) { + puts ("Bad FIT image format!\n"); + return 1; + } + + fit_print_contents (hdr); + + if (!fit_all_image_check_hashes (hdr)) { + puts ("Bad hash in FIT image!\n"); + return 1; + } + + return 0; +#endif + default: + puts ("Unknown image format!\n"); + break; + } + + return 1; +} + +int do_http_upgrade(const unsigned char *data, const ulong size) +{ + /* check the image */ + if(image_info(data)) { + return -1; + } + /* write the image to the flash */ + puts("http ugrade ...\n"); + return 0; +} + +int do_http_progress(const int state) +{ + /* toggle LED's here */ + switch(state) { + case HTTP_PROGRESS_START: + puts("http start\n"); + break; + case HTTP_PROGRESS_TIMEOUT: + break; + case HTTP_PROGRESS_UPLOAD_READY: + puts("http upload ready\n"); + break; + case HTTP_PROGRESS_UGRADE_READY: + puts("http ugrade ready\n"); + break; + case HTTP_PROGRESS_UGRADE_FAILED: + puts("http ugrade failed\n"); + break; + } + return 0; +} + +unsigned long do_http_tmp_address(void) +{ + char *s = getenv ("ram_addr"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + return 0 /*0x80a00000*/; +} + +#endif diff --git a/package/uboot-lantiq/files/include/configs/easy50712.h b/package/uboot-lantiq/files/include/configs/easy50712.h index e061b831d..8eeb6c06a 100644 --- a/package/uboot-lantiq/files/include/configs/easy50712.h +++ b/package/uboot-lantiq/files/include/configs/easy50712.h @@ -112,4 +112,6 @@ # define CONFIG_EBU_BUSCON0 0x0001D7FF #endif +#define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */ + #endif /* __CONFIG_H */ From e0e232b87230222418b8df5444e2975e1a6ceb33 Mon Sep 17 00:00:00 2001 From: ralph Date: Tue, 30 Mar 2010 13:51:10 +0000 Subject: [PATCH 14/45] missing patch & config file git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20604 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/uboot-lantiq/Config.in | 32 + package/uboot-lantiq/patches/300-httpd.patch | 9349 ++++++++++++++++++ 2 files changed, 9381 insertions(+) create mode 100644 package/uboot-lantiq/Config.in create mode 100644 package/uboot-lantiq/patches/300-httpd.patch diff --git a/package/uboot-lantiq/Config.in b/package/uboot-lantiq/Config.in new file mode 100644 index 000000000..7544e711d --- /dev/null +++ b/package/uboot-lantiq/Config.in @@ -0,0 +1,32 @@ +config UBOOT_CONFIG + string "configuration file" + default "easy50712_DDR166M" + help + The configuration reflects the settings for a dedicated board hardware. + Select for Danube evaluation board easy50712_DDR166M . + Select for AR9 evaluation board easy50812_DDR166M . + +config UBOOT_DDR_CONFIG + string "DDR configuration file" + default "danube_ref_ddr166.conf" + depends on UBOOT_RAMBOOT + help + The DDR configuration file should reflect the DDR memory device configuration . + It will be used to create a RAM boot image + Select for Danube evalution board danube_ref_ddr166.conf . + Select for AR9 evalution board easy50812.conf . + +config UBOOT_RAMBOOT + bool "Enable RAM boot image" + help + Using the UART boot mode of the ROM code this image could be loaded to the RAM. + Executing the image in the RAM the functionality of the uboot image can be + tested first without touching the original flash. + Note: Be carefull, by saving the environment the flash will be modified. + The OWRT flash layout differs from the layout provided by Lantiq / Infineon. + +config IFXMIPS_UBOOT_A800 + bool "add ARV452 Switch bringup hack" + depends on PACKAGE_uboot-ifxmips + help + Say Y, if you have a arv452 board (wav-281, A800, ..) diff --git a/package/uboot-lantiq/patches/300-httpd.patch b/package/uboot-lantiq/patches/300-httpd.patch new file mode 100644 index 000000000..f9a81e90c --- /dev/null +++ b/package/uboot-lantiq/patches/300-httpd.patch @@ -0,0 +1,9349 @@ +--- a/common/cmd_net.c ++++ b/common/cmd_net.c +@@ -43,6 +43,18 @@ U_BOOT_CMD( + "[loadAddress] [[hostIPaddr:]bootfilename]" + ); + ++#if defined(CONFIG_CMD_HTTPD) ++int do_httpd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ++{ ++ return NetLoopHttpd(); ++} ++ ++U_BOOT_CMD( ++ httpd, 1, 1, do_httpd, ++ "httpd\t- start webserver\n", "\n" ++); ++#endif ++ + int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) + { + return netboot_common (TFTP, cmdtp, argc, argv); +--- a/include/net.h ++++ b/include/net.h +@@ -383,7 +383,8 @@ extern int NetTimeOffset; /* offset ti + + /* Initialize the network adapter */ + extern int NetLoop(proto_t); +- ++extern int NetLoopHttpd(void); ++extern void NetSendHttpd(void); + /* Shutdown adapters and cleanup */ + extern void NetStop(void); + +--- /dev/null ++++ b/net/httpd.c +@@ -0,0 +1,52 @@ ++/* ++ * Copyright 1994, 1995, 2000 Neil Russell. ++ * (See License) ++ * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de ++ */ ++ ++#include ++#include ++#include ++#include "uip-0.9/uipopt.h" ++#include "uip-0.9/uip.h" ++#include "uip-0.9/uip_arp.h" ++ ++ ++#if defined(CONFIG_CMD_HTTPD) ++ ++#define TIMEOUT 5 ++ ++static int arptimer = 0; ++ ++void ++HttpdHandler (void) ++{ ++ int i; ++ for(i = 0; i < UIP_CONNS; i++) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ NetSendHttpd(); ++ } ++ } ++ if(++arptimer == 20) { ++ uip_arp_timer(); ++ arptimer = 0; ++ } ++} ++ ++static void ++HttpdTimeout (void) ++{ ++ puts ("T "); ++ NetSetTimeout (TIMEOUT * 1000, HttpdTimeout); ++} ++ ++void ++HttpdStart (void) ++{ ++ uip_init(); ++ httpd_init(); ++} ++ ++#endif +--- /dev/null ++++ b/include/httpd.h +@@ -0,0 +1,17 @@ ++#ifndef _UIP_HTTPD_H__ ++#define _UIP_HTTPD_H__ ++ ++void HttpdStart (void); ++void HttpdHandler (void); ++ ++/* board specific implementation */ ++extern int do_http_upgrade(const unsigned char *data, const ulong size); ++ ++#define HTTP_PROGRESS_START 0 ++#define HTTP_PROGRESS_TIMEOUT 1 ++#define HTTP_PROGRESS_UPLOAD_READY 2 ++#define HTTP_PROGRESS_UGRADE_READY 3 ++#define HTTP_PROGRESS_UGRADE_FAILED 4 ++extern int do_http_progress(const int state); ++ ++#endif +--- a/net/Makefile ++++ b/net/Makefile +@@ -26,6 +26,10 @@ include $(TOPDIR)/config.mk + # CFLAGS += -DDEBUG + + LIB = $(obj)libnet.a ++UIPDIR = uip-0.9 ++RSADIR = uip-0.9 ++$(shell mkdir -p $(obj)$(UIPDIR)) ++$(shell mkdir -p $(obj)$(RSADIR)) + + COBJS-y += bootp.o + COBJS-$(CONFIG_CMD_DNS) += dns.o +@@ -36,6 +40,9 @@ COBJS-y += rarp.o + COBJS-$(CONFIG_CMD_SNTP) += sntp.o + COBJS-y += tftp.o + ++COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o ++COBJS-$(CONFIG_CMD_RSA) += $(RSADIR)/bigint.o $(RSADIR)/base64.o $(RSADIR)/rmd160.o $(RSADIR)/rsa.o ++ + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(COBJS)) +--- a/net/net.c ++++ b/net/net.c +@@ -95,6 +95,19 @@ + #if defined(CONFIG_CMD_DNS) + #include "dns.h" + #endif ++#if defined(CONFIG_CMD_HTTPD) ++#include "httpd.h" ++#include "uip-0.9/uipopt.h" ++#include "uip-0.9/uip.h" ++#include "uip-0.9/uip_arp.h" ++static int https_running = 0; ++int httpd_upload_complete = 0; ++unsigned char *httpd_upload_data = 0; ++extern int upload_running; ++void NetReceiveHttpd(volatile uchar * inpkt, int len); ++void NetSendHttpd(void); ++extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); ++#endif + + #if defined(CONFIG_CMD_NET) + +@@ -1310,6 +1323,13 @@ NetReceive(volatile uchar * inpkt, int l + + debug("packet received\n"); + ++#if defined(CONFIG_CMD_HTTPD) ++ if(https_running) { ++ NetReceiveHttpd(inpkt, len); ++ return; ++ } ++#endif ++ + NetRxPacket = inpkt; + NetRxPacketLen = len; + et = (Ethernet_t *)inpkt; +@@ -1952,3 +1972,161 @@ ushort getenv_VLAN(char *var) + { + return (string_to_VLAN(getenv(var))); + } ++ ++#if defined(CONFIG_CMD_HTTPD) ++ ++void ++NetSendHttpd(void) ++{ ++ volatile uchar *tmpbuf = NetTxPacket; ++ int i; ++ ++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) { ++ tmpbuf[i] = uip_buf[i]; ++ } ++ ++ for(; i < uip_len; i++) { ++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN]; ++ } ++ eth_send(NetTxPacket, uip_len); ++} ++ ++#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ ++void ++NetReceiveHttpd(volatile uchar * inpkt, int len) ++{ ++ memcpy(uip_buf, inpkt, len); ++ uip_len = len; ++ if(BUF->type == htons(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ NetSendHttpd(); ++ } ++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); ++ if(uip_len > 0) { ++ NetSendHttpd(); ++ } ++ } ++} ++ ++int ++NetLoopHttpd(void) ++{ ++ unsigned long long tout = 0; ++ bd_t *bd = gd->bd; ++ unsigned short int ip[2]; ++ ++#ifdef CONFIG_NET_MULTI ++ NetRestarted = 0; ++ NetDevExists = 0; ++#endif ++ ++ /* XXX problem with bss workaround */ ++ NetArpWaitPacketMAC = NULL; ++ NetArpWaitTxPacket = NULL; ++ NetArpWaitPacketIP = 0; ++ NetArpWaitReplyIP = 0; ++ NetArpWaitTxPacket = NULL; ++ NetTxPacket = NULL; ++ NetTryCount = 1; ++ ++ if (!NetTxPacket) { ++ int i; ++ /* ++ * Setup packet buffers, aligned correctly. ++ */ ++ NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); ++ NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; ++ for (i = 0; i < PKTBUFSRX; i++) { ++ NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN; ++ } ++ } ++ ++ if (!NetArpWaitTxPacket) { ++ NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); ++ NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; ++ NetArpWaitTxPacketSize = 0; ++ } ++ ++ eth_halt(); ++#ifdef CONFIG_NET_MULTI ++ eth_set_current(); ++#endif ++ if (eth_init(bd) < 0) { ++ eth_halt(); ++ return(-1); ++ } ++ ++restart: ++#ifdef CONFIG_NET_MULTI ++ memcpy (NetOurEther, eth_get_dev()->enetaddr, 6); ++#else ++ eth_getenv_enetaddr("ethaddr", NetOurEther); ++#endif ++ ++ NetCopyIP(&NetOurIP, &bd->bi_ip_addr); ++ NetOurGatewayIP = getenv_IPaddr ("gatewayip"); ++ NetOurSubnetMask= getenv_IPaddr ("netmask"); ++ NetOurVLAN = getenv_VLAN("vlan"); ++ NetOurNativeVLAN = getenv_VLAN("nvlan"); ++ ++ printf("starting httpd server from server %ld.%ld.%ld.%ld\n", ++ (bd->bi_ip_addr & 0xff000000) >> 24, ++ (bd->bi_ip_addr & 0x00ff0000) >> 16, ++ (bd->bi_ip_addr & 0x0000ff00) >> 8, ++ (bd->bi_ip_addr & 0x000000ff)); ++ ++ HttpdStart(); ++ ++ ip[0] = ((bd->bi_ip_addr & 0xffff0000) >> 16); ++ ip[1] = (bd->bi_ip_addr & 0x0000ffff); ++ uip_sethostaddr(ip); ++ ++ do_http_progress(HTTP_PROGRESS_START); ++ ++ https_running = 1; ++ for (;;) { ++ unsigned long long t1; ++ WATCHDOG_RESET(); ++ if(eth_rx() > 0) { ++ HttpdHandler(); ++ } else { ++ t1 = get_ticks(); ++ if(t1 - tout > 1000) { ++ do_http_progress(HTTP_PROGRESS_TIMEOUT); ++ tout = t1; ++ } ++ } ++ if(!httpd_upload_complete) ++ continue; ++ printf("Bytes transferred = %ld (%lx hex)\n", ++ NetBootFileXferSize, ++ NetBootFileXferSize); ++ eth_halt(); ++ do_http_progress(HTTP_PROGRESS_UPLOAD_READY); ++ if(do_http_upgrade(&httpd_upload_data[0], NetBootFileXferSize) == 0) { ++ do_http_progress(HTTP_PROGRESS_UGRADE_READY); ++ udelay(1000 * 10); ++ do_reset (0,0,0,0); ++ return 0; ++ } ++ break; ++ } ++ https_running = 0; ++ NetBootFileXferSize = 0; ++ httpd_upload_complete = 0; ++ upload_running = 0; ++// free(httpd_upload_data); ++ ++ do_http_progress(HTTP_PROGRESS_UGRADE_FAILED); ++ ++ goto restart; ++ ++ return -1; ++} ++ ++#endif +--- /dev/null ++++ b/net/rsa/base64.c +@@ -0,0 +1,137 @@ ++#include "base64.h" ++ ++static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++/* Note that '=' (padding) is 0 */ ++static const unsigned char fb64[256] = { ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, ++ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, ++ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ++ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, ++ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, ++ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++}; ++ ++static int encodeblock( unsigned char *in, char *out, int len ) ++{ ++ char s[3]; ++ int i; ++ ++ for (i = 0; i < len; i++) ++ s[i] = in[i]; ++ for (i = len; i < 3; i++) ++ s[i] = 0; ++ out[0] = (unsigned char)(cb64[(s[0] & 0xfc) >> 2 ]); ++ out[1] = (unsigned char)(cb64[((s[0] & 0x03) << 4) | ((s[1] & 0xf0) >> 4) ]); ++ out[2] = (unsigned char)(cb64[((s[1] & 0x0f) << 2) | ((s[2] & 0xc0) >> 6) ]); ++ out[3] = (unsigned char)(cb64[s[2] & 0x3f ]); ++ switch (len) { ++ case 1: ++ out[3] = '='; ++ case 2: ++ out[2] = '='; ++ break; ++ default: ++ break; ++ } ++ ++ return 4; ++} ++ ++static int decodeblock(char *ins, unsigned char *out, int len) ++{ ++ int i; ++ unsigned char in[4]; ++ int skip = 0; ++ ++ if (len != 4) ++ return -1; ++ for (i = 0; i < len; i++) { ++ if (ins[i] == '=') { ++ in[i] = 0; ++ skip++; ++ } else ++ in[i] = fb64[(int)(ins[i])]; ++ if (in[i] == 255) { ++ return -1; ++ } ++ } ++ out[0] = (unsigned char ) (in[0] << 2 | in[1] >> 4); ++ if (skip == 2) { ++ return 1; ++ } ++ out[1] = (unsigned char )((in[1] & 0x0f) << 4 | in[2] >> 2); ++ if (skip == 1) { ++ return 2; ++ } ++ out[2] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]); ++ ++ return 3; ++} ++ ++int B64_encode(char *source, char *destination, int size_source, int size_destination) ++{ ++ int chunks, reminder, size, d, i, size_expected; ++ char *s; ++ unsigned char *t; ++ ++ chunks = size_source / 3; ++ reminder = size_source % 3; ++ size = 0; ++ size_expected = (chunks * 4) + (reminder?(reminder + 1):0); ++ if (size_destination < ((chunks * 4) + (reminder?4:0))) { ++ return 1; ++ } ++ for (i = 0; i < chunks; i++) { ++ s = source + (i * 3); ++ t = destination + (i * 4); ++ d = encodeblock(s, t, 3); ++ if (d == -1) { ++ return 1; ++ } ++ size += d; ++ } ++ if (reminder) { ++ d = encodeblock(source + (chunks * 3), destination + (chunks * 4), reminder); ++ if (d == -1) { ++ return 1; ++ } ++ size += d; ++ } ++ return size; ++} ++ ++int B64_decode(char *source, char *destination, int size_source, int size_destination) ++{ ++ int chunks, reminder, size, d, i; ++ ++ chunks = size_source / 4; ++ reminder = size_source % 4; ++ size = 0; ++ if (reminder) { ++ return 1; ++ } ++ if (size_destination < ((chunks * 3))) { ++ printf("%d, %d\n", ++ size_destination, ((chunks * 3) + reminder)); ++ return -1; ++ } ++ for (i = 0; i < chunks; i++) { ++ d = decodeblock(source + (i * 4), destination + (i * 3), 4); ++ if (d == -1) { ++ return -1; ++ } ++ size += d; ++ } ++ return size; ++} ++ +--- /dev/null ++++ b/net/rsa/base64.h +@@ -0,0 +1,11 @@ ++#ifndef _BASE64_H_ ++#define _BASE64_H_ ++#ifdef __cplusplus ++extern "C" { ++#endif ++int B64_encode(char *source, char *destination, int size_source, int size_destination); ++int B64_decode(char *source, char *destination, int size_source, int size_destination); ++#ifdef __cplusplus ++} ++#endif ++#endif +--- /dev/null ++++ b/net/rsa/bigint.c +@@ -0,0 +1,906 @@ ++/* ++ * Copyright(C) 2006 ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2.1 of the License, or ++ * (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/** ++ * @defgroup bigint_api Big Integer API ++ * @brief The bigint implementation as used by the axTLS project. ++ * ++ * The bigint library is for RSA encryption/decryption as well as signing. ++ * This code tries to minimise use of malloc/free by maintaining a small ++ * cache. A bigint context may maintain state by being made "permanent". ++ * It be be later released with a bi_depermanent() and bi_free() call. ++ * ++ * It supports the following reduction techniques: ++ * - Classical ++ * - Barrett ++ * - Montgomery ++ * ++ * It also implements the following: ++ * - Karatsuba multiplication ++ * - Squaring ++ * - Sliding window exponentiation ++ * - Chinese Remainder Theorem (implemented in rsa.c). ++ * ++ * All the algorithms used are pretty standard, and designed for different ++ * data bus sizes. Negative numbers are not dealt with at all, so a subtraction ++ * may need to be tested for negativity. ++ * ++ * This library steals some ideas from Jef Poskanzer ++ * ++ * and GMP . It gets most of its implementation ++ * detail from "The Handbook of Applied Cryptography" ++ * ++ * @{ ++ */ ++ ++#include "bigint.h" ++#include ++#include "div64.h" ++ ++static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i); ++static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom); ++static bigint *alloc(BI_CTX *ctx, int size); ++static bigint *trim(bigint *bi); ++static void more_comps(bigint *bi, int n); ++ ++/** ++ * @brief Start a new bigint context. ++ * @return A bigint context. ++ */ ++BI_CTX *bi_initialize(void) ++{ ++ BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX)); ++ ++ ctx->active_list = NULL; ++ ctx->active_count = 0; ++ ctx->free_list = NULL; ++ ctx->free_count = 0; ++ ctx->mod_offset = 0; ++ ++ /* the radix */ ++ ctx->bi_radix = alloc(ctx, 2); ++ ctx->bi_radix->comps[0] = 0; ++ ctx->bi_radix->comps[1] = 1; ++ bi_permanent(ctx->bi_radix); ++ ++ return ctx; ++} ++ ++/** ++ * @brief Close the bigint context and free any resources. ++ * ++ * Free up any used memory - a check is done if all objects were not ++ * properly freed. ++ * @param ctx [in] The bigint session context. ++ */ ++void bi_terminate(BI_CTX *ctx) ++{ ++ bigint *p, *pn; ++ ++ bi_depermanent(ctx->bi_radix); ++ bi_free(ctx, ctx->bi_radix); ++ ++ if (ctx->active_count != 0) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return; ++ } ++ ++ for (p = ctx->free_list; p != NULL; p = pn) ++ { ++ pn = p->next; ++ free(p->comps); ++ free(p); ++ } ++ ++ free(ctx); ++} ++ ++/** ++ * @brief Increment the number of references to this object. ++ * It does not do a full copy. ++ * @param bi [in] The bigint to copy. ++ * @return A referent to the same bigint. ++ */ ++bigint *bi_copy(bigint *bi) ++{ ++ check(bi); ++ if (bi->refs != PERMANENT) ++ bi->refs++; ++ return bi; ++} ++ ++/** ++ * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it. ++ * ++ * For this object to be freed, bi_depermanent() must be called. ++ * @param bi [in] The bigint to be made permanent. ++ */ ++void bi_permanent(bigint *bi) ++{ ++ check(bi); ++ if (bi->refs != 1) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return; ++ } ++ ++ bi->refs = PERMANENT; ++} ++ ++/** ++ * @brief Take a permanent object and make it elligible for freedom. ++ * @param bi [in] The bigint to be made back to temporary. ++ */ ++void bi_depermanent(bigint *bi) ++{ ++ check(bi); ++ if (bi->refs != PERMANENT) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return; ++ } ++ ++ bi->refs = 1; ++} ++ ++/** ++ * @brief Free a bigint object so it can be used again. ++ * ++ * The memory itself it not actually freed, just tagged as being available ++ * @param ctx [in] The bigint session context. ++ * @param bi [in] The bigint to be freed. ++ */ ++void bi_free(BI_CTX *ctx, bigint *bi) ++{ ++ check(bi); ++ if (bi->refs == PERMANENT) ++ { ++ return; ++ } ++ ++ if (--bi->refs > 0) ++ { ++ return; ++ } ++ ++ bi->next = ctx->free_list; ++ ctx->free_list = bi; ++ ctx->free_count++; ++ ++ if (--ctx->active_count < 0) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return; ++ } ++} ++ ++/** ++ * @brief Convert an (unsigned) integer into a bigint. ++ * @param ctx [in] The bigint session context. ++ * @param i [in] The (unsigned) integer to be converted. ++ * ++ */ ++bigint *int_to_bi(BI_CTX *ctx, comp i) ++{ ++ bigint *biR = alloc(ctx, 1); ++ biR->comps[0] = i; ++ return biR; ++} ++ ++/** ++ * @brief Do a full copy of the bigint object. ++ * @param ctx [in] The bigint session context. ++ * @param bi [in] The bigint object to be copied. ++ */ ++bigint *bi_clone(BI_CTX *ctx, const bigint *bi) ++{ ++ bigint *biR = alloc(ctx, bi->size); ++ check(bi); ++ memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE); ++ return biR; ++} ++ ++/** ++ * @brief Perform an additon operation between two bigints. ++ * @param ctx [in] The bigint session context. ++ * @param bia [in] A bigint. ++ * @param bib [in] Another bigint. ++ * @return The result of the addition. ++ */ ++bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib) ++{ ++ int n; ++ comp carry = 0; ++ comp *pa, *pb; ++ ++ check(bia); ++ check(bib); ++ ++ if (bia->size > bib->size) ++ n = bia->size; ++ else ++ n = bib->size; ++ more_comps(bia, n+1); ++ more_comps(bib, n); ++ pa = bia->comps; ++ pb = bib->comps; ++ ++ do ++ { ++ comp sl, rl, cy1; ++ sl = *pa + *pb++; ++ rl = sl + carry; ++ cy1 = sl < *pa; ++ carry = cy1 | (rl < sl); ++ *pa++ = rl; ++ } while (--n != 0); ++ ++ *pa = carry; /* do overflow */ ++ bi_free(ctx, bib); ++ return trim(bia); ++} ++ ++/** ++ * @brief Perform a subtraction operation between two bigints. ++ * @param ctx [in] The bigint session context. ++ * @param bia [in] A bigint. ++ * @param bib [in] Another bigint. ++ * @param is_negative [out] If defined, indicates that the result was negative. ++ * is_negative may be NULL. ++ * @return The result of the subtraction. The result is always positive. ++ */ ++bigint *bi_subtract(BI_CTX *ctx, ++ bigint *bia, bigint *bib, int *is_negative) ++{ ++ int n = bia->size; ++ comp *pa, *pb, carry = 0; ++ ++ check(bia); ++ check(bib); ++ ++ more_comps(bib, n); ++ pa = bia->comps; ++ pb = bib->comps; ++ ++ do ++ { ++ comp sl, rl, cy1; ++ sl = *pa - *pb++; ++ rl = sl - carry; ++ cy1 = sl > *pa; ++ carry = cy1 | (rl > sl); ++ *pa++ = rl; ++ } while (--n != 0); ++ ++ if (is_negative) /* indicate a negative result */ ++ { ++ *is_negative = carry; ++ } ++ ++ bi_free(ctx, trim(bib)); /* put bib back to the way it was */ ++ return trim(bia); ++} ++ ++/** ++ * Perform a multiply between a bigint an an (unsigned) integer ++ */ ++static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b) ++{ ++ int j = 0, n = bia->size; ++ bigint *biR = alloc(ctx, n + 1); ++ comp carry = 0; ++ comp *r = biR->comps; ++ comp *a = bia->comps; ++ ++ check(bia); ++ ++ /* clear things to start with */ ++ memset(r, 0, ((n+1)*COMP_BYTE_SIZE)); ++ ++ do ++ { ++ long_comp tmp = *r + (long_comp)a[j]*b + carry; ++ *r++ = (comp)tmp; /* downsize */ ++ carry = (comp)(tmp >> COMP_BIT_SIZE); ++ } while (++j < n); ++ ++ *r = carry; ++ bi_free(ctx, bia); ++ return trim(biR); ++} ++ ++/** ++ * @brief Does both division and modulo calculations. ++ * ++ * Used extensively when doing classical reduction. ++ * @param ctx [in] The bigint session context. ++ * @param u [in] A bigint which is the numerator. ++ * @param v [in] Either the denominator or the modulus depending on the mode. ++ * @param is_mod [n] Determines if this is a normal division (0) or a reduction ++ * (1). ++ * @return The result of the division/reduction. ++ */ ++bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod) ++{ ++ int n = v->size, m = u->size-n; ++ int j = 0, orig_u_size = u->size; ++ uint8_t mod_offset = ctx->mod_offset; ++ comp d; ++ bigint *quotient, *tmp_u; ++ comp q_dash; ++ ++ check(u); ++ check(v); ++ ++ /* if doing reduction and we are < mod, then return mod */ ++ if (is_mod && bi_compare(v, u) > 0) ++ { ++ bi_free(ctx, v); ++ return u; ++ } ++ ++ quotient = alloc(ctx, m+1); ++ tmp_u = alloc(ctx, n+1); ++ v = trim(v); /* make sure we have no leading 0's */ ++ // d = (comp)((long_comp)COMP_RADIX/(V1+1)); ++ long_comp x = COMP_RADIX; do_div(x, V1+1); d = x; ++ ++ /* clear things to start with */ ++ memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE)); ++ ++ /* normalise */ ++ if (d > 1) ++ { ++ u = bi_int_multiply(ctx, u, d); ++ ++ if (is_mod) ++ { ++ v = ctx->bi_normalised_mod[mod_offset]; ++ } ++ else ++ { ++ v = bi_int_multiply(ctx, v, d); ++ } ++ } ++ ++ if (orig_u_size == u->size) /* new digit position u0 */ ++ { ++ more_comps(u, orig_u_size + 1); ++ } ++ ++ do ++ { ++ /* get a temporary short version of u */ ++ memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE); ++ ++ /* calculate q' */ ++ if (U(0) == V1) ++ { ++ q_dash = COMP_RADIX-1; ++ } ++ else ++ { ++ //q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1); ++ long_comp x = U(0)*COMP_RADIX + U(1); do_div(x, V1); q_dash = x; ++ ++ } ++ ++ if (v->size > 1 && V2) ++ { ++ /* we are implementing the following ++ if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - ++ q_dash*V1)*COMP_RADIX) + U(2))) ... */ ++ comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - ++ (long_comp)q_dash*V1); ++ if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2)) ++ { ++ q_dash--; ++ } ++ } ++ ++ /* multiply and subtract */ ++ if (q_dash) ++ { ++ int is_negative; ++ tmp_u = bi_subtract(ctx, tmp_u, ++ bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative); ++ more_comps(tmp_u, n+1); ++ ++ Q(j) = q_dash; ++ ++ /* add back */ ++ if (is_negative) ++ { ++ Q(j)--; ++ tmp_u = bi_add(ctx, tmp_u, bi_copy(v)); ++ /* lop off the carry */ ++ tmp_u->size--; ++ v->size--; ++ } ++ } ++ else ++ { ++ Q(j) = 0; ++ } ++ ++ /* copy back to u */ ++ memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE); ++ } while (++j <= m); ++ ++ bi_free(ctx, tmp_u); ++ bi_free(ctx, v); ++ ++ if (is_mod) /* get the remainder */ ++ { ++ bi_free(ctx, quotient); ++ return bi_int_divide(ctx, trim(u), d); ++ } ++ else /* get the quotient */ ++ { ++ bi_free(ctx, u); ++ return trim(quotient); ++ } ++} ++ ++/** ++ * Perform an integer divide on a bigint. ++ */ ++static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom) ++{ ++ int i = biR->size - 1; ++ long_comp r = 0; ++ ++ check(biR); ++ ++ do ++ { ++ r = (r<comps[i]; ++ //biR->comps[i] = (comp)(r / denom); ++ long_comp x = r; do_div(x, denom); biR->comps[i] = x; ++/* while(r > denom) ++ { ++ r -= denom; ++ }*/ ++ r%=denom; ++ } while (--i != 0); ++ ++ return trim(biR); ++} ++ ++/** ++ * @brief Allow a binary sequence to be imported as a bigint. ++ * @param ctx [in] The bigint session context. ++ * @param data [in] The data to be converted. ++ * @param size [in] The number of bytes of data. ++ * @return A bigint representing this data. ++ */ ++bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size) ++{ ++ bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE); ++ int i, j = 0, offset = 0; ++ ++ memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE); ++ ++ for (i = size-1; i >= 0; i--) ++ { ++ biR->comps[offset] += data[i] << (j*8); ++ ++ if (++j == COMP_BYTE_SIZE) ++ { ++ j = 0; ++ offset ++; ++ } ++ } ++ ++ return trim(biR); ++} ++ ++/** ++ * @brief Take a bigint and convert it into a byte sequence. ++ * ++ * This is useful after a decrypt operation. ++ * @param ctx [in] The bigint session context. ++ * @param x [in] The bigint to be converted. ++ * @param data [out] The converted data as a byte stream. ++ * @param size [in] The maximum size of the byte stream. Unused bytes will be ++ * zeroed. ++ */ ++void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size) ++{ ++ int i, j, k = size-1; ++ ++ check(x); ++ memset(data, 0, size); /* ensure all leading 0's are cleared */ ++ ++ for (i = 0; i < x->size; i++) ++ { ++ for (j = 0; j < COMP_BYTE_SIZE; j++) ++ { ++ comp mask = 0xff << (j*8); ++ int num = (x->comps[i] & mask) >> (j*8); ++ data[k--] = num; ++ ++ if (k < 0) ++ { ++ break; ++ } ++ } ++ } ++ ++ bi_free(ctx, x); ++} ++ ++/** ++ * @brief Pre-calculate some of the expensive steps in reduction. ++ * ++ * This function should only be called once (normally when a session starts). ++ * When the session is over, bi_free_mod() should be called. bi_mod_power() ++ * relies on this function being called. ++ * @param ctx [in] The bigint session context. ++ * @param bim [in] The bigint modulus that will be used. ++ * @param mod_offset [in] There are three moduluii that can be stored - the ++ * standard modulus, and it's two primes p and q. This offset refers to which ++ * modulus we are referring to. ++ * @see bi_free_mod(), bi_mod_power(). ++ */ ++void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset) ++{ ++ int k = bim->size; ++ comp d; ++// comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1)); ++ long_comp x = COMP_RADIX; do_div(x, bim->comps[k-1]+1); d = x; ++ ++ ctx->bi_mod[mod_offset] = bim; ++ bi_permanent(ctx->bi_mod[mod_offset]); ++ ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d); ++ bi_permanent(ctx->bi_normalised_mod[mod_offset]); ++} ++ ++/** ++ * @brief Used when cleaning various bigints at the end of a session. ++ * @param ctx [in] The bigint session context. ++ * @param mod_offset [in] The offset to use. ++ * @see bi_set_mod(). ++ */ ++void bi_free_mod(BI_CTX *ctx, int mod_offset) ++{ ++ bi_depermanent(ctx->bi_mod[mod_offset]); ++ bi_free(ctx, ctx->bi_mod[mod_offset]); ++ bi_depermanent(ctx->bi_normalised_mod[mod_offset]); ++ bi_free(ctx, ctx->bi_normalised_mod[mod_offset]); ++} ++ ++/** ++ * Perform a standard multiplication between two bigints. ++ */ ++static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) ++{ ++ int i, j, i_plus_j, n = bia->size, t = bib->size; ++ bigint *biR = alloc(ctx, n + t); ++ comp *sr = biR->comps; ++ comp *sa = bia->comps; ++ comp *sb = bib->comps; ++ ++ check(bia); ++ check(bib); ++ ++ /* clear things to start with */ ++ memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE)); ++ i = 0; ++ ++ do ++ { ++ comp carry = 0; ++ comp b = *sb++; ++ i_plus_j = i; ++ j = 0; ++ ++ do ++ { ++ long_comp tmp = sr[i_plus_j] + (long_comp)sa[j]*b + carry; ++ sr[i_plus_j++] = (comp)tmp; /* downsize */ ++ carry = (comp)(tmp >> COMP_BIT_SIZE); ++ } while (++j < n); ++ ++ sr[i_plus_j] = carry; ++ } while (++i < t); ++ ++ bi_free(ctx, bia); ++ bi_free(ctx, bib); ++ return trim(biR); ++} ++ ++/** ++ * @brief Perform a multiplication operation between two bigints. ++ * @param ctx [in] The bigint session context. ++ * @param bia [in] A bigint. ++ * @param bib [in] Another bigint. ++ * @return The result of the multiplication. ++ */ ++bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) ++{ ++ check(bia); ++ check(bib); ++ ++ return regular_multiply(ctx, bia, bib); ++} ++ ++ ++/** ++ * @brief Compare two bigints. ++ * @param bia [in] A bigint. ++ * @param bib [in] Another bigint. ++ * @return -1 if smaller, 1 if larger and 0 if equal. ++ */ ++int bi_compare(bigint *bia, bigint *bib) ++{ ++ int r, i; ++ ++ check(bia); ++ check(bib); ++ ++ if (bia->size > bib->size) ++ r = 1; ++ else if (bia->size < bib->size) ++ r = -1; ++ else ++ { ++ comp *a = bia->comps; ++ comp *b = bib->comps; ++ ++ /* Same number of components. Compare starting from the high end ++ * and working down. */ ++ r = 0; ++ i = bia->size - 1; ++ ++ do ++ { ++ if (a[i] > b[i]) ++ { ++ r = 1; ++ break; ++ } ++ else if (a[i] < b[i]) ++ { ++ r = -1; ++ break; ++ } ++ } while (--i >= 0); ++ } ++ ++ return r; ++} ++ ++/** ++ * Allocate and zero more components. Does not consume bi. ++ */ ++static void more_comps(bigint *bi, int n) ++{ ++ if (n > bi->max_comps) ++ { ++ if ((bi->max_comps * 2) > n) { ++ bi->max_comps = bi->max_comps * 2; ++ } else { ++ bi->max_comps = n; ++ } ++ bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE); ++ } ++ ++ if (n > bi->size) ++ { ++ memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE); ++ } ++ ++ bi->size = n; ++} ++ ++/* ++ * Make a new empty bigint. It may just use an old one if one is available. ++ * Otherwise get one of the heap. ++ */ ++static bigint *alloc(BI_CTX *ctx, int size) ++{ ++ bigint *biR; ++ ++ /* Can we recycle an old bigint? */ ++ if (ctx->free_list != NULL) ++ { ++ biR = ctx->free_list; ++ ctx->free_list = biR->next; ++ ctx->free_count--; ++ if (biR->refs != 0) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return 0; ++ } ++ ++ more_comps(biR, size); ++ } ++ else ++ { ++ /* No free bigints available - create a new one. */ ++ biR = (bigint *)malloc(sizeof(bigint)); ++ biR->comps = (comp*) malloc(size * COMP_BYTE_SIZE); ++ biR->max_comps = size; /* give some space to spare */ ++ } ++ ++ biR->size = size; ++ biR->refs = 1; ++ biR->next = NULL; ++ ctx->active_count++; ++ return biR; ++} ++ ++/* ++ * Work out the highest '1' bit in an exponent. Used when doing sliding-window ++ * exponentiation. ++ */ ++static int find_max_exp_index(bigint *biexp) ++{ ++ int i = COMP_BIT_SIZE-1; ++ comp shift = COMP_RADIX/2; ++ comp test = biexp->comps[biexp->size-1]; /* assume no leading zeroes */ ++ ++ check(biexp); ++ ++ do ++ { ++ if (test & shift) ++ { ++ return i+(biexp->size-1)*COMP_BIT_SIZE; ++ } ++ ++ shift >>= 1; ++ } while (--i != 0); ++ ++ return -1; /* error - must have been a leading 0 */ ++} ++ ++/* ++ * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window ++ * exponentiation. ++ */ ++static int exp_bit_is_one(bigint *biexp, int offset) ++{ ++ comp test = biexp->comps[offset / COMP_BIT_SIZE]; ++ int num_shifts = offset % COMP_BIT_SIZE; ++ comp shift = 1; ++ int i; ++ ++ check(biexp); ++ ++ for (i = 0; i < num_shifts; i++) ++ { ++ shift <<= 1; ++ } ++ ++ return test & shift; ++} ++ ++/* ++ * Delete any leading 0's (and allow for 0). ++ */ ++static bigint *trim(bigint *bi) ++{ ++ check(bi); ++ ++ while (bi->comps[bi->size-1] == 0 && bi->size > 1) ++ { ++ bi->size--; ++ } ++ ++ return bi; ++} ++ ++/** ++ * @brief Perform a modular exponentiation. ++ * ++ * This function requires bi_set_mod() to have been called previously. This is ++ * one of the optimisations used for performance. ++ * @param ctx [in] The bigint session context. ++ * @param bi [in] The bigint on which to perform the mod power operation. ++ * @param biexp [in] The bigint exponent. ++ * @see bi_set_mod(). ++ */ ++bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) ++{ ++ int i = find_max_exp_index(biexp), j, window_size = 1; ++ bigint *biR = int_to_bi(ctx, 1); ++ ++ check(bi); ++ check(biexp); ++ ++ ctx->g = (bigint **)malloc(sizeof(bigint *)); ++ ctx->g[0] = bi_clone(ctx, bi); ++ ctx->window = 1; ++ bi_permanent(ctx->g[0]); ++ ++ /* if sliding-window is off, then only one bit will be done at a time and ++ * will reduce to standard left-to-right exponentiation */ ++ do ++ { ++ if (exp_bit_is_one(biexp, i)) ++ { ++ int l = i-window_size+1; ++ int part_exp = 0; ++ ++ if (l < 0) /* LSB of exponent will always be 1 */ ++ { ++ l = 0; ++ } ++ else ++ { ++ while (exp_bit_is_one(biexp, l) == 0) ++ { ++ l++; /* go back up */ ++ } ++ } ++ ++ /* build up the section of the exponent */ ++ for (j = i; j >= l; j--) ++ { ++ biR = bi_residue(ctx, bi_square(ctx, biR)); ++ if (exp_bit_is_one(biexp, j)) ++ part_exp++; ++ ++ if (j != l) ++ part_exp <<= 1; ++ } ++ ++ part_exp = (part_exp-1)/2; /* adjust for array */ ++ biR = bi_residue(ctx, ++ bi_multiply(ctx, biR, ctx->g[part_exp])); ++ i = l-1; ++ } ++ else /* square it */ ++ { ++ biR = bi_residue(ctx, bi_square(ctx, biR)); ++ i--; ++ } ++ } while (i >= 0); ++ ++ /* cleanup */ ++ for (i = 0; i < ctx->window; i++) ++ { ++ bi_depermanent(ctx->g[i]); ++ bi_free(ctx, ctx->g[i]); ++ } ++ ++ free(ctx->g); ++ bi_free(ctx, bi); ++ bi_free(ctx, biexp); ++ return biR; ++} ++ ++/** @} */ +--- /dev/null ++++ b/net/rsa/bigint.h +@@ -0,0 +1,73 @@ ++/* ++ * Copyright(C) 2006 ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Trimmed down from axTLS ++ * ++ * $Id: bigint.h 392 2007-06-25 16:24:51Z pablo.martin $ ++ * ++ */ ++ ++#ifndef BIGINT_HEADER ++#define BIGINT_HEADER ++ ++#define CONFIG_BIGINT_CLASSICAL 1 ++ ++#define SOCKET_READ(A,B,C) read(A,B,C) ++#define SOCKET_WRITE(A,B,C) write(A,B,C) ++#define SOCKET_CLOSE(A) close(A) ++#define TTY_FLUSH() ++ ++#include "bigint_impl.h" ++ ++#ifndef CONFIG_BIGINT_CHECK_ON ++#define check(A) /**< disappears in normal production mode */ ++#endif ++BI_CTX *bi_initialize(void); ++void bi_terminate(BI_CTX *ctx); ++void bi_permanent(bigint *bi); ++void bi_depermanent(bigint *bi); ++void bi_free(BI_CTX *ctx, bigint *bi); ++bigint *bi_copy(bigint *bi); ++bigint *bi_clone(BI_CTX *ctx, const bigint *bi); ++void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size); ++bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len); ++bigint *int_to_bi(BI_CTX *ctx, comp i); ++ ++/* the functions that actually do something interesting */ ++bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib); ++bigint *bi_subtract(BI_CTX *ctx, bigint *bia, ++ bigint *bib, int *is_negative); ++bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod); ++bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib); ++bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp); ++bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp); ++int bi_compare(bigint *bia, bigint *bib); ++void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset); ++void bi_free_mod(BI_CTX *ctx, int mod_offset); ++ ++/** ++ * @def bi_mod ++ * Find the residue of B. bi_set_mod() must be called before hand. ++ */ ++#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1) ++ ++#define bi_residue(A, B) bi_mod(A, B) ++ ++#define bi_square(A, B) bi_multiply(A, bi_copy(B), B) ++ ++#endif ++ +--- /dev/null ++++ b/net/rsa/bigint_impl.h +@@ -0,0 +1,109 @@ ++/* ++ * Copyright(C) 2006 ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2.1 of the License, or ++ * (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef BIGINT_IMPL_HEADER ++#define BIGINT_IMPL_HEADER ++ ++#include ++#include ++ ++/* Maintain a number of precomputed variables when doing reduction */ ++#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */ ++#ifdef CONFIG_BIGINT_CRT ++#define BIGINT_P_OFFSET 1 /**< p modulo offset. */ ++#define BIGINT_Q_OFFSET 2 /**< q module offset. */ ++#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */ ++#else ++#define BIGINT_NUM_MODS 1 ++#endif ++ ++/* Architecture specific functions for big ints */ ++// #ifdef WIN32 ++// #define COMP_RADIX 4294967296i64 ++// #define COMP_BIG_MSB 0x8000000000000000i64 ++// #else ++#define COMP_RADIX 4294967296ULL /**< Max component + 1 */ ++#define COMP_BIG_MSB 0x8000000000000000ULL /**< (Max dbl comp + 1)/ 2 */ ++//#endif ++#define COMP_BIT_SIZE 32 /**< Number of bits in a component. */ ++#define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */ ++#define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */ ++ ++typedef uint32_t comp; /**< A single precision component. */ ++typedef uint64_t long_comp; /**< A double precision component. */ ++typedef int64_t slong_comp; /**< A signed double precision component. */ ++ ++/** ++ * @struct _bigint ++ * @brief A big integer basic object ++ */ ++struct _bigint ++{ ++ struct _bigint* next; /**< The next bigint in the cache. */ ++ short size; /**< The number of components in this bigint. */ ++ short max_comps; /**< The heapsize allocated for this bigint */ ++ int refs; /**< An internal reference count. */ ++ comp* comps; /**< A ptr to the actual component data */ ++}; ++ ++typedef struct _bigint bigint; /**< An alias for _bigint */ ++ ++/** ++ * Maintains the state of the cache, and a number of variables used in ++ * reduction. ++ */ ++typedef struct /**< A big integer "session" context. */ ++{ ++ bigint *active_list; /**< Bigints currently used. */ ++ bigint *free_list; /**< Bigints not used. */ ++ bigint *bi_radix; /**< The radix used. */ ++ bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */ ++ ++#if defined(CONFIG_BIGINT_MONTGOMERY) ++ bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */ ++ bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */ ++ comp N0_dash[BIGINT_NUM_MODS]; ++#elif defined(CONFIG_BIGINT_BARRETT) ++ bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */ ++#endif ++ bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */ ++ bigint **g; /**< Used by sliding-window. */ ++ int window; /**< The size of the sliding window */ ++ ++ int active_count; /**< Number of active bigints. */ ++ int free_count; /**< Number of free bigints. */ ++ ++#ifdef CONFIG_BIGINT_MONTGOMERY ++ uint8_t use_classical; /**< Use classical reduction. */ ++#endif ++ uint8_t mod_offset; /**< The mod offset we are using */ ++} BI_CTX; ++ ++#if 0 ++#define max(a,b) ((a)>(b)?(a):(b)) /**< Find the maximum of 2 numbers. */ ++#define min(a,b) ((a)<(b)?(a):(b)) /**< Find the minimum of 2 numbers. */ ++#endif ++ ++#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */ ++ ++#define V1 v->comps[v->size-1] /**< v1 for division */ ++#define V2 v->comps[v->size-2] /**< v2 for division */ ++#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */ ++#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */ ++ ++#endif +--- /dev/null ++++ b/net/rsa/div64.h +@@ -0,0 +1,113 @@ ++/* ++ * Copyright (C) 2000, 2004 Maciej W. Rozycki ++ * Copyright (C) 2003 Ralf Baechle ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ */ ++#ifndef _ASM_DIV64_H ++#define _ASM_DIV64_H ++ ++#if (_MIPS_SZLONG == 32) ++ ++#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) ++#define GCC_REG_ACCUM "$0" ++#else ++#define GCC_REG_ACCUM "accum" ++#endif ++ ++ ++//#include ++ ++/* ++ * No traps on overflows for any of these... ++ */ ++ ++#define do_div64_32(res, high, low, base) ({ \ ++ unsigned long __quot, __mod; \ ++ unsigned long __cf, __tmp, __tmp2, __i; \ ++ \ ++ __asm__(".set push\n\t" \ ++ ".set noat\n\t" \ ++ ".set noreorder\n\t" \ ++ "move %2, $0\n\t" \ ++ "move %3, $0\n\t" \ ++ "b 1f\n\t" \ ++ " li %4, 0x21\n" \ ++ "0:\n\t" \ ++ "sll $1, %0, 0x1\n\t" \ ++ "srl %3, %0, 0x1f\n\t" \ ++ "or %0, $1, %5\n\t" \ ++ "sll %1, %1, 0x1\n\t" \ ++ "sll %2, %2, 0x1\n" \ ++ "1:\n\t" \ ++ "bnez %3, 2f\n\t" \ ++ " sltu %5, %0, %z6\n\t" \ ++ "bnez %5, 3f\n" \ ++ "2:\n\t" \ ++ " addiu %4, %4, -1\n\t" \ ++ "subu %0, %0, %z6\n\t" \ ++ "addiu %2, %2, 1\n" \ ++ "3:\n\t" \ ++ "bnez %4, 0b\n\t" \ ++ " srl %5, %1, 0x1f\n\t" \ ++ ".set pop" \ ++ : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ ++ "=&r" (__i), "=&r" (__tmp2) \ ++ : "Jr" (base), "0" (high), "1" (low)); \ ++ \ ++ (res) = __quot; \ ++ __mod; }) ++ ++#define do_div(n, base) ({ \ ++ unsigned long long __quot; \ ++ unsigned long __mod; \ ++ unsigned long long __div; \ ++ unsigned long __upper, __low, __high, __base; \ ++ \ ++ __div = (n); \ ++ __base = (base); \ ++ \ ++ __high = __div >> 32; \ ++ __low = __div; \ ++ __upper = __high; \ ++ \ ++ if (__high) \ ++ __asm__("divu $0, %z2, %z3" \ ++ : "=h" (__upper), "=l" (__high) \ ++ : "Jr" (__high), "Jr" (__base) \ ++ : GCC_REG_ACCUM); \ ++ \ ++ __mod = do_div64_32(__low, __upper, __low, __base); \ ++ \ ++ __quot = __high; \ ++ __quot = __quot << 32 | __low; \ ++ (n) = __quot; \ ++ __mod; }) ++#endif /* (_MIPS_SZLONG == 32) */ ++ ++#if (_MIPS_SZLONG == 64) ++ ++/* ++ * Hey, we're already 64-bit, no ++ * need to play games.. ++ */ ++#define do_div(n, base) ({ \ ++ unsigned long __quot; \ ++ unsigned int __mod; \ ++ unsigned long __div; \ ++ unsigned int __base; \ ++ \ ++ __div = (n); \ ++ __base = (base); \ ++ \ ++ __mod = __div % __base; \ ++ __quot = __div / __base; \ ++ \ ++ (n) = __quot; \ ++ __mod; }) ++ ++#endif /* (_MIPS_SZLONG == 64) */ ++ ++#endif /* _ASM_DIV64_H */ +--- /dev/null ++++ b/net/rsa/dump_key.c +@@ -0,0 +1,29 @@ ++#include ++#include ++#include ++#include ++#include ++ ++int main(int argc, char **argv) ++{ ++ FILE *fp = fopen("public_fon_rsa_key_6.pem", "r"); ++ struct stat s; ++ unsigned char *b; ++ int i; ++ if(!fp) ++ return 1; ++ stat("public_fon_rsa_key_6.pem", &s); ++ b = malloc(s.st_size); ++ fread(b, s.st_size, 1, fp); ++ fclose(fp); ++ printf("unsigned char public_key[] = {\n\t"); ++ for(i = 0;i < s.st_size; i++) ++ { ++ printf("0x%02X,", b[i]); ++ if(i%16 == 15) ++ printf("\n\t"); ++ } ++ printf("};\n"); ++// printf("\n%d %d\n", i, s.st_size); ++ return 0; ++} +--- /dev/null ++++ b/net/rsa/foncheckrsa.c +@@ -0,0 +1,79 @@ ++/* ++ * RSA + RIPEMD160 signature verification command ++ * ++ * Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * Created: 20060728 Pablo Martín Medrano ++ * ++ * $Id: foncheckrsa.c 332 2007-05-02 09:45:54Z pablo.martin $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "fonrsa.h" ++ ++int main(int argc, char **argv) ++{ ++ int fd, i; ++ FONRSA_ERROR fonrsa_error; ++ void *handle; ++ ++ if (argc != 4) { ++ fprintf(stderr, " Usage: foncheckrsa [public_key.der] [signature] [file]\n"); ++ fprintf(stderr, " Pablo Martín Medrano \n"); ++ fprintf(stderr, " RIPEMD-160 software written by Antoon Bosselaers,\n"); ++ fprintf(stderr, " available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/.\n"); ++ fprintf(stderr, " Uses the axTLS library bigint implementation (libfonrsa)\n"); ++ fprintf(stderr, " http://www.leroc.com.au/axTLS/\n"); ++ return -1; ++ } ++ /* Check the existence of input files */ ++ for (i = 1; i < 4; i++) { ++ if ((fd = open(argv[i], O_RDONLY)) == -1) { ++ fprintf(stderr, "Error: opening \"%s\": %s\n", argv[i], ++ strerror(errno)); ++ fprintf(stderr, "Bailing out..."); ++ exit(-2); ++ } ++ close(fd); ++ } ++ handle = FR_init(argv[1]); ++ if (handle == NULL) { ++ printf("Error loading keys in %s\n", argv[1]); ++ return 1; ++ } ++ fonrsa_error = FR_verify_file(handle, argv[3], argv[2]); ++ FR_end(handle); ++ switch (fonrsa_error) { ++ case FONRSA_OK: ++ printf("Verified OK\n"); ++ return 0; ++ case FONRSA_VERIFICATION_FAILURE: ++ printf("Verification failure\n"); ++ return 1; ++ default: ++ printf("Verification error\n"); ++ return -1; ++ } ++ return -1; ++} ++ +--- /dev/null ++++ b/net/rsa/fonrsa.c +@@ -0,0 +1,584 @@ ++/* ++ * FONSM RSA handling library ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Created: 20070306 Pablo Martin Medrano ++ * ++ * Based on axTLS ++ * ++ * $Id: fonrsa.c 405 2007-09-19 15:26:17Z jesus.pico $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rmd160.h" ++#include "bigint.h" ++#include "fonrsa.h" ++#include "base64.h" ++ ++typedef struct { ++ uint8_t *buffer; ++ size_t size; ++} DER_key; ++ ++typedef struct { ++ bigint *m; /* modulus */ ++ bigint *e; /* public exponent */ ++ int num_octets; ++ BI_CTX *bi_ctx; /* big integer handle */ ++} RSA_parameters; ++ ++typedef struct { ++ DER_key *derkey; ++ RSA_parameters *rsaparms; ++} RSA; ++ ++static uint8_t *CH_load_raw_file(char *filename, size_t *size); ++static DER_key *CH_load_der_key(char *filename); ++static void CH_free_der_key(DER_key *key); ++static int asn1_get_public_key(const uint8_t *buf, int len, RSA_parameters **rsa_parameters); ++void CH_pub_key_new(RSA_parameters **rsa_parameters, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len); ++int CH_decrypt(RSA_parameters *rsa, uint8_t *buffer_in, uint8_t *buffer_out); ++byte *RMDbinary(char *fname); ++int CH_get_rmd160_hash_from_signature(byte *hash, char *signature_file, char *public_key_file); ++static unsigned char *load_file_in_buffer(char *path, int *size); ++static int save_file_from_buffer(char *path, unsigned char *buffer, int size); ++int ExtractPadding(uint8_t* OutputBuffer, uint8_t* InputBuffer, int LengthOfInputBuffer); ++ ++#define RMDsize 160 /* A RIPEMD-160 hash has 160 bits */ ++ ++/* ++ * returns RMD(message in file fname) fname is read as binary data. ++ * non-reentrant ++ */ ++byte *RMDbinary(char *fname) ++{ ++ FILE *mf; /* pointer to file */ ++ byte data[1024]; /* contains current mess. block */ ++ dword nbytes; /* length of this block */ ++ dword MDbuf[RMDsize / 32]; /* contains (A, B, C, D(, E)) */ ++ static byte hashcode[RMDsize / 8]; /* for final hash-value */ ++ dword X[16]; /* current 16-word chunk */ ++ unsigned int i, j; /* counters */ ++ dword length[2]; /* length in bytes of message */ ++ dword offset; /* # of unprocessed bytes at */ ++ /* call of MDfinish */ ++ ++ /* initialize */ ++ if ((mf = fopen(fname, "rb")) == NULL) { ++ fprintf(stderr, "\nRMDbinary: cannot open file \"%s\".\n", ++ fname); ++ exit(1); ++ } ++ MDinit(MDbuf); ++ length[0] = 0; ++ length[1] = 0; ++ while ((nbytes = fread(data, 1, 1024, mf)) != 0) { ++ /* process all complete blocks */ ++ for (i = 0; i < (nbytes >> 6); i++) { ++ for (j = 0; j < 16; j++) ++ X[j] = BYTES_TO_DWORD(data + 64 * i + 4 * j); ++ compress(MDbuf, X); ++ } ++ /* update length[] */ ++ if (length[0] + nbytes < length[0]) ++ length[1]++; /* overflow to msb of length */ ++ length[0] += nbytes; ++ } ++ /* finish: */ ++ offset = length[0] & 0x3C0; /* extract bytes 6 to 10 inclusive */ ++ MDfinish(MDbuf, data + offset, length[0], length[1]); ++ ++ for (i = 0; i < RMDsize / 8; i += 4) { ++ hashcode[i] = MDbuf[i >> 2]; ++ hashcode[i + 1] = (MDbuf[i >> 2] >> 8); ++ hashcode[i + 2] = (MDbuf[i >> 2] >> 16); ++ hashcode[i + 3] = (MDbuf[i >> 2] >> 24); ++ } ++ fclose(mf); ++ ++ return (byte *) hashcode; ++} ++byte *RMDbinary_buffer(char *buffer, int size_buffer) ++{ ++ return NULL; ++} ++ ++/* ++ * Extracts the RMD 160 hash from the signature file ++ */ ++int CH_get_rmd160_hash_from_signature(byte *hash, char *signature_file, char *public_key_file) ++{ ++ RSA_parameters *rsa_parameters; ++ DER_key *derkey; ++ uint8_t *signature; ++ size_t signature_size; ++ uint8_t *decrypted; ++ ++ signature = CH_load_raw_file(signature_file, &signature_size); ++ if ((signature == NULL)||(signature_size != 512)) { ++ fprintf(stderr, "Error: Loading signature key '%s'\n", signature_file); ++ exit(-1); ++ } ++ derkey = CH_load_der_key(public_key_file); ++ if (derkey == NULL) { ++ fprintf(stderr, "Error: opening DER key file '%s'\n", public_key_file); ++ exit(-1); ++ } ++ if ((asn1_get_public_key(derkey->buffer, derkey->size, &rsa_parameters)) != 0) { ++ fprintf(stderr, "Error: Extracting public key from DER file\n"); ++ exit(-1); ++ } ++ CH_free_der_key(derkey); ++ if (rsa_parameters->num_octets != 512) ++ fprintf(stderr, "Error: The RSA public key size is not 4096 bits %d\n", rsa_parameters->num_octets); ++ decrypted = (uint8_t *)malloc(rsa_parameters->num_octets); ++ if (CH_decrypt(rsa_parameters, signature, decrypted)) { ++ fprintf(stderr, "Error: Decrypting signature\n"); ++ exit(-1); ++ } ++ memcpy(hash, decrypted + 492, 20); ++ free(decrypted); ++ free(signature); ++ return 0; ++} ++ ++/* ++ * Decrypts the signature buffer using the rsa public key loaded ++ */ ++int CH_decrypt(RSA_parameters *rsa, uint8_t *buffer_in, uint8_t *buffer_out) ++{ ++ bigint *dat_bi; ++ bigint *decrypted_bi; ++ int byte_size; ++ ++ byte_size = rsa->num_octets; ++ dat_bi = bi_import(rsa->bi_ctx, buffer_in, byte_size); ++ rsa->bi_ctx->mod_offset = BIGINT_M_OFFSET; ++ bi_copy(rsa->m); ++ decrypted_bi = bi_mod_power(rsa->bi_ctx, dat_bi, rsa->e); ++ bi_export(rsa->bi_ctx, decrypted_bi, buffer_out, byte_size); ++ return 0; ++} ++/* ++ * Loads a file in a uint8_t buffer ++ */ ++static uint8_t *CH_load_raw_file(char *filename, size_t *size) ++{ ++ struct stat st; ++ int fd; ++ ssize_t br; ++ uint8_t *ret; ++ ++ if ((stat(filename, &st)) == -1) ++ return NULL; ++ if ((ret = (uint8_t *)malloc(st.st_size)) == NULL) ++ return NULL; ++ fd = open(filename, O_RDONLY); ++ if (fd == -1) { ++ free(ret); ++ return NULL; ++ } ++ br = read(fd, ret, st.st_size); ++ close(fd); ++ if (br != st.st_size) { ++ free(ret); ++ return NULL; ++ } ++ *size = st.st_size; ++ return ret; ++} ++/* ++ * Loads a .der file in a buffer ++ */ ++static DER_key *CH_load_der_key(char *filename) ++{ ++ DER_key *ret; ++ ++ if ((ret = (DER_key *)malloc(sizeof(DER_key))) == NULL) ++ return NULL; ++ if ((ret->buffer = CH_load_raw_file(filename, &(ret->size))) == NULL) { ++ free(ret); ++ return NULL; ++ } ++ return ret; ++} ++/* ++ * CH_load_pem_key ++ */ ++static DER_key *CH_load_pem_key(char *filename) ++{ ++ DER_key *ret; ++ uint8_t *buffer; ++ char *b64,*p,*t; ++ char key[1024]; ++ size_t filesize; ++ int size; ++ ++ if ((ret = (DER_key *)malloc(sizeof(DER_key))) == NULL) ++ return NULL; ++ if ((buffer = CH_load_raw_file(filename, &filesize)) == NULL) { ++ free(ret); ++ return NULL; ++ } ++ p = (char *)buffer; ++ while ((*p != '\n') && (*p != '\0')) ++ p++; ++ if (*p == '\0') { ++ free(ret); ++ return NULL; ++ } ++ p++; ++ b64 = t = p; ++ while((p - b64) <= filesize) { ++ if ((*p == '-')) { ++ break; ++ } else if ((*p != '\n') && (*p != ' ') && (*p != '\t')) { ++ *t = *p; ++ t++; ++ } ++ p++; ++ } ++ *t = '\0'; ++ size = B64_decode(b64, key, strlen(b64), 1024); ++ if (size < 0) { ++ free(buffer); ++ free(ret); ++ return NULL; ++ } ++ free(buffer); ++ ret->buffer = (char *)malloc(size); ++ ret->size = size; ++ memcpy((void *)ret->buffer, (void *)key, size); ++ return ret; ++} ++ ++/* ++ * CH_free_der_key ++ */ ++static void CH_free_der_key(DER_key *key) ++{ ++ free(key->buffer); ++ free(key); ++} ++ ++/* ++ * Get the public key specifics from an ASN.1 encoded file ++ * A function lacking in the exported axTLS API ++ * ++ * This is a really weird hack that only works with RSA public key ++ * files ++ */ ++static int asn1_get_public_key(const uint8_t *buf, int len, RSA_parameters **rsa_parameters) ++{ ++ uint8_t *modulus, *pub_exp; ++ int mod_len, pub_len; ++ ++ pub_len = 3; ++ mod_len = len - 37; ++ if (buf[0] != 0x30) { ++ return -1; ++ } ++ ++ pub_exp = (uint8_t *)malloc(3); ++ modulus = (uint8_t *)malloc(mod_len); ++ memcpy(modulus, buf + 32 , mod_len); ++ memcpy(pub_exp, buf + 34 + mod_len, 3); ++ if (mod_len <= 0 || pub_len <= 0 ) ++ return -1; ++ CH_pub_key_new(rsa_parameters, modulus, mod_len, pub_exp, pub_len); ++ ++ free(modulus); ++ free(pub_exp); ++ return 0; ++} ++ ++/* ++ * Similar to RSA_pub_key_new, rewritten to make this program depend only on bi module ++ */ ++void CH_pub_key_new(RSA_parameters **rsa, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len) ++{ ++ RSA_parameters *rsa_parameters; ++ ++ BI_CTX *bi_ctx = bi_initialize(); ++ *rsa = (RSA_parameters *)calloc(1, sizeof(RSA_parameters)); ++ rsa_parameters = *rsa; ++ rsa_parameters->bi_ctx = bi_ctx; ++ rsa_parameters->num_octets = (mod_len & 0xFFF0); ++ rsa_parameters->m = bi_import(bi_ctx, modulus, mod_len); ++ bi_set_mod(bi_ctx, rsa_parameters->m, BIGINT_M_OFFSET); ++ rsa_parameters->e = bi_import(bi_ctx, pub_exp, pub_len); ++ bi_permanent(rsa_parameters->e); ++} ++ ++static unsigned char *load_file_in_buffer(char *path, int *size) ++{ ++ unsigned char *buffer; ++ struct stat st; ++ int fd; ++ ++ if (stat(path, &st)) ++ return NULL; ++ buffer = (unsigned char *)malloc(st.st_size); ++ if (buffer == NULL) ++ return NULL; ++ if ((fd = open(path, O_RDONLY)) == -1) { ++ free(buffer); ++ return NULL; ++ } ++ if (read(fd, (void *)buffer,st.st_size) != (ssize_t)st.st_size) { ++ free(buffer); ++ close(fd); ++ return NULL; ++ } ++ *size = (int)st.st_size; ++ close(fd); ++ return buffer; ++} ++ ++static int save_file_from_buffer(char *path, unsigned char *buffer, int size) ++{ ++ int fd; ++ ++ if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) == -1) ++ return -1; ++ if (write(fd, buffer, (size_t)size) != ((ssize_t)size)) { ++ close(fd); ++ return -1; ++ } ++ close(fd); ++ return 0; ++} ++ ++/* FR_init */ ++void *FR_init(char *public_key_path) ++{ ++ DER_key *derkey; ++ RSA_parameters *rsa_parameters; ++ char *ending; ++ ++ ending = public_key_path + strlen(public_key_path) - 3; ++ if (!strcmp(ending, "der")) ++ derkey = CH_load_der_key(public_key_path); ++ else if (!strcmp(ending, "pem")) ++ derkey = CH_load_pem_key(public_key_path); ++ else { ++ fprintf(stderr, "Error: unknown key format\n"); ++ exit(-1); ++ } ++ if (derkey == NULL) { ++ fprintf(stderr, "Error: opening key file '%s'\n", public_key_path); ++ exit(-1); ++ } ++ if ((asn1_get_public_key(derkey->buffer, derkey->size, &rsa_parameters)) != 0) { ++ fprintf(stderr, "Error: Extracting public key from file\n"); ++ exit(-1); ++ } ++ CH_free_der_key(derkey); ++ return (void *)rsa_parameters; ++} ++ ++/* FR_end */ ++FONRSA_ERROR FR_end(void *handle) ++{ ++ RSA_parameters *rsa_parameters = (RSA_parameters *)handle; ++ ++ free(rsa_parameters); ++ return FONRSA_OK; ++} ++ ++/* FR_decrypt_buffer */ ++FONRSA_ERROR FR_decrypt_buffer(void *handler, unsigned char *cryptext, int cryptext_size, ++ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size) ++{ ++ RSA_parameters *rsaparms = (RSA_parameters *)handler; ++ ++ if (cryptext_size != rsaparms->num_octets) { ++ return FONRSA_SIZE; ++ } ++ if (plaintext_buffer_size < cryptext_size) { ++ return FONRSA_SIZE; ++ } ++ if (CH_decrypt(rsaparms, (uint8_t *)cryptext, (uint8_t *)plaintext)) { ++ return FONRSA_DECRYPT; ++ } ++ *plaintext_size = cryptext_size; ++ return FONRSA_OK; ++} ++ ++FONRSA_ERROR FR_decrypt_buffer_v2(void *handler, unsigned char *cryptext, int cryptext_size, ++ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size) ++{ ++ unsigned char* AuxBuffer; ++ int AuxSize; ++ ++ AuxBuffer = (unsigned char*)malloc(cryptext_size); ++ ++ RSA_parameters *rsaparms = (RSA_parameters *)handler; ++ ++ if (cryptext_size != rsaparms->num_octets) { ++ return FONRSA_SIZE; ++ } ++ if (plaintext_buffer_size < cryptext_size) { ++ return FONRSA_SIZE; ++ } ++ if (CH_decrypt(rsaparms, (uint8_t *)cryptext, (uint8_t *)AuxBuffer)) { ++ return FONRSA_DECRYPT; ++ } ++ if ((AuxSize = ExtractPadding((uint8_t*)plaintext, (uint8_t*)AuxBuffer, cryptext_size)) < 0) ++ { ++ printf("Incorrect Padding decrypting buffer"); ++ return FONRSA_DECRYPT; ++ } ++ *plaintext_size = AuxSize; ++ return FONRSA_OK; ++} ++ ++/* ++ * ++ * Implementation of PKCS 1.5 padding, borrowed from ++ * Tom's code (public domain) ++ */ ++ ++/* Standalone FR_verify_file */ ++FONRSA_ERROR FR_verify_file(void *handler, char *file_path, char *signature_file_path) ++{ ++ int j; ++ byte *hashcode; ++ byte hash[20]; ++ uint8_t *decrypted; ++ RSA_parameters *rsa_parameters = (RSA_parameters *)handler; ++ char *signature_buffer; ++ int signature_size; ++ ++ /* Calculates the RIPEMD-160 hash of the file */ ++ hashcode = RMDbinary (file_path); ++ /* Decrypts the signature file using the RSA public key */ ++ signature_buffer = load_file_in_buffer(signature_file_path, &signature_size); ++ if (signature_buffer == NULL) ++ return FONRSA_OPENKEY; ++ ++ if (rsa_parameters->num_octets != signature_size) ++ return FONRSA_SIZE; ++ decrypted = (uint8_t *)malloc(rsa_parameters->num_octets); ++ if (CH_decrypt(rsa_parameters, signature_buffer, decrypted)) { ++ fprintf(stderr, "Error: Decrypting signature\n"); ++ exit(-1); ++ } ++ memcpy(hash, decrypted + 492, 20); ++ free(decrypted); ++ free(signature_buffer); ++ for (j = 0; j < RMDsize/8; j++) { ++ if (hash[j] != hashcode[j]) ++ return FONRSA_VERIFICATION_FAILURE; ++ } ++ return FONRSA_OK; ++} ++ ++/* FR_decrypt_file */ ++FONRSA_ERROR FR_decrypt_file(void *handle, char *crypted_file_path, char *plaintext_file_path) ++{ ++ int size; ++ FONRSA_ERROR ret; ++ char *filebuffer; ++ char crypted[1024]; ++ int crypted_size; ++ ++ if ((filebuffer = load_file_in_buffer(crypted_file_path, &size)) == NULL) { ++ return FONRSA_LOADFILE; ++ } ++ ++ ret = FR_decrypt_buffer(handle, filebuffer, size, crypted, 1024, &crypted_size); ++ if (ret != FONRSA_OK) { ++ free(filebuffer); ++ return ret; ++ } ++ free(filebuffer); ++ ++ if (save_file_from_buffer(plaintext_file_path, crypted, crypted_size)) { ++ printf("Error writing %lu bytes into %s", crypted_size, plaintext_file_path); ++ return FONRSA_SAVEFILE; ++ } ++ return FONRSA_OK; ++} ++ ++int ExtractPadding(uint8_t* OutputBuffer, uint8_t* InputBuffer, int LengthOfInputBuffer) ++{ ++ int i; ++ ++ //First typical checks... ++ if (LengthOfInputBuffer < MINIMUM_PADING_BYTES_PKCS_1_5) ++ { ++ fprintf(stderr, "Error:ExtractPadding: Error, Length of input buffer is too short.\n"); ++ return -1; ++ } ++ else if((InputBuffer[0] != 0) || (InputBuffer[1] > 2)) //Necessary header of Padding... ++ { ++ fprintf(stderr, "Error:ExtractPadding: Error, Padding header is incorrect.\n"); ++ return -1; ++ } ++ for (i=2; i < LengthOfInputBuffer; i++) //Variable size of non-zero padding.... ++ { ++ if (InputBuffer[i] == 0) break; //This is the end of Padding. ++ } ++ //We need to evaluate if there is an existing message... ++ if (i < LengthOfInputBuffer - 2) ++ {//Ok, Padding is extracted... copying the message and finishing... ++ memcpy(OutputBuffer, &(InputBuffer[i + 1]), LengthOfInputBuffer - (i + 1)); ++ return LengthOfInputBuffer - (i + 1); ++ } ++ //If we have reached to this point, then an error has occurred... ++ return -1; ++} ++ ++#ifdef __MAINTEST__ ++int main(int argc, char **argv) ++{ ++ void *handle = NULL; ++ FONRSA_ERROR ret; ++ char *filebuffer = NULL; ++ char crypted[1024]; ++ int size, crypted_size; ++ ++ if (argc != 4) { ++ printf("Usage: %s \n", argv[0]); ++ return 1; ++ } ++ ++ handle = FR_init(argv[1]); ++ if (handle == NULL) { ++ printf("Error loading keys\n"); ++ return 1; ++ } ++ ret = FR_decrypt_file(handle, argv[2], argv[3]); ++ if (ret != FONRSA_OK) { ++ printf("FR_decrypt_file returns %d\n", ret); ++ } ++ FR_end(handle); ++ return (int)ret; ++} ++ ++#endif ++ ++ +--- /dev/null ++++ b/net/rsa/fonrsa.h +@@ -0,0 +1,53 @@ ++/* ++ * FONSM RSA handling library, used by fonsmcd and foncheckrsa ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Created: 20070306 Pablo Martin Medrano ++ * ++ * $Id: fonrsa.h 404 2007-09-17 10:41:31Z jesus.pico $ ++ */ ++#ifndef _FONRSA_H ++#define _FONRSA_H ++ ++#define MINIMUM_PADING_BYTES_PKCS_1_5 3 ++ ++typedef enum { ++ FONRSA_OK = 0, ++ FONRSA_VERIFICATION_FAILURE = 1, ++ FONRSA_OPENKEY = 2, ++ FONRSA_SIZE = 3, ++ FONRSA_LOADFILE = 4, ++ FONRSA_CRYPT = 5, ++ FONRSA_DECRYPT = 6, ++ FONRSA_SAVEFILE = 7, ++ FONRSA_NOSYS = 8, ++ FONRSA_VERIFY = 9 ++} FONRSA_ERROR; ++ ++void *FR_init(char *public_key_path); ++FONRSA_ERROR FR_end(void *handle); ++FONRSA_ERROR FR_decrypt_buffer(void *handler, unsigned char *cryptext, int cryptext_size, ++ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size); ++FONRSA_ERROR FR_decrypt_buffer_v2(void *handler, unsigned char *cryptext, int cryptext_size, ++ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size); ++FONRSA_ERROR FR_verify_file(void *handler, char *file_path, char *signature_file_path); ++FONRSA_ERROR FR_decrypt_file(void *handler, char *crypted_file_path, char *plaintext_file_path); ++ ++#endif ++ ++ +--- /dev/null ++++ b/net/rsa/log.c +@@ -0,0 +1,138 @@ ++/* ++ * Fonsm log module. Used inside the fonsm backend module and on the client. ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * Created: 20070202 Pablo Martin Medrano ++ * ++ * $Id: log.c 392 2007-06-25 16:24:51Z pablo.martin $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#ifndef WIN32 ++#include ++#endif ++#include "log.h" ++ ++#define MAX_SESSION_PREFIX 256 ++ ++typedef struct { ++ char domain[256]; ++ LG_LEVEL watermark; ++ int mode; ++ LG_log_function_pointer function; ++} ST_fslog; ++ ++static ST_fslog fslog; ++static void LG_log_string(LG_LEVEL level, const char *message); ++ ++/*! ++ \brief Starts the log subsystem, redirecting glog() to stderr/syslog depending ++ on mode ++ \retval FSLOG_ERROR : FSLOG_OK if everything goes well ++ \param lg : handle that will be returned ++ \param ident : program identifier, any string ++ \param low_watermark : if the log level is less than this value, it will not be logged ++ \param mode : FSLOG_MODE_SYSLOG (log to syslog) or FSLOG_MODE_STDERR (log to stderr) ++*/ ++FSLOG_ERROR LG_start(const char *domain, LG_LEVEL watermark, int mode, ++ LG_log_function_pointer log_function, int facility) ++{ ++#ifndef WIN32 ++ strncpy(fslog.domain, domain, MAX_LG_DOMAIN); ++ fslog.domain[MAX_LG_DOMAIN - 1] = '\0'; ++ fslog.watermark = watermark; ++ fslog.mode = mode; ++ fslog.function = log_function?log_function:LG_log_string; ++ if (fslog.mode & LG_SYSLOG) ++ openlog(domain, LOG_NDELAY, facility); ++ return FSLOG_OK; ++#else ++ return FSLOG_OK; ++#endif ++} ++ ++/*! ++ \brief Set the low watermark ++ \retval FSLOG_ERROR : FSLOG_OK ++ \param lg : log handle ++ \param low_watermark : new watermark ++*/ ++FSLOG_ERROR LG_set_loglevel(LG_LEVEL watermark) ++{ ++ fslog.watermark = watermark; ++ return FSLOG_OK; ++} ++ ++/*! ++ \brief Ends the log subsystem, unregisteing glog handle ++ \retval FSLOG_ERROR : FSLOG_OK if everything goes well ++ \param handle : log handle to free ++*/ ++FSLOG_ERROR LG_end(void) ++{ ++#ifndef WIN32 ++ if (fslog.mode & LG_SYSLOG) ++ closelog(); ++#endif ++ return FSLOG_OK; ++} ++ ++ ++void LG_log(LG_LEVEL loglevel, const char *message, ...) ++{ ++#ifndef WIN32 ++ va_list ap; ++ char buffer[4096]; ++ int n; ++ ++ va_start(ap, message); ++ n = vsnprintf(buffer, MAX_LOG_STRING, message, ap); ++ va_end(ap); ++ if (n > -1 && n < MAX_LOG_STRING) ++ fslog.function(loglevel, buffer); ++ else ++ fon_critical("%s: Message too big to be logged", __FUNCTION__); ++#else ++ return; ++#endif ++} ++ ++/* Default log function (when mode is LG_SYSLOG or LG_STDERR) */ ++static void LG_log_string(LG_LEVEL level, const char *message) ++{ ++#ifndef WIN32 ++ static struct { ++ int syslog_level; ++ char *log_string; ++ } fonlog_to_syslog[] = { ++ [LG_DEBUG] = {LOG_ERR, "DEBUG"}, ++ [LG_MESSAGE] = {LOG_ERR, "MESSAGE"}, ++ [LG_WARNING] = {LOG_ERR, "WARNING"}, ++ [LG_CRITICAL] = {LOG_ERR, "CRITICAL"}, ++ [LG_ERROR] = {LOG_ERR, "ERROR"} ++ }; ++ ++ if (level < fslog.watermark) ++ return; ++ if (fslog.mode & LG_SYSLOG) { ++ if (level == LG_MESSAGE) { ++ syslog(LOG_INFO, "%s", message); ++ } else { ++ syslog(fonlog_to_syslog[level].syslog_level, "%s: %s", fonlog_to_syslog[level].log_string, message); ++ } ++ } ++ if (fslog.mode & LG_STDERR) { ++ fprintf(stderr, "%s[%d]: %8.8s: %s\n", fslog.domain, ++ getpid(), fonlog_to_syslog[level].log_string, ++ message); ++ } ++#else ++ /* FIXE: todo */ ++ return; ++#endif ++} ++ +--- /dev/null ++++ b/net/rsa/log.h +@@ -0,0 +1,77 @@ ++/* ++ * Fonsm log module. Used inside the fonsm backend module and on the client. ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * Created: 20070202 Pablo Martin Medrano ++ * ++ * $Id: log.h 379 2007-05-28 09:17:48Z pablo.martin $ ++ */ ++#ifndef _LOG_H ++#define _LOG_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++ ++typedef enum { ++ FSLOG_OK = 0, ++ FSLOG_UNKNOWN = -1 ++} FSLOG_ERROR; ++ ++ ++typedef void * LG_HANDLE; ++ ++typedef enum { ++ LG_DEBUG = 0, ++ LG_MESSAGE = 1, ++ LG_INFO = 2, ++ LG_WARNING = 3, ++ LG_CRITICAL = 4, ++ LG_ERROR = 5 ++} LG_LEVEL; ++ ++#define LG_SYSLOG 0x01 ++#define LG_STDERR 0x02 ++#define LG_CUSTOM 0x04 ++ ++#define MAX_LG_DOMAIN 256 ++#define MAX_LOG_STRING 4096 ++ ++#ifndef NDEBUG ++#ifndef LOGPRINTF ++#define fon_debug(...) LG_log (LG_DEBUG, __VA_ARGS__) ++#else ++#define fon_debug(...) { printf("DEBUG: "); printf(__VA_ARGS__); printf("\n"); } ++#endif ++#else ++/* fon_debug evaluates to nothing when NDEBUG is defined */ ++#define fon_debug(...) ++#endif ++#ifndef LOGPRINTF ++#define fon_message(...) LG_log (LG_MESSAGE, __VA_ARGS__) ++#define fon_warning(...) LG_log (LG_WARNING, __VA_ARGS__) ++#define fon_critical(...) LG_log (LG_CRITICAL, __VA_ARGS__) ++#define fon_error(...) LG_log (LG_ERROR, __VA_ARGS__) ++#else ++#define fon_message(...) { printf("MESSAGE: "); printf(__VA_ARGS__); printf("\n"); } ++#define fon_warning(...) { printf("WARNING: "); printf(__VA_ARGS__); printf("\n"); } ++#define fon_critical(...) { printf("CRITICAL: "); printf(__VA_ARGS__); printf("\n"); } ++#define fon_error(...) { printf("ERROR: "); printf(__VA_ARGS__); printf("\n"); } ++#endif ++ ++typedef void (*LG_log_function_pointer)(LG_LEVEL level, const char *message); ++ ++FSLOG_ERROR LG_start(const char *domain, LG_LEVEL watermark, int mode, LG_log_function_pointer log_function, int facility); ++FSLOG_ERROR LG_set_loglevel(LG_LEVEL watermark); ++FSLOG_ERROR LG_end(void); ++void LG_log(LG_LEVEL loglevel, const char *message, ...); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif ++ +--- /dev/null ++++ b/net/rsa/Makefile +@@ -0,0 +1,31 @@ ++# ++# FONRSA & FONSIGN libraries unit testing ++# ++# This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++# ++# Execute in this directory ++# ++# Created: 20070422 Pablo Martin Medrano ++# ++# $Id: Makefile 389 2007-06-11 08:29:56Z pablo.martin $ ++# ++# FIXME: Put this in the main Makefile.am ++# ++all: fonsign dump_key ++ ++fonsign: ++ gcc -g sign_openssl.c -D__MAINTEST__ -o fonsign -lssl ++ ++dump_key: ++ gcc -o dump_key dump_key.c ++ ./dump_key > public_key.h ++ ++foncheckrsa: ++ gcc -g bigint.c fonrsa.c rmd160.c foncheckrsa.c base64.c log.c -o foncheckrsa ++ ++#private_fon_rsa_key.pem: ++# openssl genrsa -out private_fon_rsa_key.pem 4096 ++# openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem ++ ++clean: ++ rm fonsign dump_key +--- /dev/null ++++ b/net/rsa/public_key.h +@@ -0,0 +1,52 @@ ++unsigned char public_key[] = { ++ 0x2D,0x2D,0x2D,0x2D,0x2D,0x42,0x45,0x47,0x49,0x4E,0x20,0x50,0x55,0x42,0x4C,0x49, ++ 0x43,0x20,0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A,0x4D,0x49,0x49,0x43,0x49, ++ 0x6A,0x41,0x4E,0x42,0x67,0x6B,0x71,0x68,0x6B,0x69,0x47,0x39,0x77,0x30,0x42,0x41, ++ 0x51,0x45,0x46,0x41,0x41,0x4F,0x43,0x41,0x67,0x38,0x41,0x4D,0x49,0x49,0x43,0x43, ++ 0x67,0x4B,0x43,0x41,0x67,0x45,0x41,0x34,0x4C,0x42,0x76,0x59,0x43,0x4B,0x38,0x38, ++ 0x6D,0x75,0x57,0x61,0x73,0x31,0x4F,0x53,0x73,0x71,0x30,0x0A,0x38,0x39,0x38,0x79, ++ 0x76,0x54,0x4B,0x71,0x41,0x6E,0x4F,0x37,0x78,0x2F,0x44,0x53,0x57,0x72,0x46,0x53, ++ 0x30,0x42,0x72,0x47,0x53,0x51,0x31,0x52,0x69,0x44,0x39,0x55,0x62,0x78,0x77,0x6F, ++ 0x64,0x76,0x36,0x65,0x51,0x4B,0x55,0x30,0x67,0x36,0x52,0x6B,0x2F,0x39,0x54,0x70, ++ 0x4C,0x6E,0x4F,0x2F,0x76,0x51,0x4B,0x70,0x69,0x41,0x30,0x30,0x0A,0x2B,0x32,0x59, ++ 0x30,0x74,0x6B,0x4C,0x39,0x73,0x6A,0x37,0x64,0x33,0x57,0x4B,0x47,0x39,0x62,0x6A, ++ 0x64,0x51,0x58,0x2F,0x43,0x49,0x35,0x57,0x46,0x42,0x42,0x64,0x77,0x57,0x73,0x74, ++ 0x4D,0x43,0x38,0x77,0x74,0x4C,0x6A,0x6A,0x45,0x59,0x79,0x43,0x58,0x46,0x32,0x31, ++ 0x30,0x39,0x7A,0x31,0x47,0x54,0x4C,0x73,0x53,0x44,0x34,0x57,0x4F,0x0A,0x45,0x50, ++ 0x6D,0x45,0x37,0x34,0x63,0x6E,0x6F,0x35,0x78,0x53,0x43,0x71,0x71,0x33,0x74,0x54, ++ 0x49,0x6D,0x38,0x50,0x78,0x49,0x77,0x54,0x46,0x6D,0x46,0x6F,0x6D,0x6A,0x76,0x31, ++ 0x4F,0x56,0x50,0x32,0x73,0x42,0x49,0x70,0x35,0x4E,0x2B,0x59,0x6F,0x56,0x61,0x53, ++ 0x58,0x6A,0x47,0x66,0x4E,0x63,0x54,0x36,0x4E,0x6B,0x39,0x76,0x6B,0x56,0x0A,0x57, ++ 0x69,0x67,0x39,0x30,0x71,0x50,0x4E,0x4C,0x58,0x6E,0x39,0x39,0x50,0x78,0x48,0x61, ++ 0x49,0x31,0x36,0x52,0x7A,0x78,0x48,0x4C,0x39,0x54,0x42,0x2B,0x50,0x43,0x33,0x68, ++ 0x33,0x61,0x58,0x33,0x71,0x57,0x30,0x4B,0x4C,0x4A,0x41,0x66,0x6F,0x35,0x70,0x48, ++ 0x6C,0x39,0x79,0x75,0x55,0x70,0x37,0x66,0x46,0x65,0x6A,0x4A,0x2B,0x41,0x58,0x0A, ++ 0x51,0x4F,0x4A,0x62,0x53,0x45,0x67,0x56,0x74,0x76,0x72,0x68,0x44,0x39,0x73,0x55, ++ 0x6D,0x4B,0x30,0x74,0x36,0x63,0x51,0x44,0x65,0x32,0x32,0x4E,0x4E,0x6E,0x77,0x37, ++ 0x43,0x4F,0x4F,0x61,0x59,0x49,0x57,0x55,0x55,0x6A,0x79,0x6A,0x68,0x35,0x50,0x4B, ++ 0x64,0x64,0x45,0x4B,0x5A,0x38,0x68,0x62,0x62,0x47,0x65,0x61,0x5A,0x4A,0x6F,0x76, ++ 0x0A,0x63,0x6F,0x51,0x64,0x55,0x56,0x51,0x6D,0x71,0x44,0x53,0x2B,0x6B,0x63,0x2F, ++ 0x41,0x51,0x6C,0x65,0x55,0x36,0x68,0x51,0x6A,0x63,0x55,0x4C,0x57,0x44,0x6B,0x4E, ++ 0x2F,0x6F,0x4F,0x6C,0x33,0x43,0x53,0x65,0x70,0x67,0x54,0x37,0x6B,0x67,0x73,0x52, ++ 0x63,0x63,0x47,0x74,0x66,0x4B,0x65,0x37,0x77,0x4D,0x70,0x35,0x66,0x59,0x4A,0x2B, ++ 0x41,0x0A,0x43,0x46,0x44,0x41,0x6F,0x4C,0x6E,0x58,0x4E,0x6A,0x4E,0x56,0x6C,0x65, ++ 0x73,0x43,0x6B,0x78,0x74,0x6A,0x62,0x4C,0x62,0x49,0x72,0x66,0x32,0x6E,0x43,0x62, ++ 0x32,0x61,0x4D,0x65,0x64,0x31,0x5A,0x48,0x4E,0x4A,0x51,0x75,0x6F,0x4E,0x58,0x67, ++ 0x72,0x43,0x41,0x44,0x31,0x71,0x2B,0x58,0x6E,0x66,0x77,0x63,0x69,0x6D,0x57,0x50, ++ 0x64,0x51,0x0A,0x44,0x59,0x6A,0x6D,0x65,0x44,0x70,0x35,0x77,0x36,0x41,0x4A,0x33, ++ 0x2F,0x35,0x59,0x39,0x55,0x74,0x78,0x47,0x34,0x72,0x51,0x72,0x61,0x68,0x78,0x53, ++ 0x42,0x77,0x43,0x4B,0x57,0x39,0x4B,0x79,0x53,0x31,0x71,0x53,0x76,0x73,0x37,0x7A, ++ 0x59,0x2F,0x52,0x59,0x37,0x4A,0x66,0x36,0x63,0x56,0x6B,0x54,0x43,0x78,0x69,0x33, ++ 0x7A,0x32,0x53,0x0A,0x50,0x46,0x33,0x51,0x64,0x6B,0x30,0x50,0x44,0x2F,0x73,0x2B, ++ 0x6B,0x77,0x39,0x71,0x4F,0x4E,0x79,0x69,0x33,0x67,0x6E,0x61,0x42,0x46,0x6E,0x54, ++ 0x77,0x48,0x7A,0x59,0x69,0x77,0x34,0x2F,0x77,0x6A,0x46,0x33,0x64,0x47,0x68,0x47, ++ 0x4E,0x6B,0x78,0x36,0x70,0x63,0x4E,0x4F,0x52,0x55,0x46,0x4E,0x65,0x4F,0x7A,0x59, ++ 0x76,0x39,0x6F,0x6A,0x0A,0x51,0x59,0x70,0x73,0x55,0x31,0x33,0x6A,0x6D,0x30,0x33, ++ 0x42,0x6F,0x45,0x2B,0x42,0x31,0x64,0x38,0x50,0x47,0x75,0x57,0x2B,0x49,0x7A,0x2F, ++ 0x41,0x4F,0x44,0x7A,0x6B,0x6F,0x56,0x6B,0x39,0x2B,0x57,0x79,0x49,0x33,0x37,0x50, ++ 0x30,0x53,0x7A,0x47,0x4B,0x72,0x2B,0x53,0x33,0x72,0x72,0x74,0x61,0x50,0x6C,0x41, ++ 0x70,0x71,0x4B,0x48,0x55,0x0A,0x6E,0x64,0x35,0x6C,0x30,0x63,0x76,0x75,0x59,0x66, ++ 0x31,0x4C,0x37,0x45,0x52,0x75,0x49,0x58,0x64,0x47,0x4C,0x6A,0x30,0x43,0x41,0x77, ++ 0x45,0x41,0x41,0x51,0x3D,0x3D,0x0A,0x2D,0x2D,0x2D,0x2D,0x2D,0x45,0x4E,0x44,0x20, ++ 0x50,0x55,0x42,0x4C,0x49,0x43,0x20,0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A, ++ }; +--- /dev/null ++++ b/net/rsa/rmd160.c +@@ -0,0 +1,292 @@ ++/********************************************************************\ ++ * ++ * FILE: rmd160.c ++ * ++ * CONTENTS: A sample C-implementation of the RIPEMD-160 ++ * hash-function. ++ * TARGET: any computer with an ANSI C compiler ++ * ++ * AUTHOR: Antoon Bosselaers, ESAT-COSIC ++ * DATE: 1 March 1996 ++ * VERSION: 1.0 ++ * ++ * Copyright (c) Katholieke Universiteit Leuven ++ * 1996, All Rights Reserved ++ * ++ * Conditions for use of the RIPEMD-160 Software ++ * ++ * The RIPEMD-160 software is freely available for use under the terms and ++ * conditions described hereunder, which shall be deemed to be accepted by ++ * any user of the software and applicable on any use of the software: ++ * ++ * 1. K.U.Leuven Department of Electrical Engineering-ESAT/COSIC shall for ++ * all purposes be considered the owner of the RIPEMD-160 software and of ++ * all copyright, trade secret, patent or other intellectual property ++ * rights therein. ++ * 2. The RIPEMD-160 software is provided on an "as is" basis without ++ * warranty of any sort, express or implied. K.U.Leuven makes no ++ * representation that the use of the software will not infringe any ++ * patent or proprietary right of third parties. User will indemnify ++ * K.U.Leuven and hold K.U.Leuven harmless from any claims or liabilities ++ * which may arise as a result of its use of the software. In no ++ * circumstances K.U.Leuven R&D will be held liable for any deficiency, ++ * fault or other mishappening with regard to the use or performance of ++ * the software. ++ * 3. User agrees to give due credit to K.U.Leuven in scientific publications ++ * or communications in relation with the use of the RIPEMD-160 software ++ * as follows: RIPEMD-160 software written by Antoon Bosselaers, ++ * available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/. ++ * ++\********************************************************************/ ++ ++/* header files */ ++#include ++#include "rmd160.h" ++ ++/********************************************************************/ ++ ++void MDinit(dword *MDbuf) ++{ ++ MDbuf[0] = 0x67452301UL; ++ MDbuf[1] = 0xefcdab89UL; ++ MDbuf[2] = 0x98badcfeUL; ++ MDbuf[3] = 0x10325476UL; ++ MDbuf[4] = 0xc3d2e1f0UL; ++ ++ return; ++} ++ ++/********************************************************************/ ++ ++void compress(dword *MDbuf, dword *X) ++{ ++ dword aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], ++ dd = MDbuf[3], ee = MDbuf[4]; ++ dword aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], ++ ddd = MDbuf[3], eee = MDbuf[4]; ++ ++ /* round 1 */ ++ FF(aa, bb, cc, dd, ee, X[ 0], 11); ++ FF(ee, aa, bb, cc, dd, X[ 1], 14); ++ FF(dd, ee, aa, bb, cc, X[ 2], 15); ++ FF(cc, dd, ee, aa, bb, X[ 3], 12); ++ FF(bb, cc, dd, ee, aa, X[ 4], 5); ++ FF(aa, bb, cc, dd, ee, X[ 5], 8); ++ FF(ee, aa, bb, cc, dd, X[ 6], 7); ++ FF(dd, ee, aa, bb, cc, X[ 7], 9); ++ FF(cc, dd, ee, aa, bb, X[ 8], 11); ++ FF(bb, cc, dd, ee, aa, X[ 9], 13); ++ FF(aa, bb, cc, dd, ee, X[10], 14); ++ FF(ee, aa, bb, cc, dd, X[11], 15); ++ FF(dd, ee, aa, bb, cc, X[12], 6); ++ FF(cc, dd, ee, aa, bb, X[13], 7); ++ FF(bb, cc, dd, ee, aa, X[14], 9); ++ FF(aa, bb, cc, dd, ee, X[15], 8); ++ ++ /* round 2 */ ++ GG(ee, aa, bb, cc, dd, X[ 7], 7); ++ GG(dd, ee, aa, bb, cc, X[ 4], 6); ++ GG(cc, dd, ee, aa, bb, X[13], 8); ++ GG(bb, cc, dd, ee, aa, X[ 1], 13); ++ GG(aa, bb, cc, dd, ee, X[10], 11); ++ GG(ee, aa, bb, cc, dd, X[ 6], 9); ++ GG(dd, ee, aa, bb, cc, X[15], 7); ++ GG(cc, dd, ee, aa, bb, X[ 3], 15); ++ GG(bb, cc, dd, ee, aa, X[12], 7); ++ GG(aa, bb, cc, dd, ee, X[ 0], 12); ++ GG(ee, aa, bb, cc, dd, X[ 9], 15); ++ GG(dd, ee, aa, bb, cc, X[ 5], 9); ++ GG(cc, dd, ee, aa, bb, X[ 2], 11); ++ GG(bb, cc, dd, ee, aa, X[14], 7); ++ GG(aa, bb, cc, dd, ee, X[11], 13); ++ GG(ee, aa, bb, cc, dd, X[ 8], 12); ++ ++ /* round 3 */ ++ HH(dd, ee, aa, bb, cc, X[ 3], 11); ++ HH(cc, dd, ee, aa, bb, X[10], 13); ++ HH(bb, cc, dd, ee, aa, X[14], 6); ++ HH(aa, bb, cc, dd, ee, X[ 4], 7); ++ HH(ee, aa, bb, cc, dd, X[ 9], 14); ++ HH(dd, ee, aa, bb, cc, X[15], 9); ++ HH(cc, dd, ee, aa, bb, X[ 8], 13); ++ HH(bb, cc, dd, ee, aa, X[ 1], 15); ++ HH(aa, bb, cc, dd, ee, X[ 2], 14); ++ HH(ee, aa, bb, cc, dd, X[ 7], 8); ++ HH(dd, ee, aa, bb, cc, X[ 0], 13); ++ HH(cc, dd, ee, aa, bb, X[ 6], 6); ++ HH(bb, cc, dd, ee, aa, X[13], 5); ++ HH(aa, bb, cc, dd, ee, X[11], 12); ++ HH(ee, aa, bb, cc, dd, X[ 5], 7); ++ HH(dd, ee, aa, bb, cc, X[12], 5); ++ ++ /* round 4 */ ++ II(cc, dd, ee, aa, bb, X[ 1], 11); ++ II(bb, cc, dd, ee, aa, X[ 9], 12); ++ II(aa, bb, cc, dd, ee, X[11], 14); ++ II(ee, aa, bb, cc, dd, X[10], 15); ++ II(dd, ee, aa, bb, cc, X[ 0], 14); ++ II(cc, dd, ee, aa, bb, X[ 8], 15); ++ II(bb, cc, dd, ee, aa, X[12], 9); ++ II(aa, bb, cc, dd, ee, X[ 4], 8); ++ II(ee, aa, bb, cc, dd, X[13], 9); ++ II(dd, ee, aa, bb, cc, X[ 3], 14); ++ II(cc, dd, ee, aa, bb, X[ 7], 5); ++ II(bb, cc, dd, ee, aa, X[15], 6); ++ II(aa, bb, cc, dd, ee, X[14], 8); ++ II(ee, aa, bb, cc, dd, X[ 5], 6); ++ II(dd, ee, aa, bb, cc, X[ 6], 5); ++ II(cc, dd, ee, aa, bb, X[ 2], 12); ++ ++ /* round 5 */ ++ JJ(bb, cc, dd, ee, aa, X[ 4], 9); ++ JJ(aa, bb, cc, dd, ee, X[ 0], 15); ++ JJ(ee, aa, bb, cc, dd, X[ 5], 5); ++ JJ(dd, ee, aa, bb, cc, X[ 9], 11); ++ JJ(cc, dd, ee, aa, bb, X[ 7], 6); ++ JJ(bb, cc, dd, ee, aa, X[12], 8); ++ JJ(aa, bb, cc, dd, ee, X[ 2], 13); ++ JJ(ee, aa, bb, cc, dd, X[10], 12); ++ JJ(dd, ee, aa, bb, cc, X[14], 5); ++ JJ(cc, dd, ee, aa, bb, X[ 1], 12); ++ JJ(bb, cc, dd, ee, aa, X[ 3], 13); ++ JJ(aa, bb, cc, dd, ee, X[ 8], 14); ++ JJ(ee, aa, bb, cc, dd, X[11], 11); ++ JJ(dd, ee, aa, bb, cc, X[ 6], 8); ++ JJ(cc, dd, ee, aa, bb, X[15], 5); ++ JJ(bb, cc, dd, ee, aa, X[13], 6); ++ ++ /* parallel round 1 */ ++ JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); ++ JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); ++ JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); ++ JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); ++ JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); ++ JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); ++ JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); ++ JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); ++ JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); ++ JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); ++ JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); ++ JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); ++ JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); ++ JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); ++ JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); ++ JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); ++ ++ /* parallel round 2 */ ++ III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); ++ III(ddd, eee, aaa, bbb, ccc, X[11], 13); ++ III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); ++ III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); ++ III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); ++ III(eee, aaa, bbb, ccc, ddd, X[13], 8); ++ III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); ++ III(ccc, ddd, eee, aaa, bbb, X[10], 11); ++ III(bbb, ccc, ddd, eee, aaa, X[14], 7); ++ III(aaa, bbb, ccc, ddd, eee, X[15], 7); ++ III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); ++ III(ddd, eee, aaa, bbb, ccc, X[12], 7); ++ III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); ++ III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); ++ III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); ++ III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); ++ ++ /* parallel round 3 */ ++ HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); ++ HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); ++ HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); ++ HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); ++ HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); ++ HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); ++ HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); ++ HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); ++ HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); ++ HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); ++ HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); ++ HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); ++ HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); ++ HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); ++ HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); ++ HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); ++ ++ /* parallel round 4 */ ++ GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); ++ GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); ++ GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); ++ GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); ++ GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); ++ GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); ++ GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); ++ GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); ++ GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); ++ GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); ++ GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); ++ GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); ++ GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); ++ GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); ++ GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); ++ GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); ++ ++ /* parallel round 5 */ ++ FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); ++ FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); ++ FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); ++ FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); ++ FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); ++ FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); ++ FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); ++ FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); ++ FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); ++ FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); ++ FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); ++ FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); ++ FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); ++ FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); ++ FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); ++ FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); ++ ++ /* combine results */ ++ ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ ++ MDbuf[1] = MDbuf[2] + dd + eee; ++ MDbuf[2] = MDbuf[3] + ee + aaa; ++ MDbuf[3] = MDbuf[4] + aa + bbb; ++ MDbuf[4] = MDbuf[0] + bb + ccc; ++ MDbuf[0] = ddd; ++ ++ return; ++} ++ ++/********************************************************************/ ++ ++void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen) ++{ ++ unsigned int i; /* counter */ ++ dword X[16]; /* message words */ ++ ++ memset(X, 0, 16*sizeof(dword)); ++ ++ /* put bytes from strptr into X */ ++ for (i=0; i<(lswlen&63); i++) { ++ /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ ++ X[i>>2] ^= (dword) *strptr++ << (8 * (i&3)); ++ } ++ ++ /* append the bit m_n == 1 */ ++ X[(lswlen>>2)&15] ^= (dword)1 << (8*(lswlen&3) + 7); ++ ++ if ((lswlen & 63) > 55) { ++ /* length goes to next block */ ++ compress(MDbuf, X); ++ memset(X, 0, 16*sizeof(dword)); ++ } ++ ++ /* append length in bits*/ ++ X[14] = lswlen << 3; ++ X[15] = (lswlen >> 29) | (mswlen << 3); ++ compress(MDbuf, X); ++ ++ return; ++} ++ ++/************************ end of file rmd160.c **********************/ ++ +--- /dev/null ++++ b/net/rsa/rmd160.h +@@ -0,0 +1,154 @@ ++/********************************************************************\ ++ * ++ * FILE: rmd160.h ++ * ++ * CONTENTS: Header file for a sample C-implementation of the ++ * RIPEMD-160 hash-function. ++ * TARGET: any computer with an ANSI C compiler ++ * ++ * AUTHOR: Antoon Bosselaers, ESAT-COSIC ++ * DATE: 1 March 1996 ++ * VERSION: 1.0 ++ * ++ * Copyright (c) Katholieke Universiteit Leuven ++ * 1996, All Rights Reserved ++ * ++ * Conditions for use of the RIPEMD-160 Software ++ * ++ * The RIPEMD-160 software is freely available for use under the terms and ++ * conditions described hereunder, which shall be deemed to be accepted by ++ * any user of the software and applicable on any use of the software: ++ * ++ * 1. K.U.Leuven Department of Electrical Engineering-ESAT/COSIC shall for ++ * all purposes be considered the owner of the RIPEMD-160 software and of ++ * all copyright, trade secret, patent or other intellectual property ++ * rights therein. ++ * 2. The RIPEMD-160 software is provided on an "as is" basis without ++ * warranty of any sort, express or implied. K.U.Leuven makes no ++ * representation that the use of the software will not infringe any ++ * patent or proprietary right of third parties. User will indemnify ++ * K.U.Leuven and hold K.U.Leuven harmless from any claims or liabilities ++ * which may arise as a result of its use of the software. In no ++ * circumstances K.U.Leuven R&D will be held liable for any deficiency, ++ * fault or other mishappening with regard to the use or performance of ++ * the software. ++ * 3. User agrees to give due credit to K.U.Leuven in scientific publications ++ * or communications in relation with the use of the RIPEMD-160 software ++ * as follows: RIPEMD-160 software written by Antoon Bosselaers, ++ * available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/. ++ * ++\********************************************************************/ ++ ++#ifndef RMD160H /* make sure this file is read only once */ ++#define RMD160H ++ ++/********************************************************************/ ++ ++/* typedef 8 and 32 bit types, resp. */ ++/* adapt these, if necessary, ++ for your operating system and compiler */ ++typedef unsigned char byte; ++typedef unsigned long dword; ++ ++ ++/********************************************************************/ ++ ++/* macro definitions */ ++ ++/* collect four bytes into one word: */ ++#define BYTES_TO_DWORD(strptr) \ ++ (((dword) *((strptr)+3) << 24) | \ ++ ((dword) *((strptr)+2) << 16) | \ ++ ((dword) *((strptr)+1) << 8) | \ ++ ((dword) *(strptr))) ++ ++/* ROL(x, n) cyclically rotates x over n bits to the left */ ++/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ ++#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) ++ ++/* the five basic functions F(), G() and H() */ ++#define F(x, y, z) ((x) ^ (y) ^ (z)) ++#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) ++#define H(x, y, z) (((x) | ~(y)) ^ (z)) ++#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) ++#define J(x, y, z) ((x) ^ ((y) | ~(z))) ++ ++/* the ten basic operations FF() through III() */ ++#define FF(a, b, c, d, e, x, s) {\ ++ (a) += F((b), (c), (d)) + (x);\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define GG(a, b, c, d, e, x, s) {\ ++ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define HH(a, b, c, d, e, x, s) {\ ++ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define II(a, b, c, d, e, x, s) {\ ++ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define JJ(a, b, c, d, e, x, s) {\ ++ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define FFF(a, b, c, d, e, x, s) {\ ++ (a) += F((b), (c), (d)) + (x);\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define GGG(a, b, c, d, e, x, s) {\ ++ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define HHH(a, b, c, d, e, x, s) {\ ++ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define III(a, b, c, d, e, x, s) {\ ++ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define JJJ(a, b, c, d, e, x, s) {\ ++ (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++ ++/********************************************************************/ ++ ++/* function prototypes */ ++ ++void MDinit(dword *MDbuf); ++/* ++ * initializes MDbuffer to "magic constants" ++ */ ++ ++void compress(dword *MDbuf, dword *X); ++/* ++ * the compression function. ++ * transforms MDbuf using message bytes X[0] through X[15] ++ */ ++ ++void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen); ++/* ++ * puts bytes from strptr into X and pad out; appends length ++ * and finally, compresses the last block(s) ++ * note: length in bits == 8 * (lswlen + 2^32 mswlen). ++ * note: there are (lswlen mod 64) bytes left in strptr. ++ */ ++ ++#endif /* RMD160H */ ++ ++/*********************** end of file rmd160.h ***********************/ ++ +--- /dev/null ++++ b/net/rsa/rsa.c +@@ -0,0 +1,303 @@ ++/* ++ * FONSM RSA handling library ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Created: 20070306 Pablo Martin Medrano ++ * ++ * Based on axTLS ++ * ++ * $Id: fonrsa.c 405 2007-09-19 15:26:17Z jesus.pico $ ++ */ ++#include ++#include ++#include "rsa.h" ++#include "rmd160.h" ++#include "bigint.h" ++#include "base64.h" ++ ++#include "public_key.h" ++ ++#define RMDsize 160 /* A RIPEMD-160 hash has 160 bits */ ++ ++typedef struct { ++ uint8_t *buffer; ++ size_t size; ++} DER_key; ++ ++typedef struct { ++ bigint *m; /* modulus */ ++ bigint *e; /* public exponent */ ++ int num_octets; ++ BI_CTX *bi_ctx; /* big integer handle */ ++} RSA_parameters; ++ ++typedef struct { ++ DER_key *derkey; ++ RSA_parameters *rsaparms; ++} RSA; ++ ++static void CH_free_der_key(DER_key *key) ++{ ++ free(key->buffer); ++ free(key); ++} ++ ++int CH_decrypt(RSA_parameters *rsa, uint8_t *buffer_in, uint8_t *buffer_out) ++{ ++ bigint *dat_bi; ++ bigint *decrypted_bi; ++ int byte_size; ++ ++ byte_size = rsa->num_octets; ++ dat_bi = bi_import(rsa->bi_ctx, buffer_in, byte_size); ++ rsa->bi_ctx->mod_offset = BIGINT_M_OFFSET; ++ bi_copy(rsa->m); ++ decrypted_bi = bi_mod_power(rsa->bi_ctx, dat_bi, rsa->e); ++ bi_export(rsa->bi_ctx, decrypted_bi, buffer_out, byte_size); ++ return 0; ++} ++ ++byte *RMDbinary(char *buffer, int len) ++{ ++ byte data[1024]; /* contains current mess. block */ ++ dword nbytes; /* length of this block */ ++ dword MDbuf[RMDsize / 32]; /* contains (A, B, C, D(, E)) */ ++ static byte hashcode[RMDsize / 8]; /* for final hash-value */ ++ dword X[16]; /* current 16-word chunk */ ++ unsigned int i, j; /* counters */ ++ dword length[2]; /* length in bytes of message */ ++ dword offset; /* # of unprocessed bytes at */ ++ /* call of MDfinish */ ++ int total = len; ++ char *tmp = buffer; ++ MDinit(MDbuf); ++ length[0] = 0; ++ length[1] = 0; ++ while ( len) { ++ memcpy(data, tmp, 1024); ++ if(len > 1024) ++ { ++ nbytes = 1024; ++ len -= 1024; ++ tmp += 1024; ++ } else { ++ nbytes = len; ++ len = 0; ++ } ++ /* process all complete blocks */ ++ for (i = 0; i < (nbytes >> 6); i++) { ++ for (j = 0; j < 16; j++) ++ X[j] = BYTES_TO_DWORD(data + 64 * i + 4 * j); ++ compress(MDbuf, X); ++ } ++ /* update length[] */ ++ if (length[0] + nbytes < length[0]) ++ length[1]++; /* overflow to msb of length */ ++ length[0] += nbytes; ++ } ++ /* finish: */ ++ offset = length[0] & 0x3C0; /* extract bytes 6 to 10 inclusive */ ++ MDfinish(MDbuf, data + offset, length[0], length[1]); ++ ++ for (i = 0; i < RMDsize / 8; i += 4) { ++ hashcode[i] = MDbuf[i >> 2]; ++ hashcode[i + 1] = (MDbuf[i >> 2] >> 8); ++ hashcode[i + 2] = (MDbuf[i >> 2] >> 16); ++ hashcode[i + 3] = (MDbuf[i >> 2] >> 24); ++ } ++ ++ return (byte *) hashcode; ++} ++ ++static DER_key *CH_load_pem_key(void) ++{ ++ DER_key *ret; ++ uint8_t *buffer; ++ char *b64,*p,*t; ++ char key[1024]; ++ size_t filesize; ++ int size; ++ ++ if ((ret = (DER_key *)malloc(sizeof(DER_key))) == NULL) ++ return NULL; ++ buffer = public_key; ++ p = (char *)buffer; ++ while ((*p != '\n') && (*p != '\0')) ++ p++; ++ if (*p == '\0') { ++ free(ret); ++ return NULL; ++ } ++ p++; ++ b64 = t = p; ++ while((p - b64) <= filesize) { ++ if ((*p == '-')) { ++ break; ++ } else if ((*p != '\n') && (*p != ' ') && (*p != '\t')) { ++ *t = *p; ++ t++; ++ } ++ p++; ++ } ++ *t = '\0'; ++ size = B64_decode(b64, key, strlen(b64), 1024); ++ if (size < 0) { ++ free(buffer); ++ free(ret); ++ return NULL; ++ } ++ //free(buffer); ++ ret->buffer = (char *)malloc(size); ++ ret->size = size; ++ memcpy((void *)ret->buffer, (void *)key, size); ++ return ret; ++} ++ ++/* ++ * Similar to RSA_pub_key_new, rewritten to make this program depend only on bi module ++ */ ++void CH_pub_key_new(RSA_parameters **rsa, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len) ++{ ++ RSA_parameters *rsa_parameters; ++ ++ BI_CTX *bi_ctx = bi_initialize(); ++ *rsa = (RSA_parameters *)calloc(1, sizeof(RSA_parameters)); ++ rsa_parameters = *rsa; ++ rsa_parameters->bi_ctx = bi_ctx; ++ rsa_parameters->num_octets = (mod_len & 0xFFF0); ++ rsa_parameters->m = bi_import(bi_ctx, modulus, mod_len); ++ bi_set_mod(bi_ctx, rsa_parameters->m, BIGINT_M_OFFSET); ++ rsa_parameters->e = bi_import(bi_ctx, pub_exp, pub_len); ++ bi_permanent(rsa_parameters->e); ++} ++ ++/* ++ * Get the public key specifics from an ASN.1 encoded file ++ * A function lacking in the exported axTLS API ++ * ++ * This is a really weird hack that only works with RSA public key ++ * files ++ */ ++static int asn1_get_public_key(const uint8_t *buf, int len, RSA_parameters **rsa_parameters) ++{ ++ uint8_t *modulus, *pub_exp; ++ int mod_len, pub_len; ++ ++ pub_len = 3; ++ mod_len = len - 37; ++ if (buf[0] != 0x30) { ++ return -1; ++ } ++ ++ pub_exp = (uint8_t *)malloc(3); ++ modulus = (uint8_t *)malloc(mod_len); ++ memcpy(modulus, buf + 32 , mod_len); ++ memcpy(pub_exp, buf + 34 + mod_len, 3); ++ if (mod_len <= 0 || pub_len <= 0 ) ++ return -1; ++ CH_pub_key_new(rsa_parameters, modulus, mod_len, pub_exp, pub_len); ++ ++ free(modulus); ++ free(pub_exp); ++ return 0; ++} ++ ++ ++/* FR_init */ ++void *FR_init(void) ++{ ++ DER_key *derkey; ++ RSA_parameters *rsa_parameters; ++ ++ derkey = CH_load_pem_key(); ++ if ((asn1_get_public_key(derkey->buffer, derkey->size, &rsa_parameters)) != 0) { ++ fprintf(stderr, "Error: Extracting public key from file\n"); ++ return 0; ++ } ++ CH_free_der_key(derkey); ++ return (void *)rsa_parameters; ++} ++ ++FONRSA_ERROR FR_end(void *handle) ++{ ++ RSA_parameters *rsa_parameters = (RSA_parameters *)handle; ++ ++ free(rsa_parameters); ++ return FONRSA_OK; ++} ++ ++/* ++ * ++ * Implementation of PKCS 1.5 padding, borrowed from ++ * Tom's code (public domain) ++ */ ++ ++/* Standalone FR_verify_file */ ++FONRSA_ERROR FR_verify_file(void *handler, char *file_data, int file_len, ++ char *signature_buffer, int signature_size) ++{ ++ int j; ++ byte *hashcode; ++ byte hash[20]; ++ uint8_t *decrypted; ++ RSA_parameters *rsa_parameters = (RSA_parameters *)handler; ++ ++ /* Calculates the RIPEMD-160 hash of the file */ ++ hashcode = RMDbinary (file_data, file_len); ++ ++ if (rsa_parameters->num_octets != signature_size) ++ return FONRSA_SIZE; ++ decrypted = (uint8_t *)malloc(rsa_parameters->num_octets); ++ if (CH_decrypt(rsa_parameters, signature_buffer, decrypted)) { ++ printf("Error: Decrypting signature\n"); ++ return FONRSA_VERIFICATION_FAILURE; ++ } ++ memcpy(hash, decrypted + 492, 20); ++ //free(decrypted); ++ //free(signature_buffer); ++ for (j = 0; j < RMDsize/8; j++) { ++ if (hash[j] != hashcode[j]) ++ return FONRSA_VERIFICATION_FAILURE; ++ } ++ return FONRSA_OK; ++} ++ ++int rsa_check_signature(char *signature, int signature_len, char *buffer, int buffer_len) ++{ ++ FONRSA_ERROR fonrsa_error; ++ void *handle; ++ handle = FR_init(); ++ if (handle == NULL) { ++ printf("Error loading keys\n"); ++ return 1; ++ } ++ fonrsa_error = FR_verify_file(handle, buffer, buffer_len, signature, signature_len); ++ FR_end(handle); ++ switch (fonrsa_error) { ++ case FONRSA_OK: ++ printf("Verified OK\n"); ++ return 0; ++ case FONRSA_VERIFICATION_FAILURE: ++ printf("Verification failure\n"); ++ return 1; ++ default: ++ printf("Verification error\n"); ++ return -1; ++ } ++ ++} +--- /dev/null ++++ b/net/rsa/rsa.h +@@ -0,0 +1,46 @@ ++/* ++ * FONSM RSA handling library, used by fonsmcd and foncheckrsa ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Created: 20070306 Pablo Martin Medrano ++ * ++ * $Id: fonrsa.h 404 2007-09-17 10:41:31Z jesus.pico $ ++ */ ++#ifndef _FONRSA_H ++#define _FONRSA_H ++ ++#define MINIMUM_PADING_BYTES_PKCS_1_5 3 ++ ++typedef enum { ++ FONRSA_OK = 0, ++ FONRSA_VERIFICATION_FAILURE = 1, ++ FONRSA_OPENKEY = 2, ++ FONRSA_SIZE = 3, ++ FONRSA_LOADFILE = 4, ++ FONRSA_CRYPT = 5, ++ FONRSA_DECRYPT = 6, ++ FONRSA_SAVEFILE = 7, ++ FONRSA_NOSYS = 8, ++ FONRSA_VERIFY = 9 ++} FONRSA_ERROR; ++ ++int rsa_check_signature(char *signature, int signature_len, char *buffer, int buffer_len); ++ ++#endif ++ ++ +--- /dev/null ++++ b/net/rsa/sign.h +@@ -0,0 +1,27 @@ ++/* ++ * Signature interface ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * Created: 20070417 Pablo Martín Medrano ++ * ++ * $Id: sign.h 389 2007-06-11 08:29:56Z pablo.martin $ ++ */ ++#ifndef __SIGN_H__ ++#define __SIGN_H__ ++#ifdef __cplusplus ++ extern "C" { ++#endif ++ ++void SG_init(void); ++void *SG_start(char *private_key_path, char *public_key_path); ++void SG_stop(void *handle); ++int SG_crypt(void *data, unsigned char *text, int size_text, unsigned char *crypted_text, ++ unsigned int crypted_text_buffer_size, int *crypted_size); ++int SG_crypt_v2(void *data, unsigned char *text, int size_text, unsigned char *crypted_text, ++ unsigned int crypted_text_buffer_size, int *crypted_size); ++#ifdef __cplusplus ++} ++#endif ++#endif /* #ifdef __SIGN_H__ */ ++ +--- /dev/null ++++ b/net/rsa/sign_openssl.c +@@ -0,0 +1,437 @@ ++/* ++ * Signature using OpenSSL ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * Created: 20070417 Pablo Martín Medrano ++ * ++ * $Id: sign_openssl.c 346 2007-05-10 19:51:38Z pablo.martin $ ++ */ ++/* ++ * ++ * How the RSA public and private key was generated ++ * To check .FON files ++ * openssl genrsa -out private_fon_rsa_key.pem 4096 ++ * openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem ++ * ++ * How the Status Manager public and private key was generated ++ * openssl genrsa -out private_sm_rsa_key.pem 2048 ++ * openssl rsa -in private_sm_rsa_key.pem -pubout -out public_sm_rsa_key.pem ++ * ++ * How to sign using the RSA private key (This is what fonsign does) ++ * openssl dgst -rmd160 -sign private_fon_rsa_key.pem FILE > SIGNATURE ++ * How to verify using the RSA public key (This is what fonverify + foncheckrsa does) ++ * openssl dgst -rmd160 -verify public_fon_rsa_key.pem -signature SIGNATURE FILE ++ * Convert to DER file (to use it in La Fonera) ++ * openssl rsa -inform PEM -outform DER -pubin -in public_fon_rsa_key.pem -pubout -out public_fon_rsa_key.der ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifndef __MAINTEST__ ++#include "log.h" ++#else ++#define fon_warning printf ++#define fon_debug printf ++#define fon_critical printf ++#endif ++#include "sign.h" ++ ++typedef struct { ++ RSA *rsa; ++ int rsa_size; ++ EVP_PKEY *pkey; ++ int pkey_size; ++ RSA *public_rsa; ++ int public_rsa_size; ++ EVP_PKEY *public_pkey; ++ int public_pkey_size; ++} Sign; ++ ++typedef enum { ++ KEY_PUBLIC = 0, ++ KEY_PRIVATE ++} KEY_TYPE; ++ ++static EVP_PKEY *SG_load_key(char *key_path, KEY_TYPE type); ++static unsigned char *load_file_in_buffer(char *path, int *size); ++static int save_file_from_buffer(char *path, char *buffer, int size); ++ ++void SG_init(void) ++{ ++ SSL_load_error_strings(); ++ SSL_library_init(); ++ OpenSSL_add_all_algorithms(); ++ OpenSSL_add_all_ciphers(); ++ OpenSSL_add_all_digests(); ++} ++ ++static unsigned char *load_file_in_buffer(char *path, int *size) ++{ ++ char *buffer; ++ struct stat st; ++ int fd; ++ ++ if (stat(path, &st)) ++ return NULL; ++ buffer = (char *)malloc(st.st_size); ++ if (buffer == NULL) ++ return NULL; ++ if ((fd = open(path, O_RDONLY)) == -1) { ++ free(buffer); ++ return NULL; ++ } ++ if (read(fd,buffer,st.st_size) != (ssize_t)st.st_size) { ++ free(buffer); ++ close(fd); ++ return NULL; ++ } ++ *size = (int)st.st_size; ++ close(fd); ++ return buffer; ++} ++ ++static int save_file_from_buffer(char *path, char *buffer, int size) ++{ ++ int fd; ++ ++ if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) == -1) ++ return -1; ++ if (write(fd, buffer, (size_t)size) != ((ssize_t)size)) { ++ close(fd); ++ return -1; ++ } ++ close(fd); ++ return 0; ++} ++ ++static EVP_PKEY *SG_load_key(char *key_path, KEY_TYPE type) ++{ ++ BIO *key = NULL; ++ EVP_PKEY *pkey; ++ ++ if ((key = BIO_new(BIO_s_file())) == NULL) { ++ //ERR_print_errors(err); ++ fon_warning("%s: Error calling BIO_new()\n", __FUNCTION__); ++ return NULL; ++ } ++ if (BIO_read_filename(key, key_path) <= 0) { ++ fon_warning("%s: Error opening %s\n", __FUNCTION__, key_path); ++ // ERR_print_errors(err); ++ BIO_free(key); ++ } ++ if (type == KEY_PUBLIC) { ++ pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL); ++ } else if (type == KEY_PRIVATE) { ++ pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); ++ } else { ++ return NULL; ++ } ++ ++ if (pkey == NULL) { ++ fon_warning("%s: Error reading %s\n", __FUNCTION__, key_path); ++ BIO_free(key); ++ return NULL; ++ } ++ BIO_free(key); ++ return pkey; ++} ++ ++void *SG_start(char *private_key_path, char *public_key_path) ++{ ++ Sign *sign; ++ ++ if ((sign = (Sign *)malloc(sizeof(Sign))) == NULL) ++ return NULL; ++ memset(sign, 0, sizeof(Sign)); ++ if (private_key_path != NULL) { ++ if ((sign->pkey = SG_load_key(private_key_path, KEY_PRIVATE)) == NULL) { ++ fon_warning("%s: Error loading %s", __FUNCTION__, private_key_path); ++ return NULL; ++ } ++ } ++ if (public_key_path != NULL) { ++ if ((sign->public_pkey = SG_load_key(public_key_path, KEY_PUBLIC)) == NULL) { ++ fon_warning("%s: Error loading %s", __FUNCTION__, public_key_path); ++ return NULL; ++ } ++ } ++ if (sign->pkey != NULL) { ++ sign->pkey_size = EVP_PKEY_size(sign->pkey); ++ if ((sign->rsa = EVP_PKEY_get1_RSA(sign->pkey)) == NULL) { ++ EVP_PKEY_free(sign->pkey); ++ return NULL; ++ } ++ } ++ if (sign->public_pkey != NULL) { ++ sign->public_pkey_size = EVP_PKEY_size(sign->public_pkey); ++ if ((sign->public_rsa = EVP_PKEY_get1_RSA(sign->public_pkey)) == NULL) { ++ EVP_PKEY_free(sign->pkey); ++ return NULL; ++ } ++ } ++ if (((sign->rsa == NULL) && (private_key_path != NULL)) || ++ ((sign->public_rsa == NULL) && (public_key_path != NULL))) { ++ fon_warning("%s: Error calling EVP_PKEY_get1_RSA()", __FUNCTION__); ++ return NULL; ++ } ++ if (sign->rsa != NULL) { ++ sign->rsa_size = RSA_size(sign->rsa); ++ if (RSA_check_key(sign->rsa) != 1) { ++ fon_warning("%s: RSA key failure", __FUNCTION__); ++ return NULL; ++ } ++ } ++ ++ return (void *)sign; ++} ++ ++void SG_stop(void *handle) ++{ ++ Sign *sign = (Sign *)handle; ++ ++ EVP_PKEY_free(sign->pkey); ++ EVP_PKEY_free(sign->public_pkey); ++ if (sign->rsa != NULL) ++ RSA_free(sign->rsa); ++ if (sign->public_rsa != NULL) ++ RSA_free(sign->public_rsa); ++ free(sign); ++} ++ ++int SG_verify(void *data, unsigned char *text, unsigned int size_text, ++ unsigned char *signature, unsigned int size_signature) ++{ ++ EVP_MD_CTX mdctx; ++ EVP_MD *md; ++ EVP_PKEY *pkey; ++ int ret; ++ Sign *sign = (Sign *)data; ++ ++ md = (EVP_MD *)EVP_ripemd160(); ++ if(!EVP_VerifyInit(&mdctx, md)) ++ return 4; ++ if (!EVP_VerifyUpdate(&mdctx, (const void *)text, (unsigned int)size_text)) { ++ return 5; ++ } ++ ret = EVP_VerifyFinal(&mdctx, (const char *)signature, size_signature, sign->public_pkey); ++ EVP_PKEY_free(pkey); ++ EVP_MD_CTX_cleanup(&mdctx); ++ return ret; ++} ++ ++int SG_sign(void *data, void *text, unsigned int size_text, void *signature_buffer, ++ unsigned int size_signature_buffer, unsigned int *size_signature) ++{ ++ unsigned char *digest[EVP_MAX_MD_SIZE]; ++ EVP_MD_CTX mdctx; ++ EVP_MD *md; ++ int ret; ++ Sign *sign = (Sign *)data; ++ ++ if (size_signature_buffer < sign->pkey_size) ++ return 1; ++ ++ md = (EVP_MD *)EVP_ripemd160(); ++ EVP_SignInit(&mdctx, md); ++ if (!EVP_SignUpdate(&mdctx, (const void *)text, (unsigned int)size_text)) { ++ return 2; ++ } ++ if (!EVP_SignFinal(&mdctx, (unsigned char *)signature_buffer, (unsigned int *)size_signature, sign->pkey)) { ++ return 3; ++ } ++ EVP_MD_CTX_cleanup(&mdctx); ++ ++ return 0; ++} ++ ++/* ++ * It's not advised to crypt using RAW ... unless you have crypted the buffer using AES before. ++ */ ++int SG_crypt(void *data, unsigned char *text, int size_text, ++ unsigned char *crypted_text, unsigned int crypted_text_buffer_size, ++ int *crypted_size) ++{ ++ EVP_MD_CTX mdctx; ++ EVP_MD *md; ++ int retsize; ++ Sign *sign = (Sign *)data; ++ ++ if (crypted_text_buffer_size < sign->pkey_size) { ++ fon_critical("%s: size_signature_buffer [%u] < %u", __FUNCTION__, size_text, sign->pkey_size); ++ return 1; ++ } ++ if (size_text != sign->pkey_size) { ++ fon_critical("%s: size_text [%u] != %u", __FUNCTION__, size_text, sign->pkey_size); ++ return 2; ++ } ++ /* The buffer is pre-padded with random data ... */ ++ fon_debug("%s: About to call RSA_private_encrypt(%d, %x, %x, %x, %d)", ++ __FUNCTION__, size_text, crypted_text, sign->rsa, RSA_NO_PADDING); ++ retsize = RSA_private_encrypt(size_text, text, crypted_text, sign->rsa, RSA_NO_PADDING); ++ if (retsize == -1) { ++ fon_critical("%s: Error calling RSA_private_encrypt(%d, %x, %x, %x, %d)", ++ __FUNCTION__, size_text, crypted_text, sign->rsa, RSA_NO_PADDING); ++ return 1; ++ } ++ *crypted_size = retsize; ++ return 0; ++} ++ ++/* SG_decrypt */ ++int SG_decrypt(void *data, unsigned char *cryptext, int cryptext_size, unsigned char *plaintext, ++ int plaintext_buffer_size, int *plaintext_size) ++{ ++ EVP_MD_CTX mdctx; ++ EVP_MD *md; ++ int retsize; ++ Sign *sign = (Sign *)data; ++ ++ if (plaintext_buffer_size < sign->public_pkey_size) { ++ fon_critical("%s: plaintext_buffer_size [%u] < %u", __FUNCTION__, plaintext_buffer_size, sign->public_pkey_size); ++ return 1; ++ } ++ if (cryptext_size != sign->public_pkey_size) { ++ fon_critical("%s: cryptext_size [%u] != %u", __FUNCTION__, cryptext_size, sign->public_pkey_size); ++ return 2; ++ } ++ retsize = RSA_public_decrypt(cryptext_size, cryptext, plaintext, sign->public_rsa, RSA_NO_PADDING); ++ if (retsize == -1) ++ return 1; ++ *plaintext_size = retsize; ++ return 0; ++} ++ ++#ifdef __MAINTEST__ ++int main(int argc, char **argv) ++{ ++ size_t argv0_size; ++ char *token; ++ ++ argv0_size = strlen(argv[0]); ++ if (argv0_size < 7) { ++ fprintf(stderr, "%s?", argv[0]); ++ return 1; ++ } ++ token = argv[0] + argv0_size - 7; ++ ++ SG_init(); ++ if (!strcmp(token, "fonsign")) { ++ return main_fonsign(argc, argv); ++ } else if (!strcmp(token, "foncryp")) { ++ return main_foncryp(argc, argv); ++ } ++ fprintf(stderr, "%s?", argv[0]); ++ return 1; ++} ++ ++int main_foncryp(int argc, char **argv) ++{ ++ void *handle = NULL; ++ int encrypt = 0; ++ char *filebuffer = NULL; ++ char crypted[1024]; ++ int size, crypted_size, ret; ++ ++ if (argc != 5) { ++ printf("Usage: %s encrypt|decrypt \n", argv[0]); ++ return 1; ++ } ++ if (!strcmp(argv[1], "encrypt")) { ++ printf("Encryption mode\n"); ++ encrypt = 1; ++ } else ++ printf("Decryption mode\n"); ++ if (encrypt) ++ handle = SG_start(argv[2], NULL); ++ else ++ handle = SG_start(NULL, argv[2]); ++ if (handle == NULL) { ++ printf("Error loading keys\n"); ++ return 1; ++ } ++ ++ filebuffer = load_file_in_buffer(argv[3], &size); ++ if (filebuffer == NULL) { ++ printf("Error reading %s\n", argv[3]); ++ SG_stop(handle); ++ return 1; ++ } ++ if (encrypt) ++ ret = SG_crypt(handle, filebuffer, size, crypted, 1024, &crypted_size); ++ else ++ ret = SG_decrypt(handle, filebuffer, size, crypted, 1024, &crypted_size); ++ ++ if (ret) { ++ printf("Error crypting %d bytes\n", size); ++ SG_stop(handle); ++ return 1; ++ } ++ printf("Crypted size %d\n", crypted_size); ++ if (save_file_from_buffer(argv[4], crypted, crypted_size)) { ++ printf("Error saving file\n"); ++ SG_stop(handle); ++ return 1; ++ } ++ ++ SG_stop(handle); ++ return 0; ++} ++ ++int main_fonsign(int argc, char **argv) ++{ ++ void *handle = NULL; ++ char signature_buffer[4096]; ++ char *signature; ++ unsigned int signature_size; ++ struct stat st; ++ char *filebuffer = NULL; ++ int size; ++ int ret = -1; ++ ++ if (argc != 5) { ++ fprintf(stderr, "usage: %s \n", argv[0]); ++ goto end; ++ } ++ handle = SG_start(argv[1], argv[2]); ++ if (handle == NULL) { ++ fprintf(stderr, "Error calling SG_start(%s)\n", argv[1]); ++ goto end; ++ } ++ filebuffer = load_file_in_buffer(argv[3], &size); ++ if (filebuffer == NULL) { ++ fprintf(stderr, "Error reading %s\n", argv[3]); ++ goto end; ++ } ++ if (SG_sign(handle, filebuffer, size, signature_buffer, 4096, &signature_size)) { ++ fprintf(stderr, "Error calling SG_sign()\n"); ++ goto end; ++ } ++ ret = SG_verify(handle, filebuffer, size, signature_buffer, signature_size); ++ if (ret == 0) ++ fprintf(stderr, "signature failure\n"); ++ else if (ret == 1) { ++ fprintf(stderr, "signature ok\n"); ++ ret = 0; ++ } else { ++ fprintf(stderr, "signature error\n"); ++ goto end; ++ } ++ if (save_file_from_buffer(argv[4], signature_buffer, signature_size)) { ++ fprintf(stderr, "Error writing to %s\n", argv[4]); ++ goto end; ++ } ++ ret = 0; ++end: ++ if (filebuffer != NULL) ++ free(filebuffer); ++ if (handle != NULL) ++ SG_stop(handle); ++ return ret; ++} ++#endif ++ +--- /dev/null ++++ b/net/uip-0.9/fs.c +@@ -0,0 +1,154 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ ++ ++/** ++ * \file ++ * HTTP server read-only file system code. ++ * \author Adam Dunkels ++ * ++ * A simple read-only filesystem. ++ */ ++ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: fs.c,v 1.7.2.3 2003/10/07 13:22:27 adam Exp $ ++ */ ++ ++#include "uip.h" ++#include "httpd.h" ++#include "fs.h" ++#include "fsdata.h" ++ ++#include "fsdata.c" ++ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++static u16_t count[FS_NUMFILES]; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++/*-----------------------------------------------------------------------------------*/ ++static u8_t ++fs_strcmp(const char *str1, const char *str2) ++{ ++ u8_t i; ++ i = 0; ++ loop: ++ ++ if(str2[i] == 0 || ++ str1[i] == '\r' || ++ str1[i] == '\n') { ++ return 0; ++ } ++ ++ if(str1[i] != str2[i]) { ++ return 1; ++ } ++ ++ ++ ++i; ++ goto loop; ++} ++/*-----------------------------------------------------------------------------------*/ ++int ++fs_open(const char *name, struct fs_file *file) ++{ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t i = 0; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ struct fsdata_file_noconst *f; ++ ++ for(f = (struct fsdata_file_noconst *)FS_ROOT; ++ f != NULL; ++ f = (struct fsdata_file_noconst *)f->next) { ++ ++ if(fs_strcmp(name, f->name) == 0) { ++ file->data = f->data; ++ file->len = f->len; ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ ++count[i]; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ return 1; ++ } ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ ++i; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++ } ++ return 0; ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++fs_init(void) ++{ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t i; ++ for(i = 0; i < FS_NUMFILES; i++) { ++ count[i] = 0; ++ } ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++} ++/*-----------------------------------------------------------------------------------*/ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++u16_t fs_count ++(char *name) ++{ ++ struct fsdata_file_noconst *f; ++ u16_t i; ++ ++ i = 0; ++ for(f = (struct fsdata_file_noconst *)FS_ROOT; ++ f != NULL; ++ f = (struct fsdata_file_noconst *)f->next) { ++ ++ if(fs_strcmp(name, f->name) == 0) { ++ return count[i]; ++ } ++ ++i; ++ } ++ return 0; ++} ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/fsdata.c +@@ -0,0 +1,199 @@ ++static const char data_flashing_html[] = { ++ /* /flashing.html */ ++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, ++ 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, ++ 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, ++ 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, ++ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, ++ 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, ++ 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, ++ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, ++ 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, ++ 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, ++ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, ++ 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, ++ 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, ++ 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, ++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++static const char data_fail_html[] = { ++ /* /fail.html */ ++ 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, ++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, ++ 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, ++ 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, ++ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, ++ 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45, ++ 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65, ++ 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75, ++ 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, ++ 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, ++ 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, ++ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50, ++ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65, ++ 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, ++ 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69, ++ 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, ++ 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, ++ 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, ++ 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e, ++ 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, ++ 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, ++ 0x3e, 0xa, }; ++ ++static const char data_404_html[] = { ++ /* /404.html */ ++ 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, ++ 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, ++ 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, ++ 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, ++ 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, ++ 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, ++ 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, ++ 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, ++ 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, ++ 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, ++ 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, ++ 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, ++ 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, ++ 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20, ++ 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, ++ 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, ++ 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f, ++ 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, ++ 0x6c, 0x3e, }; ++ ++static const char data_index_html[] = { ++ /* /index.html */ ++ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, ++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, ++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, ++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, ++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, ++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, ++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, ++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, ++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, ++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, ++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, ++ 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, ++ 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, ++ 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, ++ 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, ++ 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74, ++ 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d, ++ 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, ++ 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, ++ 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70, ++ 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, ++ 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69, ++ 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9, ++ 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, ++ 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, ++ 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, ++ 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++static const char data_flash_html[] = { ++ /* /flash.html */ ++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, ++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, ++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, ++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, ++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, ++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, ++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, ++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, ++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, ++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, ++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, ++ 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69, ++ 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, ++ 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, ++ 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72, ++ 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c, ++ 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, ++ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, ++ 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68, ++ 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c, ++ 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f, ++ 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9, ++ 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73, ++ 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c, ++ 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, ++ 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c, ++ 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c, ++ 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, ++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}}; ++ ++const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}}; ++ ++const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; ++ ++const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; ++ ++const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}}; ++ ++#define FS_ROOT file_flash_html ++ ++#define FS_NUMFILES 5 +\ No newline at end of file +--- /dev/null ++++ b/net/uip-0.9/fsdata.h +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: fsdata.h,v 1.4.2.1 2003/10/04 22:54:06 adam Exp $ ++ */ ++#ifndef __FSDATA_H__ ++#define __FSDATA_H__ ++ ++#include "uipopt.h" ++ ++struct fsdata_file { ++ const struct fsdata_file *next; ++ const char *name; ++ const char *data; ++ const int len; ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t count; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++}; ++ ++struct fsdata_file_noconst { ++ struct fsdata_file *next; ++ char *name; ++ char *data; ++ int len; ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t count; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++}; ++ ++#endif /* __FSDATA_H__ */ +--- /dev/null ++++ b/net/uip-0.9/fs.h +@@ -0,0 +1,80 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ ++ ++/** ++ * \file ++ * HTTP server read-only file system header file. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $ ++ */ ++#ifndef __FS_H__ ++#define __FS_H__ ++ ++#include "uip.h" ++ ++/** ++ * An open file in the read-only file system. ++ */ ++struct fs_file { ++ char *data; /**< The actual file data. */ ++ int len; /**< The length of the file data. */ ++}; ++ ++/** ++ * Open a file in the read-only file system. ++ * ++ * \param name The name of the file. ++ * ++ * \param file The file pointer, which must be allocated by caller and ++ * will be filled in by the function. ++ */ ++int fs_open(const char *name, struct fs_file *file); ++ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++u16_t fs_count(char *name); ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++/** ++ * Initialize the read-only file system. ++ */ ++void fs_init(void); ++ ++#endif /* __FS_H__ */ +--- /dev/null ++++ b/net/uip-0.9/httpd.c +@@ -0,0 +1,278 @@ ++#include "uip.h" ++#include "httpd.h" ++#include "fs.h" ++#include "fsdata.h" ++#include ++ ++#define HTTP_NONE 0 ++#define HTTP_FILE 1 ++#define HTTP_FIRMWARE 2 ++ ++#define PRINT(x) printf("%s", x) ++#define PRINTLN(x) printf("%s\n", x) ++ ++extern unsigned long do_http_tmp_address(void); ++ ++struct httpd_state *hs; ++ ++extern const struct fsdata_file file_index_html; ++extern const struct fsdata_file file_404_html; ++extern const struct fsdata_file file_flash_html; ++extern int httpd_upload_complete; ++extern unsigned char *httpd_upload_data; ++unsigned char *upload_data; ++extern ulong NetBootFileXferSize; ++int upload_running = 0; ++ ++#define ISO_G 0x47 ++#define ISO_E 0x45 ++#define ISO_T 0x54 ++#define ISO_P 0x50 ++#define ISO_O 0x4f ++#define ISO_S 0x53 ++#define ISO_T 0x54 ++#define ISO_slash 0x2f ++#define ISO_c 0x63 ++#define ISO_g 0x67 ++#define ISO_i 0x69 ++#define ISO_space 0x20 ++#define ISO_nl 0x0a ++#define ISO_cr 0x0d ++#define ISO_a 0x61 ++#define ISO_t 0x74 ++#define ISO_hash 0x23 ++#define ISO_period 0x2e ++ ++static char eol[3] = { 0x0d, 0x0a, 0x00 }; ++static char eol2[5] = { 0x0d, 0x0a, 0x0d, 0x0a, 0x00 }; ++static char boundary[128]; ++static int boundary_len = 0; ++ ++/* we use this so that we can do without the ctype library */ ++#define is_digit(c) ((c) >= '0' && (c) <= '9') ++static int atoi(const char *s) ++{ ++ int i=0; ++ ++ while (is_digit(*s)) ++ i = i*10 + *(s++) - '0'; ++ return i; ++} ++ ++void ++httpd_init(void) ++{ ++ fs_init(); ++ uip_listen(HTONS(80)); ++} ++ ++void ++httpd_appcall(void) ++{ ++ struct fs_file fsfile; ++ u8_t i; ++ switch(uip_conn->lport) { ++ case HTONS(80): ++ hs = (struct httpd_state *)(uip_conn->appstate); ++ if(uip_connected()) ++ { ++ hs->state = HTTP_NONE; ++ hs->count = 0; ++ return; ++ } else if(uip_poll()) ++ { ++ if(hs->count++ >= 1000) { ++ uip_abort(); ++ } ++ return; ++ } else if(uip_newdata() && hs->state == HTTP_NONE) ++ { ++ if(uip_appdata[0] == ISO_G && ++ uip_appdata[1] == ISO_E && ++ uip_appdata[2] == ISO_T && ++ uip_appdata[3] == ISO_space) ++ { ++ hs->state = HTTP_FILE; ++ } ++ if(uip_appdata[0] == ISO_P && ++ uip_appdata[1] == ISO_O && ++ uip_appdata[2] == ISO_S && ++ uip_appdata[3] == ISO_T && ++ uip_appdata[4] == ISO_space) ++ { ++ hs->state = HTTP_FIRMWARE; ++ } ++ if(hs->state == HTTP_NONE) ++ { ++ uip_abort(); ++ return; ++ } ++ if(hs->state == HTTP_FILE) ++ { ++ for(i = 4; i < 40; ++i) ++ { ++ if(uip_appdata[i] == ISO_space || ++ uip_appdata[i] == ISO_cr || ++ uip_appdata[i] == ISO_nl) ++ { ++ uip_appdata[i] = 0; ++ break; ++ } ++ } ++ ++ PRINT("request for file "); ++ PRINTLN(&uip_appdata[4]); ++ if(uip_appdata[4] == ISO_slash && ++ uip_appdata[5] == 0) ++ { ++ fs_open(file_index_html.name, &fsfile); ++ } else { ++ if(!fs_open((const char *)&uip_appdata[4], &fsfile)) ++ { ++ PRINTLN("couldn't open file"); ++ fs_open(file_index_html.name, &fsfile); ++ } ++ } ++ hs->script = 0; ++ hs->state = HTTP_FILE; ++ hs->dataptr = fsfile.data; ++ hs->count = fsfile.len; ++ } ++ if(hs->state == HTTP_FIRMWARE) ++ { ++ unsigned char *start = (unsigned char*)uip_appdata; ++ char *clen = strstr(start, "Content-Length:"); ++ int len = 0; ++ unsigned char *next, *end; ++ unsigned char *boundary_start; ++ int i; ++ uip_appdata[uip_len] = '\0'; ++ if(clen) ++ { ++ clen += sizeof("Content-Length:"); ++ next = strstr(clen, eol); ++ if(next) ++ { ++ len = atoi(clen); ++ next++; ++ printf("expecting %d bytes\n", len); ++ upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address(); ++ printf("received data will be stored at 0x%08X\n", upload_data); ++ if(!upload_data) ++ { ++ printf("failed to allocate memory\n"); ++ uip_close(); ++ return; ++ } ++ } else { ++ uip_close(); ++ return; ++ } ++ } ++ if(len < 4 * 1024) ++ { ++ uip_close(); ++ return; ++ } ++ boundary_start = strstr(next, "---"); ++ if(!boundary_start) ++ { ++ uip_close(); ++ return; ++ } ++ end = strstr(boundary_start, eol); ++ if(!eol) ++ { ++ uip_close(); ++ return; ++ } ++ boundary_len = end - boundary_start; ++ memcpy(boundary, boundary_start, boundary_len); ++ boundary[boundary_len] = 0; ++ next = strstr(boundary_start, "name=\"firmware\";"); ++ if(!next) ++ { ++ uip_close(); ++ return; ++ } ++ next = strstr(next, eol2); ++ if(!next) ++ { ++ printf("could not find start of data\n"); ++ uip_close(); ++ return; ++ } ++ next += 4; ++ hs->script = 0; ++ hs->state = HTTP_FIRMWARE; ++ hs->upload = uip_len - (next - start); ++ hs->upload_total = len - (int)(next - boundary_start); ++ hs->upload_total -= (strlen(boundary) + 6); ++ //printf("storing %d bytes at %p\n", (int)hs->upload, upload_data); ++ for(i = 0; i < hs->upload; i++) ++ upload_data[i] = next[i]; ++ upload_data += (int)hs->upload; ++ printf("%d / %d\n", (int)hs->upload, hs->upload_total); ++ uip_slen = 0; ++ return; ++ } ++ } ++ ++ if(hs->state == HTTP_FIRMWARE) ++ { ++ if(uip_newdata()) ++ { ++ int i; ++ hs->count = 0; ++ uip_appdata[uip_len] = '\0'; ++ hs->upload += uip_len; ++ //printf("storing %d bytes at %p\n", uip_len, upload_data); ++ printf("%d / %d\n", (int)hs->upload, hs->upload_total); ++ for(i = 0; i < uip_len; i++) ++ upload_data[i] = uip_appdata[i]; ++ upload_data += uip_len; ++ uip_slen = 0; ++ if(hs->upload >= hs->upload_total) ++ { ++ upload_running = 1; ++ NetBootFileXferSize = hs->upload_total; ++ fs_open(file_flash_html.name, &fsfile); ++ hs->script = 0; ++ hs->state = HTTP_FILE; ++ hs->dataptr = fsfile.data; ++ hs->count = fsfile.len; ++ } ++ } ++ } ++ if(hs->state == HTTP_FILE) ++ { ++ if(uip_acked()) ++ { ++ if(hs->count >= uip_conn->len) ++ { ++ hs->count -= uip_conn->len; ++ hs->dataptr += uip_conn->len; ++ } else { ++ hs->count = 0; ++ } ++ if(hs->count == 0) ++ { ++ if(upload_running) ++ { ++ int i; ++ httpd_upload_complete = 1; ++ // for(i = 0; i < hs->upload_total; i++) ++ // printf("%c", httpd_upload_data[i]); ++ } ++ uip_close(); ++ } ++ } ++ uip_send(hs->dataptr, hs->count); ++ } ++ break; ++ ++ default: ++ uip_abort(); ++ break; ++ } ++} +--- /dev/null ++++ b/net/uip-0.9/httpd.h +@@ -0,0 +1,83 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ ++ ++/** ++ * \file ++ * HTTP server header file. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: httpd.h,v 1.4.2.3 2003/10/06 22:56:44 adam Exp $ ++ * ++ */ ++ ++#ifndef __HTTPD_H__ ++#define __HTTPD_H__ ++ ++void httpd_init(void); ++void httpd_appcall(void); ++ ++/* UIP_APPCALL: the name of the application function. This function ++ must return void and take no arguments (i.e., C type "void ++ appfunc(void)"). */ ++#ifndef UIP_APPCALL ++#define UIP_APPCALL httpd_appcall ++#endif ++ ++struct httpd_state { ++ u8_t state; ++ u16_t count; ++ char *dataptr; ++ char *script; ++ unsigned int upload; ++ unsigned int upload_total; ++}; ++ ++ ++/* UIP_APPSTATE_SIZE: The size of the application-specific state ++ stored in the uip_conn structure. */ ++#ifndef UIP_APPSTATE_SIZE ++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) ++#endif ++ ++#define FS_STATISTICS 1 ++ ++extern struct httpd_state *hs; ++ ++ ++/* we copy the data to RAM+10MB */ ++#define TMP_DATA 0x8A100000 ++ ++#endif /* __HTTPD_H__ */ +--- /dev/null ++++ b/net/uip-0.9/main.c +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: main.c,v 1.10.2.1 2003/10/04 22:54:17 adam Exp $ ++ * ++ */ ++ ++ ++#include "uip.h" ++#include "uip_arp.h" ++#include "tapdev.h" ++#include "httpd.h" ++ ++#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ ++#ifndef NULL ++#define NULL (void *)0 ++#endif /* NULL */ ++ ++/*-----------------------------------------------------------------------------------*/ ++int ++main(void) ++{ ++ u8_t i, arptimer; ++ tapdev_init(); ++ uip_init(); ++ httpd_init(); ++ arptimer = 0; ++ while(1) { ++ uip_len = tapdev_read(); ++ if(uip_len == 0) { ++ for(i = 0; i < UIP_CONNS; i++) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ tapdev_send(); ++ } ++ } ++ ++ if(++arptimer == 20) { ++ uip_arp_timer(); ++ arptimer = 0; ++ } ++ } else { ++ if(BUF->type == htons(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ tapdev_send(); ++ } ++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); ++ if(uip_len > 0) { ++ tapdev_send(); ++ } ++ } ++ } ++ } ++ return 0; ++} +--- /dev/null ++++ b/net/uip-0.9/Makefile +@@ -0,0 +1,54 @@ ++# Copyright (c) 2001, Adam Dunkels. ++# All rights reserved. ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions ++# are met: ++# 1. Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# 2. Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in the ++# documentation and/or other materials provided with the distribution. ++# 3. All advertising materials mentioning features or use of this software ++# must display the following acknowledgement: ++# This product includes software developed by Adam Dunkels. ++# 4. The name of the author may not be used to endorse or promote ++# products derived from this software without specific prior ++# written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++# ++# This file is part of the uIP TCP/IP stack. ++# ++# $Id: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $ ++# ++ ++CC=gcc ++CFLAGS=-Wall -fpack-struct -DDUMP=0 ++ ++all: uip ++ ++uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o ++ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ ++ ++%.o: %.c ++ $(CC) $(CFLAGS) -c $^ -o $@ ++ ++clean: ++ rm -f *.o *~ *core uip ++ ++ ++ ++ ++ ++ +--- /dev/null ++++ b/net/uip-0.9/tapdev.c +@@ -0,0 +1,192 @@ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: tapdev.c,v 1.7.2.1 2003/10/07 13:23:19 adam Exp $ ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef linux ++#include ++#include ++#include ++#define DEVTAP "/dev/net/tun" ++#else /* linux */ ++#define DEVTAP "/dev/tap0" ++#endif /* linux */ ++ ++#include "uip.h" ++ ++static int fd; ++ ++static unsigned long lasttime; ++static struct timezone tz; ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++tapdev_init(void) ++{ ++ char buf[1024]; ++ ++ fd = open(DEVTAP, O_RDWR); ++ if(fd == -1) { ++ perror("tapdev: tapdev_init: open"); ++ exit(1); ++ } ++ ++#ifdef linux ++ { ++ struct ifreq ifr; ++ memset(&ifr, 0, sizeof(ifr)); ++ ifr.ifr_flags = IFF_TAP|IFF_NO_PI; ++ if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) { ++ perror(buf); ++ exit(1); ++ } ++ } ++#endif /* Linux */ ++ ++ snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d", ++ UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3); ++ system(buf); ++ ++ lasttime = 0; ++} ++ ++void dump_mem(int type, int len) ++{ ++#if DUMP == 1 ++ int i; ++ for(i = 0; i < len; i++) ++ printf("%c", uip_buf[i]); ++ if(type) ++ { ++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"); ++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"); ++ } else { ++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"); ++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"); ++ } ++ fflush(stdout); ++#endif ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++unsigned int ++tapdev_read(void) ++{ ++ fd_set fdset; ++ struct timeval tv, now; ++ int ret; ++ ++ if(lasttime >= 500000) { ++ lasttime = 0; ++ return 0; ++ } ++ ++ tv.tv_sec = 0; ++ tv.tv_usec = 500000 - lasttime; ++ ++ ++ FD_ZERO(&fdset); ++ FD_SET(fd, &fdset); ++ ++ gettimeofday(&now, &tz); ++ ret = select(fd + 1, &fdset, NULL, NULL, &tv); ++ if(ret == 0) { ++ lasttime = 0; ++ return 0; ++ } ++ ret = read(fd, uip_buf, UIP_BUFSIZE); ++ if(ret == -1) { ++ perror("tap_dev: tapdev_read: read"); ++ } ++ gettimeofday(&tv, &tz); ++ lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec); ++ dump_mem(0, ret); ++ return ret; ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++tapdev_send(void) ++{ ++ int ret; ++ struct iovec iov[2]; ++ ++#ifdef linux ++ { ++ char tmpbuf[UIP_BUFSIZE]; ++ int i; ++ ++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) { ++ tmpbuf[i] = uip_buf[i]; ++ } ++ ++ for(; i < uip_len; i++) { ++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN]; ++ } ++ ++ ret = write(fd, tmpbuf, uip_len); ++ } ++#else ++ ++ if(uip_len < 40 + UIP_LLH_LEN) { ++ ret = write(fd, uip_buf, uip_len + UIP_LLH_LEN); ++ } else { ++ iov[0].iov_base = uip_buf; ++ iov[0].iov_len = 40 + UIP_LLH_LEN; ++ iov[1].iov_base = (char *)uip_appdata; ++ iov[1].iov_len = uip_len - (40 + UIP_LLH_LEN); ++ ++ ret = writev(fd, iov, 2); ++ } ++#endif ++ dump_mem(1, ret); ++ ++ if(ret == -1) { ++ perror("tap_dev: tapdev_send: writev"); ++ exit(1); ++ } ++} ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/tapdev.h +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: tapdev.h,v 1.1.2.1 2003/10/04 22:54:17 adam Exp $ ++ * ++ */ ++ ++#ifndef __TAPDEV_H__ ++#define __TAPDEV_H__ ++ ++void tapdev_init(void); ++unsigned int tapdev_read(void); ++void tapdev_send(void); ++ ++#endif /* __TAPDEV_H__ */ +--- /dev/null ++++ b/net/uip-0.9/uip_arch.c +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $ ++ * ++ */ ++ ++ ++#include "uip.h" ++#include "uip_arch.h" ++ ++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define IP_PROTO_TCP 6 ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_add32(u8_t *op32, u16_t op16) ++{ ++ ++ uip_acc32[3] = op32[3] + (op16 & 0xff); ++ uip_acc32[2] = op32[2] + (op16 >> 8); ++ uip_acc32[1] = op32[1]; ++ uip_acc32[0] = op32[0]; ++ ++ if(uip_acc32[2] < (op16 >> 8)) { ++ ++uip_acc32[1]; ++ if(uip_acc32[1] == 0) { ++ ++uip_acc32[0]; ++ } ++ } ++ ++ ++ if(uip_acc32[3] < (op16 & 0xff)) { ++ ++uip_acc32[2]; ++ if(uip_acc32[2] == 0) { ++ ++uip_acc32[1]; ++ if(uip_acc32[1] == 0) { ++ ++uip_acc32[0]; ++ } ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_chksum(u16_t *sdata, u16_t len) ++{ ++ u16_t acc; ++ ++ for(acc = 0; len > 1; len -= 2) { ++ acc += *sdata; ++ if(acc < *sdata) { ++ /* Overflow, so we add the carry to acc (i.e., increase by ++ one). */ ++ ++acc; ++ } ++ ++sdata; ++ } ++ ++ /* add up any odd byte */ ++ if(len == 1) { ++ acc += htons(((u16_t)(*(u8_t *)sdata)) << 8); ++ if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) { ++ ++acc; ++ } ++ } ++ ++ return acc; ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_ipchksum(void) ++{ ++ return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_tcpchksum(void) ++{ ++ u16_t hsum, sum; ++ ++ ++ /* Compute the checksum of the TCP header. */ ++ hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); ++ ++ /* Compute the checksum of the data in the TCP packet and add it to ++ the TCP header checksum. */ ++ sum = uip_chksum((u16_t *)uip_appdata, ++ (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); ++ ++ if((sum += hsum) < hsum) { ++ ++sum; ++ } ++ ++ if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) { ++ ++sum; ++ } ++ if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) { ++ ++sum; ++ } ++ if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) { ++ ++sum; ++ } ++ if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) { ++ ++sum; ++ } ++ if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) { ++ ++sum; ++ } ++ ++ hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20); ++ ++ if((sum += hsum) < hsum) { ++ ++sum; ++ } ++ ++ return sum; ++} ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/uip_arch.h +@@ -0,0 +1,130 @@ ++/** ++ * \defgroup uiparch Architecture specific uIP functions ++ * @{ ++ * ++ * The functions in the architecture specific module implement the IP ++ * check sum and 32-bit additions. ++ * ++ * The IP checksum calculation is the most computationally expensive ++ * operation in the TCP/IP stack and it therefore pays off to ++ * implement this in efficient assembler. The purpose of the uip-arch ++ * module is to let the checksum functions to be implemented in ++ * architecture specific assembler. ++ * ++ */ ++ ++/** ++ * \file ++ * Declarations of architecture specific functions. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_ARCH_H__ ++#define __UIP_ARCH_H__ ++ ++#include "uip.h" ++ ++/** ++ * Carry out a 32-bit addition. ++ * ++ * Because not all architectures for which uIP is intended has native ++ * 32-bit arithmetic, uIP uses an external C function for doing the ++ * required 32-bit additions in the TCP protocol processing. This ++ * function should add the two arguments and place the result in the ++ * global variable uip_acc32. ++ * ++ * \note The 32-bit integer pointed to by the op32 parameter and the ++ * result in the uip_acc32 variable are in network byte order (big ++ * endian). ++ * ++ * \param op32 A pointer to a 4-byte array representing a 32-bit ++ * integer in network byte order (big endian). ++ * ++ * \param op16 A 16-bit integer in host byte order. ++ */ ++void uip_add32(u8_t *op32, u16_t op16); ++ ++/** ++ * Calculate the Internet checksum over a buffer. ++ * ++ * The Internet checksum is the one's complement of the one's ++ * complement sum of all 16-bit words in the buffer. ++ * ++ * See RFC1071. ++ * ++ * \note This function is not called in the current version of uIP, ++ * but future versions might make use of it. ++ * ++ * \param buf A pointer to the buffer over which the checksum is to be ++ * computed. ++ * ++ * \param len The length of the buffer over which the checksum is to ++ * be computed. ++ * ++ * \return The Internet checksum of the buffer. ++ */ ++u16_t uip_chksum(u16_t *buf, u16_t len); ++ ++/** ++ * Calculate the IP header checksum of the packet header in uip_buf. ++ * ++ * The IP header checksum is the Internet checksum of the 20 bytes of ++ * the IP header. ++ * ++ * \return The IP header checksum of the IP header in the uip_buf ++ * buffer. ++ */ ++u16_t uip_ipchksum(void); ++ ++/** ++ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. ++ * ++ * The TCP checksum is the Internet checksum of data contents of the ++ * TCP segment, and a pseudo-header as defined in RFC793. ++ * ++ * \note The uip_appdata pointer that points to the packet data may ++ * point anywhere in memory, so it is not possible to simply calculate ++ * the Internet checksum of the contents of the uip_buf buffer. ++ * ++ * \return The TCP checksum of the TCP segment in uip_buf and pointed ++ * to by uip_appdata. ++ */ ++u16_t uip_tcpchksum(void); ++ ++/** @} */ ++ ++#endif /* __UIP_ARCH_H__ */ +--- /dev/null ++++ b/net/uip-0.9/uip_arp.c +@@ -0,0 +1,421 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \defgroup uiparp uIP Address Resolution Protocol ++ * @{ ++ * ++ * The Address Resolution Protocol ARP is used for mapping between IP ++ * addresses and link level addresses such as the Ethernet MAC ++ * addresses. ARP uses broadcast queries to ask for the link level ++ * address of a known IP address and the host which is configured with ++ * the IP address for which the query was meant, will respond with its ++ * link level address. ++ * ++ * \note This ARP implementation only supports Ethernet. ++ */ ++ ++/** ++ * \file ++ * Implementation of the ARP Address Resolution Protocol. ++ * \author Adam Dunkels ++ * ++ */ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $ ++ * ++ */ ++ ++ ++#include "uip_arp.h" ++ ++struct arp_hdr { ++ struct uip_eth_hdr ethhdr; ++ u16_t hwtype; ++ u16_t protocol; ++ u8_t hwlen; ++ u8_t protolen; ++ u16_t opcode; ++ struct uip_eth_addr shwaddr; ++ u16_t sipaddr[2]; ++ struct uip_eth_addr dhwaddr; ++ u16_t dipaddr[2]; ++}; ++ ++struct ethip_hdr { ++ struct uip_eth_hdr ethhdr; ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++}; ++ ++#define ARP_REQUEST 1 ++#define ARP_REPLY 2 ++ ++#define ARP_HWTYPE_ETH 1 ++ ++struct arp_entry { ++ u16_t ipaddr[2]; ++ struct uip_eth_addr ethaddr; ++ u8_t time; ++}; ++ ++struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, ++ UIP_ETHADDR1, ++ UIP_ETHADDR2, ++ UIP_ETHADDR3, ++ UIP_ETHADDR4, ++ UIP_ETHADDR5}}; ++ ++static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; ++static u16_t ipaddr[2]; ++static u8_t i, c; ++ ++static u8_t arptime; ++static u8_t tmpage; ++ ++#define BUF ((struct arp_hdr *)&uip_buf[0]) ++#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Initialize the ARP module. ++ * ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_init(void) ++{ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ memset(arp_table[i].ipaddr, 0, 4); ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Periodic ARP processing function. ++ * ++ * This function performs periodic timer processing in the ARP module ++ * and should be called at regular intervals. The recommended interval ++ * is 10 seconds between the calls. ++ * ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_timer(void) ++{ ++ struct arp_entry *tabptr; ++ ++ ++arptime; ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && ++ arptime - tabptr->time >= UIP_ARP_MAXAGE) { ++ memset(tabptr->ipaddr, 0, 4); ++ } ++ } ++ ++} ++/*-----------------------------------------------------------------------------------*/ ++static void ++uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) ++{ ++ register struct arp_entry *tabptr; ++ /* Walk through the ARP mapping table and try to find an entry to ++ update. If none is found, the IP -> MAC address mapping is ++ inserted in the ARP table. */ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ ++ tabptr = &arp_table[i]; ++ /* Only check those entries that are actually in use. */ ++ if(tabptr->ipaddr[0] != 0 && ++ tabptr->ipaddr[1] != 0) { ++ ++ /* Check if the source IP address of the incoming packet matches ++ the IP address in this ARP table entry. */ ++ if(ipaddr[0] == tabptr->ipaddr[0] && ++ ipaddr[1] == tabptr->ipaddr[1]) { ++ ++ /* An old entry found, update this and return. */ ++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); ++ tabptr->time = arptime; ++ ++ return; ++ } ++ } ++ } ++ ++ /* If we get here, no existing ARP table entry was found, so we ++ create one. */ ++ ++ /* First, we try to find an unused entry in the ARP table. */ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(tabptr->ipaddr[0] == 0 && ++ tabptr->ipaddr[1] == 0) { ++ break; ++ } ++ } ++ ++ /* If no unused entry is found, we try to find the oldest entry and ++ throw it away. */ ++ if(i == UIP_ARPTAB_SIZE) { ++ tmpage = 0; ++ c = 0; ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(arptime - tabptr->time > tmpage) { ++ tmpage = arptime - tabptr->time; ++ c = i; ++ } ++ } ++ i = c; ++ } ++ ++ /* Now, i is the ARP table entry which we will fill with the new ++ information. */ ++ memcpy(tabptr->ipaddr, ipaddr, 4); ++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); ++ tabptr->time = arptime; ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * ARP processing for incoming IP packets ++ * ++ * This function should be called by the device driver when an IP ++ * packet has been received. The function will check if the address is ++ * in the ARP cache, and if so the ARP cache entry will be ++ * refreshed. If no ARP cache entry was found, a new one is created. ++ * ++ * This function expects an IP packet with a prepended Ethernet header ++ * in the uip_buf[] buffer, and the length of the packet in the global ++ * variable uip_len. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_ipin(void) ++{ ++ uip_len -= sizeof(struct uip_eth_hdr); ++ ++ /* Only insert/update an entry if the source IP address of the ++ incoming IP packet comes from a host on the local network. */ ++ if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) != ++ (uip_hostaddr[0] & uip_arp_netmask[0])) { ++ return; ++ } ++ if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) != ++ (uip_hostaddr[1] & uip_arp_netmask[1])) { ++ return; ++ } ++ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); ++ ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * ARP processing for incoming ARP packets. ++ * ++ * This function should be called by the device driver when an ARP ++ * packet has been received. The function will act differently ++ * depending on the ARP packet type: if it is a reply for a request ++ * that we previously sent out, the ARP cache will be filled in with ++ * the values from the ARP reply. If the incoming ARP packet is an ARP ++ * request for our IP address, an ARP reply packet is created and put ++ * into the uip_buf[] buffer. ++ * ++ * When the function returns, the value of the global variable uip_len ++ * indicates whether the device driver should send out a packet or ++ * not. If uip_len is zero, no packet should be sent. If uip_len is ++ * non-zero, it contains the length of the outbound packet that is ++ * present in the uip_buf[] buffer. ++ * ++ * This function expects an ARP packet with a prepended Ethernet ++ * header in the uip_buf[] buffer, and the length of the packet in the ++ * global variable uip_len. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_arpin(void) ++{ ++ ++ if(uip_len < sizeof(struct arp_hdr)) { ++ uip_len = 0; ++ return; ++ } ++ ++ uip_len = 0; ++ ++ switch(BUF->opcode) { ++ case HTONS(ARP_REQUEST): ++ /* ARP request. If it asked for our address, we send out a ++ reply. */ ++ if(BUF->dipaddr[0] == uip_hostaddr[0] && ++ BUF->dipaddr[1] == uip_hostaddr[1]) { ++ /* The reply opcode is 2. */ ++ BUF->opcode = HTONS(2); ++ ++ memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); ++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); ++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); ++ ++ BUF->dipaddr[0] = BUF->sipaddr[0]; ++ BUF->dipaddr[1] = BUF->sipaddr[1]; ++ BUF->sipaddr[0] = uip_hostaddr[0]; ++ BUF->sipaddr[1] = uip_hostaddr[1]; ++ ++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); ++ uip_len = sizeof(struct arp_hdr); ++ } ++ break; ++ case HTONS(ARP_REPLY): ++ /* ARP reply. We insert or update the ARP table if it was meant ++ for us. */ ++ if(BUF->dipaddr[0] == uip_hostaddr[0] && ++ BUF->dipaddr[1] == uip_hostaddr[1]) { ++ ++ uip_arp_update(BUF->sipaddr, &BUF->shwaddr); ++ } ++ break; ++ } ++ ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Prepend Ethernet header to an outbound IP packet and see if we need ++ * to send out an ARP request. ++ * ++ * This function should be called before sending out an IP packet. The ++ * function checks the destination IP address of the IP packet to see ++ * what Ethernet MAC address that should be used as a destination MAC ++ * address on the Ethernet. ++ * ++ * If the destination IP address is in the local network (determined ++ * by logical ANDing of netmask and our IP address), the function ++ * checks the ARP cache to see if an entry for the destination IP ++ * address is found. If so, an Ethernet header is prepended and the ++ * function returns. If no ARP cache entry is found for the ++ * destination IP address, the packet in the uip_buf[] is replaced by ++ * an ARP request packet for the IP address. The IP packet is dropped ++ * and it is assumed that they higher level protocols (e.g., TCP) ++ * eventually will retransmit the dropped packet. ++ * ++ * If the destination IP address is not on the local network, the IP ++ * address of the default router is used instead. ++ * ++ * When the function returns, a packet is present in the uip_buf[] ++ * buffer, and the length of the packet is in the global variable ++ * uip_len. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_out(void) ++{ ++ struct arp_entry *tabptr; ++ /* Find the destination IP address in the ARP table and construct ++ the Ethernet header. If the destination IP addres isn't on the ++ local network, we use the default router's IP address instead. ++ ++ If not ARP table entry is found, we overwrite the original IP ++ packet with an ARP request for the IP address. */ ++ ++ /* Check if the destination address is on the local network. */ ++ if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) != ++ (uip_hostaddr[0] & uip_arp_netmask[0]) || ++ (IPBUF->destipaddr[1] & uip_arp_netmask[1]) != ++ (uip_hostaddr[1] & uip_arp_netmask[1])) { ++ /* Destination address was not on the local network, so we need to ++ use the default router's IP address instead of the destination ++ address when determining the MAC address. */ ++ ipaddr[0] = uip_arp_draddr[0]; ++ ipaddr[1] = uip_arp_draddr[1]; ++ } else { ++ /* Else, we use the destination IP address. */ ++ ipaddr[0] = IPBUF->destipaddr[0]; ++ ipaddr[1] = IPBUF->destipaddr[1]; ++ } ++ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(ipaddr[0] == tabptr->ipaddr[0] && ++ ipaddr[1] == tabptr->ipaddr[1]) ++ break; ++ } ++ ++ if(i == UIP_ARPTAB_SIZE) { ++ /* The destination address was not in our ARP table, so we ++ overwrite the IP packet with an ARP request. */ ++ ++ memset(BUF->ethhdr.dest.addr, 0xff, 6); ++ memset(BUF->dhwaddr.addr, 0x00, 6); ++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); ++ ++ BUF->dipaddr[0] = ipaddr[0]; ++ BUF->dipaddr[1] = ipaddr[1]; ++ BUF->sipaddr[0] = uip_hostaddr[0]; ++ BUF->sipaddr[1] = uip_hostaddr[1]; ++ BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ ++ BUF->hwtype = HTONS(ARP_HWTYPE_ETH); ++ BUF->protocol = HTONS(UIP_ETHTYPE_IP); ++ BUF->hwlen = 6; ++ BUF->protolen = 4; ++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); ++ ++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; ++ ++ uip_len = sizeof(struct arp_hdr); ++ return; ++ } ++ ++ /* Build an ethernet header. */ ++ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); ++ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ ++ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); ++ ++ uip_len += sizeof(struct uip_eth_hdr); ++} ++/*-----------------------------------------------------------------------------------*/ ++ ++/** @} */ ++/** @} */ +--- /dev/null ++++ b/net/uip-0.9/uip_arp.h +@@ -0,0 +1,201 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \addtogroup uiparp ++ * @{ ++ */ ++ ++/** ++ * \file ++ * Macros and definitions for the ARP module. ++ * \author Adam Dunkels ++ */ ++ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_ARP_H__ ++#define __UIP_ARP_H__ ++ ++#include "uip.h" ++ ++ ++/** ++ * Representation of a 48-bit Ethernet address. ++ */ ++struct uip_eth_addr { ++ u8_t addr[6]; ++}; ++ ++extern struct uip_eth_addr uip_ethaddr; ++ ++/** ++ * The Ethernet header. ++ */ ++struct uip_eth_hdr { ++ struct uip_eth_addr dest; ++ struct uip_eth_addr src; ++ u16_t type; ++}; ++ ++#define UIP_ETHTYPE_ARP 0x0806 ++#define UIP_ETHTYPE_IP 0x0800 ++#define UIP_ETHTYPE_IP6 0x86dd ++ ++ ++/* The uip_arp_init() function must be called before any of the other ++ ARP functions. */ ++void uip_arp_init(void); ++ ++/* The uip_arp_ipin() function should be called whenever an IP packet ++ arrives from the Ethernet. This function refreshes the ARP table or ++ inserts a new mapping if none exists. The function assumes that an ++ IP packet with an Ethernet header is present in the uip_buf buffer ++ and that the length of the packet is in the uip_len variable. */ ++void uip_arp_ipin(void); ++ ++/* The uip_arp_arpin() should be called when an ARP packet is received ++ by the Ethernet driver. This function also assumes that the ++ Ethernet frame is present in the uip_buf buffer. When the ++ uip_arp_arpin() function returns, the contents of the uip_buf ++ buffer should be sent out on the Ethernet if the uip_len variable ++ is > 0. */ ++void uip_arp_arpin(void); ++ ++/* The uip_arp_out() function should be called when an IP packet ++ should be sent out on the Ethernet. This function creates an ++ Ethernet header before the IP header in the uip_buf buffer. The ++ Ethernet header will have the correct Ethernet MAC destination ++ address filled in if an ARP table entry for the destination IP ++ address (or the IP address of the default router) is present. If no ++ such table entry is found, the IP packet is overwritten with an ARP ++ request and we rely on TCP to retransmit the packet that was ++ overwritten. In any case, the uip_len variable holds the length of ++ the Ethernet frame that should be transmitted. */ ++void uip_arp_out(void); ++ ++/* The uip_arp_timer() function should be called every ten seconds. It ++ is responsible for flushing old entries in the ARP table. */ ++void uip_arp_timer(void); ++ ++/** @} */ ++ ++/** ++ * \addtogroup uipconffunc ++ * @{ ++ */ ++ ++/** ++ * Set the default router's IP address. ++ * ++ * \param addr A pointer to a 4-byte array containing the IP address ++ * of the default router. ++ * ++ * \hideinitializer ++ */ ++#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \ ++ uip_arp_draddr[1] = addr[1]; } while(0) ++ ++/** ++ * Set the netmask. ++ * ++ * \param addr A pointer to a 4-byte array containing the IP address ++ * of the netmask. ++ * ++ * \hideinitializer ++ */ ++#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \ ++ uip_arp_netmask[1] = addr[1]; } while(0) ++ ++ ++/** ++ * Get the default router's IP address. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the IP address of the default router. ++ * ++ * \hideinitializer ++ */ ++#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \ ++ addr[1] = uip_arp_draddr[1]; } while(0) ++ ++/** ++ * Get the netmask. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the value of the netmask. ++ * ++ * \hideinitializer ++ */ ++#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \ ++ addr[1] = uip_arp_netmask[1]; } while(0) ++ ++ ++/** ++ * Specifiy the Ethernet MAC address. ++ * ++ * The ARP code needs to know the MAC address of the Ethernet card in ++ * order to be able to respond to ARP queries and to generate working ++ * Ethernet headers. ++ * ++ * \note This macro only specifies the Ethernet MAC address to the ARP ++ * code. It cannot be used to change the MAC address of the Ethernet ++ * card. ++ * ++ * \param eaddr A pointer to a struct uip_eth_addr containing the ++ * Ethernet MAC address of the Ethernet card. ++ * ++ * \hideinitializer ++ */ ++#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ ++ uip_ethaddr.addr[1] = eaddr.addr[1];\ ++ uip_ethaddr.addr[2] = eaddr.addr[2];\ ++ uip_ethaddr.addr[3] = eaddr.addr[3];\ ++ uip_ethaddr.addr[4] = eaddr.addr[4];\ ++ uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) ++ ++/** @} */ ++ ++/** ++ * \internal Internal variables that are set using the macros ++ * uip_setdraddr and uip_setnetmask. ++ */ ++extern u16_t uip_arp_draddr[2], uip_arp_netmask[2]; ++#endif /* __UIP_ARP_H__ */ ++ ++ +--- /dev/null ++++ b/net/uip-0.9/uip.c +@@ -0,0 +1,1503 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \file ++ * The uIP TCP/IP stack code. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $ ++ * ++ */ ++ ++/* ++This is a small implementation of the IP and TCP protocols (as well as ++some basic ICMP stuff). The implementation couples the IP, TCP and the ++application layers very tightly. To keep the size of the compiled code ++down, this code also features heavy usage of the goto statement. ++ ++The principle is that we have a small buffer, called the uip_buf, in ++which the device driver puts an incoming packet. The TCP/IP stack ++parses the headers in the packet, and calls upon the application. If ++the remote host has sent data to the application, this data is present ++in the uip_buf and the application read the data from there. It is up ++to the application to put this data into a byte stream if needed. The ++application will not be fed with data that is out of sequence. ++ ++If the application whishes to send data to the peer, it should put its ++data into the uip_buf, 40 bytes from the start of the buffer. The ++TCP/IP stack will calculate the checksums, and fill in the necessary ++header fields and finally send the packet back to the peer. ++*/ ++ ++#include "uip.h" ++#include "uipopt.h" ++#include "uip_arch.h" ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Variable definitions. */ ++ ++ ++/* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */ ++#if UIP_FIXEDADDR > 0 ++const unsigned short int uip_hostaddr[2] = ++ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), ++ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; ++const unsigned short int uip_arp_draddr[2] = ++ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), ++ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; ++const unsigned short int uip_arp_netmask[2] = ++ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), ++ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; ++#else ++unsigned short int uip_hostaddr[2]; ++unsigned short int uip_arp_draddr[2], uip_arp_netmask[2]; ++#endif /* UIP_FIXEDADDR */ ++ ++u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains ++ incoming packets. */ ++volatile u8_t *uip_appdata; /* The uip_appdata pointer points to ++ application data. */ ++volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the ++ application data which is to be sent. */ ++#if UIP_URGDATA > 0 ++volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to ++ urgent data (out-of-band data), if ++ present. */ ++volatile u8_t uip_urglen, uip_surglen; ++#endif /* UIP_URGDATA > 0 */ ++ ++volatile unsigned short int uip_len, uip_slen; ++ /* The uip_len is either 8 or 16 bits, ++ depending on the maximum packet ++ size. */ ++ ++volatile u8_t uip_flags; /* The uip_flags variable is used for ++ communication between the TCP/IP stack ++ and the application program. */ ++struct uip_conn *uip_conn; /* uip_conn always points to the current ++ connection. */ ++ ++struct uip_conn uip_conns[UIP_CONNS]; ++ /* The uip_conns array holds all TCP ++ connections. */ ++unsigned short int uip_listenports[UIP_LISTENPORTS]; ++ /* The uip_listenports list all currently ++ listning ports. */ ++#if UIP_UDP ++struct uip_udp_conn *uip_udp_conn; ++struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; ++#endif /* UIP_UDP */ ++ ++ ++static unsigned short int ipid; /* Ths ipid variable is an increasing ++ number that is used for the IP ID ++ field. */ ++ ++static u8_t iss[4]; /* The iss variable is used for the TCP ++ initial sequence number. */ ++ ++#if UIP_ACTIVE_OPEN ++static unsigned short int lastport; /* Keeps track of the last port used for ++ a new connection. */ ++#endif /* UIP_ACTIVE_OPEN */ ++ ++/* Temporary variables. */ ++volatile u8_t uip_acc32[4]; ++static u8_t c, opt; ++static unsigned short int tmp16; ++ ++/* Structures and definitions. */ ++#define TCP_FIN 0x01 ++#define TCP_SYN 0x02 ++#define TCP_RST 0x04 ++#define TCP_PSH 0x08 ++#define TCP_ACK 0x10 ++#define TCP_URG 0x20 ++#define TCP_CTL 0x3f ++ ++#define ICMP_ECHO_REPLY 0 ++#define ICMP_ECHO 8 ++ ++/* Macros. */ ++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0]) ++#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++ ++#if UIP_STATISTICS == 1 ++struct uip_stats uip_stat; ++#define UIP_STAT(s) s ++#else ++#define UIP_STAT(s) ++#endif /* UIP_STATISTICS == 1 */ ++ ++#if UIP_LOGGING == 1 ++extern void puts(const char *s); ++#define UIP_LOG(m) puts(m) ++#else ++#define UIP_LOG(m) ++#endif /* UIP_LOGGING == 1 */ ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_init(void) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ uip_listenports[c] = 0; ++ } ++ for(c = 0; c < UIP_CONNS; ++c) { ++ uip_conns[c].tcpstateflags = CLOSED; ++ } ++#if UIP_ACTIVE_OPEN ++ lastport = 1024; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++#if UIP_UDP ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ uip_udp_conns[c].lport = 0; ++ } ++#endif /* UIP_UDP */ ++ ++ ++ /* IPv4 initialization. */ ++#if UIP_FIXEDADDR == 0 ++ uip_hostaddr[0] = uip_hostaddr[1] = 0; ++#endif /* UIP_FIXEDADDR */ ++ ++} ++/*-----------------------------------------------------------------------------------*/ ++#if UIP_ACTIVE_OPEN ++struct uip_conn * ++uip_connect(unsigned short int *ripaddr, unsigned short int rport) ++{ ++ register struct uip_conn *conn, *cconn; ++ ++ /* Find an unused local port. */ ++ again: ++ ++lastport; ++ ++ if(lastport >= 32000) { ++ lastport = 4096; ++ } ++ ++ /* Check if this port is already in use, and if so try to find ++ another one. */ ++ for(c = 0; c < UIP_CONNS; ++c) { ++ conn = &uip_conns[c]; ++ if(conn->tcpstateflags != CLOSED && ++ conn->lport == htons(lastport)) { ++ goto again; ++ } ++ } ++ ++ ++ conn = 0; ++ for(c = 0; c < UIP_CONNS; ++c) { ++ cconn = &uip_conns[c]; ++ if(cconn->tcpstateflags == CLOSED) { ++ conn = cconn; ++ break; ++ } ++ if(cconn->tcpstateflags == TIME_WAIT) { ++ if(conn == 0 || ++ cconn->timer > uip_conn->timer) { ++ conn = cconn; ++ } ++ } ++ } ++ ++ if(conn == 0) { ++ return 0; ++ } ++ ++ conn->tcpstateflags = SYN_SENT; ++ ++ conn->snd_nxt[0] = iss[0]; ++ conn->snd_nxt[1] = iss[1]; ++ conn->snd_nxt[2] = iss[2]; ++ conn->snd_nxt[3] = iss[3]; ++ ++ conn->initialmss = conn->mss = UIP_TCP_MSS; ++ ++ conn->len = 1; /* TCP length of the SYN is one. */ ++ conn->nrtx = 0; ++ conn->timer = 1; /* Send the SYN next time around. */ ++ conn->rto = UIP_RTO; ++ conn->sa = 0; ++ conn->sv = 16; ++ conn->lport = htons(lastport); ++ conn->rport = rport; ++ conn->ripaddr[0] = ripaddr[0]; ++ conn->ripaddr[1] = ripaddr[1]; ++ ++ return conn; ++} ++#endif /* UIP_ACTIVE_OPEN */ ++/*-----------------------------------------------------------------------------------*/ ++#if UIP_UDP ++struct uip_udp_conn * ++uip_udp_new(unsigned short int *ripaddr, unsigned short int rport) ++{ ++ register struct uip_udp_conn *conn; ++ ++ /* Find an unused local port. */ ++ again: ++ ++lastport; ++ ++ if(lastport >= 32000) { ++ lastport = 4096; ++ } ++ ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ if(uip_udp_conns[c].lport == lastport) { ++ goto again; ++ } ++ } ++ ++ ++ conn = 0; ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ if(uip_udp_conns[c].lport == 0) { ++ conn = &uip_udp_conns[c]; ++ break; ++ } ++ } ++ ++ if(conn == 0) { ++ return 0; ++ } ++ ++ conn->lport = HTONS(lastport); ++ conn->rport = HTONS(rport); ++ conn->ripaddr[0] = ripaddr[0]; ++ conn->ripaddr[1] = ripaddr[1]; ++ ++ return conn; ++} ++#endif /* UIP_UDP */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_unlisten(unsigned short int port) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(uip_listenports[c] == port) { ++ uip_listenports[c] = 0; ++ return; ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_listen(unsigned short int port) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(uip_listenports[c] == 0) { ++ uip_listenports[c] = port; ++ return; ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++/* XXX: IP fragment reassembly: not well-tested. */ ++ ++#if UIP_REASSEMBLY ++#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) ++static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; ++static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; ++static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, ++ 0x0f, 0x07, 0x03, 0x01}; ++static unsigned short int uip_reasslen; ++static u8_t uip_reassflags; ++#define UIP_REASS_FLAG_LASTFRAG 0x01 ++static u8_t uip_reasstmr; ++ ++#define IP_HLEN 20 ++#define IP_MF 0x20 ++ ++static u8_t ++uip_reass(void) ++{ ++ unsigned short int offset, len; ++ unsigned short int i; ++ ++ /* If ip_reasstmr is zero, no packet is present in the buffer, so we ++ write the IP header of the fragment into the reassembly ++ buffer. The timer is updated with the maximum age. */ ++ if(uip_reasstmr == 0) { ++ memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN); ++ uip_reasstmr = UIP_REASS_MAXAGE; ++ uip_reassflags = 0; ++ /* Clear the bitmap. */ ++ memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0); ++ } ++ ++ /* Check if the incoming fragment matches the one currently present ++ in the reasembly buffer. If so, we proceed with copying the ++ fragment into the buffer. */ ++ if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && ++ BUF->srcipaddr[1] == FBUF->srcipaddr[1] && ++ BUF->destipaddr[0] == FBUF->destipaddr[0] && ++ BUF->destipaddr[1] == FBUF->destipaddr[1] && ++ BUF->ipid[0] == FBUF->ipid[0] && ++ BUF->ipid[1] == FBUF->ipid[1]) { ++ ++ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; ++ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; ++ ++ /* If the offset or the offset + fragment length overflows the ++ reassembly buffer, we discard the entire packet. */ ++ if(offset > UIP_REASS_BUFSIZE || ++ offset + len > UIP_REASS_BUFSIZE) { ++ uip_reasstmr = 0; ++ goto nullreturn; ++ } ++ ++ /* Copy the fragment into the reassembly buffer, at the right ++ offset. */ ++ memcpy(&uip_reassbuf[IP_HLEN + offset], ++ (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), ++ len); ++ ++ /* Update the bitmap. */ ++ if(offset / (8 * 8) == (offset + len) / (8 * 8)) { ++ /* If the two endpoints are in the same byte, we only update ++ that byte. */ ++ ++ uip_reassbitmap[offset / (8 * 8)] |= ++ bitmap_bits[(offset / 8 ) & 7] & ++ ~bitmap_bits[((offset + len) / 8 ) & 7]; ++ } else { ++ /* If the two endpoints are in different bytes, we update the ++ bytes in the endpoints and fill the stuff inbetween with ++ 0xff. */ ++ uip_reassbitmap[offset / (8 * 8)] |= ++ bitmap_bits[(offset / 8 ) & 7]; ++ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { ++ uip_reassbitmap[i] = 0xff; ++ } ++ uip_reassbitmap[(offset + len) / (8 * 8)] |= ++ ~bitmap_bits[((offset + len) / 8 ) & 7]; ++ } ++ ++ /* If this fragment has the More Fragments flag set to zero, we ++ know that this is the last fragment, so we can calculate the ++ size of the entire packet. We also set the ++ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received ++ the final fragment. */ ++ ++ if((BUF->ipoffset[0] & IP_MF) == 0) { ++ uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; ++ uip_reasslen = offset + len; ++ } ++ ++ /* Finally, we check if we have a full packet in the buffer. We do ++ this by checking if we have the last fragment and if all bits ++ in the bitmap are set. */ ++ if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { ++ /* Check all bytes up to and including all but the last byte in ++ the bitmap. */ ++ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { ++ if(uip_reassbitmap[i] != 0xff) { ++ goto nullreturn; ++ } ++ } ++ /* Check the last byte in the bitmap. It should contain just the ++ right amount of bits. */ ++ if(uip_reassbitmap[uip_reasslen / (8 * 8)] != ++ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { ++ goto nullreturn; ++ } ++ ++ /* If we have come this far, we have a full packet in the ++ buffer, so we allocate a pbuf and copy the packet into it. We ++ also reset the timer. */ ++ uip_reasstmr = 0; ++ memcpy(BUF, FBUF, uip_reasslen); ++ ++ /* Pretend to be a "normal" (i.e., not fragmented) IP packet ++ from now on. */ ++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; ++ BUF->len[0] = uip_reasslen >> 8; ++ BUF->len[1] = uip_reasslen & 0xff; ++ BUF->ipchksum = 0; ++ BUF->ipchksum = ~(uip_ipchksum()); ++ ++ return uip_reasslen; ++ } ++ } ++ ++ nullreturn: ++ return 0; ++} ++#endif /* UIP_REASSEMBL */ ++/*-----------------------------------------------------------------------------------*/ ++static void ++uip_add_rcv_nxt(unsigned short int n) ++{ ++ uip_add32(uip_conn->rcv_nxt, n); ++ uip_conn->rcv_nxt[0] = uip_acc32[0]; ++ uip_conn->rcv_nxt[1] = uip_acc32[1]; ++ uip_conn->rcv_nxt[2] = uip_acc32[2]; ++ uip_conn->rcv_nxt[3] = uip_acc32[3]; ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_process(u8_t flag) ++{ ++ register struct uip_conn *uip_connr = uip_conn; ++ ++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; ++ ++ ++ /* Check if we were invoked because of the perodic timer fireing. */ ++ if(flag == UIP_TIMER) { ++#if UIP_REASSEMBLY ++ if(uip_reasstmr != 0) { ++ --uip_reasstmr; ++ } ++#endif /* UIP_REASSEMBLY */ ++ /* Increase the initial sequence number. */ ++ if(++iss[3] == 0) { ++ if(++iss[2] == 0) { ++ if(++iss[1] == 0) { ++ ++iss[0]; ++ } ++ } ++ } ++ uip_len = 0; ++ if(uip_connr->tcpstateflags == TIME_WAIT || ++ uip_connr->tcpstateflags == FIN_WAIT_2) { ++ ++(uip_connr->timer); ++ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { ++ uip_connr->tcpstateflags = CLOSED; ++ } ++ } else if(uip_connr->tcpstateflags != CLOSED) { ++ /* If the connection has outstanding data, we increase the ++ connection's timer and see if it has reached the RTO value ++ in which case we retransmit. */ ++ if(uip_outstanding(uip_connr)) { ++ if(uip_connr->timer-- == 0) { ++ if(uip_connr->nrtx == UIP_MAXRTX || ++ ((uip_connr->tcpstateflags == SYN_SENT || ++ uip_connr->tcpstateflags == SYN_RCVD) && ++ uip_connr->nrtx == UIP_MAXSYNRTX)) { ++ uip_connr->tcpstateflags = CLOSED; ++ ++ /* We call UIP_APPCALL() with uip_flags set to ++ UIP_TIMEDOUT to inform the application that the ++ connection has timed out. */ ++ uip_flags = UIP_TIMEDOUT; ++ UIP_APPCALL(); ++ ++ /* We also send a reset packet to the remote host. */ ++ BUF->flags = TCP_RST | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ /* Exponential backoff. */ ++ uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? ++ 4: ++ uip_connr->nrtx); ++ ++(uip_connr->nrtx); ++ ++ /* Ok, so we need to retransmit. We do this differently ++ depending on which state we are in. In ESTABLISHED, we ++ call upon the application so that it may prepare the ++ data for the retransmit. In SYN_RCVD, we resend the ++ SYNACK that we sent earlier and in LAST_ACK we have to ++ retransmit our FINACK. */ ++ UIP_STAT(++uip_stat.tcp.rexmit); ++ switch(uip_connr->tcpstateflags & TS_MASK) { ++ case SYN_RCVD: ++ /* In the SYN_RCVD state, we should retransmit our ++ SYNACK. */ ++ goto tcp_send_synack; ++ ++#if UIP_ACTIVE_OPEN ++ case SYN_SENT: ++ /* In the SYN_SENT state, we retransmit out SYN. */ ++ BUF->flags = 0; ++ goto tcp_send_syn; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ case ESTABLISHED: ++ /* In the ESTABLISHED state, we call upon the application ++ to do the actual retransmit after which we jump into ++ the code for sending out the packet (the apprexmit ++ label). */ ++ uip_len = 0; ++ uip_slen = 0; ++ uip_flags = UIP_REXMIT; ++ UIP_APPCALL(); ++ goto apprexmit; ++ ++ case FIN_WAIT_1: ++ case CLOSING: ++ case LAST_ACK: ++ /* In all these states we should retransmit a FINACK. */ ++ goto tcp_send_finack; ++ ++ } ++ } ++ } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) { ++ /* If there was no need for a retransmission, we poll the ++ application for new data. */ ++ uip_len = 0; ++ uip_slen = 0; ++ uip_flags = UIP_POLL; ++ UIP_APPCALL(); ++ goto appsend; ++ } ++ } ++ goto drop; ++ } ++#if UIP_UDP ++ if(flag == UIP_UDP_TIMER) { ++ if(uip_udp_conn->lport != 0) { ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; ++ uip_len = uip_slen = 0; ++ uip_flags = UIP_POLL; ++ UIP_UDP_APPCALL(); ++ goto udp_send; ++ } else { ++ goto drop; ++ } ++ } ++#endif ++ ++ /* This is where the input processing starts. */ ++ UIP_STAT(++uip_stat.ip.recv); ++ ++ ++ /* Start of IPv4 input header processing code. */ ++ ++ /* Check validity of the IP header. */ ++ if(BUF->vhl != 0x45) { /* IP version and header length. */ ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.vhlerr); ++ UIP_LOG("ip: invalid version or header length."); ++ goto drop; ++ } ++ ++ /* Check the size of the packet. If the size reported to us in ++ uip_len doesn't match the size reported in the IP header, there ++ has been a transmission error and we drop the packet. */ ++ ++ if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */ ++ uip_len = (uip_len & 0xff) | (BUF->len[0] << 8); ++ } ++ if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */ ++ uip_len = (uip_len & 0xff00) | BUF->len[1]; ++ } ++ ++ /* Check the fragment flag. */ ++ if((BUF->ipoffset[0] & 0x3f) != 0 || ++ BUF->ipoffset[1] != 0) { ++#if UIP_REASSEMBLY ++ uip_len = uip_reass(); ++ if(uip_len == 0) { ++ goto drop; ++ } ++#else ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.fragerr); ++ UIP_LOG("ip: fragment dropped."); ++ goto drop; ++#endif /* UIP_REASSEMBLY */ ++ } ++ ++ /* If we are configured to use ping IP address configuration and ++ hasn't been assigned an IP address yet, we accept all ICMP ++ packets. */ ++#if UIP_PINGADDRCONF ++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { ++ if(BUF->proto == UIP_PROTO_ICMP) { ++ UIP_LOG("ip: possible ping config packet received."); ++ goto icmp_input; ++ } else { ++ UIP_LOG("ip: packet dropped since no address assigned."); ++ goto drop; ++ } ++ } ++#endif /* UIP_PINGADDRCONF */ ++ ++ /* Check if the packet is destined for our IP address. */ ++ if(BUF->destipaddr[0] != uip_hostaddr[0]) { ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_LOG("ip: packet not for us."); ++ goto drop; ++ } ++ if(BUF->destipaddr[1] != uip_hostaddr[1]) { ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_LOG("ip: packet not for us."); ++ goto drop; ++ } ++ ++ if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header ++ checksum. */ ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.chkerr); ++ UIP_LOG("ip: bad checksum."); ++ goto drop; ++ } ++ ++ if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump ++ to the tcp_input label. */ ++ goto tcp_input; ++ ++#if UIP_UDP ++ if(BUF->proto == UIP_PROTO_UDP) ++ goto udp_input; ++#endif /* UIP_UDP */ ++ ++ if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from ++ here. */ ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.protoerr); ++ UIP_LOG("ip: neither tcp nor icmp."); ++ goto drop; ++ } ++ ++ //icmp_input: ++ UIP_STAT(++uip_stat.icmp.recv); ++ ++ /* ICMP echo (i.e., ping) processing. This is simple, we only change ++ the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP ++ checksum before we return the packet. */ ++ if(ICMPBUF->type != ICMP_ECHO) { ++ UIP_STAT(++uip_stat.icmp.drop); ++ UIP_STAT(++uip_stat.icmp.typeerr); ++ UIP_LOG("icmp: not icmp echo."); ++ goto drop; ++ } ++ ++ /* If we are configured to use ping IP address assignment, we use ++ the destination IP address of this ping packet and assign it to ++ ourself. */ ++#if UIP_PINGADDRCONF ++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { ++ uip_hostaddr[0] = BUF->destipaddr[0]; ++ uip_hostaddr[1] = BUF->destipaddr[1]; ++ } ++#endif /* UIP_PINGADDRCONF */ ++ ++ ICMPBUF->type = ICMP_ECHO_REPLY; ++ ++ if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { ++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; ++ } else { ++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); ++ } ++ ++ /* Swap IP addresses. */ ++ tmp16 = BUF->destipaddr[0]; ++ BUF->destipaddr[0] = BUF->srcipaddr[0]; ++ BUF->srcipaddr[0] = tmp16; ++ tmp16 = BUF->destipaddr[1]; ++ BUF->destipaddr[1] = BUF->srcipaddr[1]; ++ BUF->srcipaddr[1] = tmp16; ++ ++ UIP_STAT(++uip_stat.icmp.sent); ++ goto send; ++ ++ /* End of IPv4 input header processing code. */ ++ ++ ++#if UIP_UDP ++ /* UDP input processing. */ ++ udp_input: ++ /* UDP processing is really just a hack. We don't do anything to the ++ UDP/IP headers, but let the UDP application do all the hard ++ work. If the application sets uip_slen, it has a packet to ++ send. */ ++#if UIP_UDP_CHECKSUMS ++ if(uip_udpchksum() != 0xffff) { ++ UIP_STAT(++uip_stat.udp.drop); ++ UIP_STAT(++uip_stat.udp.chkerr); ++ UIP_LOG("udp: bad checksum."); ++ goto drop; ++ } ++#endif /* UIP_UDP_CHECKSUMS */ ++ ++ /* Demultiplex this UDP packet between the UDP "connections". */ ++ for(uip_udp_conn = &uip_udp_conns[0]; ++ uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; ++ ++uip_udp_conn) { ++ if(uip_udp_conn->lport != 0 && ++ UDPBUF->destport == uip_udp_conn->lport && ++ (uip_udp_conn->rport == 0 || ++ UDPBUF->srcport == uip_udp_conn->rport) && ++ BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] && ++ BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) { ++ goto udp_found; ++ } ++ } ++ goto drop; ++ ++ udp_found: ++ uip_len = uip_len - 28; ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; ++ uip_flags = UIP_NEWDATA; ++ uip_slen = 0; ++ UIP_UDP_APPCALL(); ++ udp_send: ++ if(uip_slen == 0) { ++ goto drop; ++ } ++ uip_len = uip_slen + 28; ++ ++ BUF->len[0] = (uip_len >> 8); ++ BUF->len[1] = (uip_len & 0xff); ++ ++ BUF->proto = UIP_PROTO_UDP; ++ ++ UDPBUF->udplen = HTONS(uip_slen + 8); ++ UDPBUF->udpchksum = 0; ++#if UIP_UDP_CHECKSUMS ++ /* Calculate UDP checksum. */ ++ UDPBUF->udpchksum = ~(uip_udpchksum()); ++ if(UDPBUF->udpchksum == 0) { ++ UDPBUF->udpchksum = 0xffff; ++ } ++#endif /* UIP_UDP_CHECKSUMS */ ++ ++ BUF->srcport = uip_udp_conn->lport; ++ BUF->destport = uip_udp_conn->rport; ++ ++ BUF->srcipaddr[0] = uip_hostaddr[0]; ++ BUF->srcipaddr[1] = uip_hostaddr[1]; ++ BUF->destipaddr[0] = uip_udp_conn->ripaddr[0]; ++ BUF->destipaddr[1] = uip_udp_conn->ripaddr[1]; ++ ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 40]; ++ goto ip_send_nolen; ++#endif /* UIP_UDP */ ++ ++ /* TCP input processing. */ ++ tcp_input: ++ UIP_STAT(++uip_stat.tcp.recv); ++ ++ /* Start of TCP input header processing code. */ ++ ++ if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP ++ checksum. */ ++ UIP_STAT(++uip_stat.tcp.drop); ++ UIP_STAT(++uip_stat.tcp.chkerr); ++ UIP_LOG("tcp: bad checksum."); ++ goto drop; ++ } ++ ++ /* Demultiplex this segment. */ ++ /* First check any active connections. */ ++ for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) { ++ if(uip_connr->tcpstateflags != CLOSED && ++ BUF->destport == uip_connr->lport && ++ BUF->srcport == uip_connr->rport && ++ BUF->srcipaddr[0] == uip_connr->ripaddr[0] && ++ BUF->srcipaddr[1] == uip_connr->ripaddr[1]) { ++ goto found; ++ } ++ } ++ ++ /* If we didn't find and active connection that expected the packet, ++ either this packet is an old duplicate, or this is a SYN packet ++ destined for a connection in LISTEN. If the SYN flag isn't set, ++ it is an old packet and we send a RST. */ ++ if((BUF->flags & TCP_CTL) != TCP_SYN) ++ goto reset; ++ ++ tmp16 = BUF->destport; ++ /* Next, check listening connections. */ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(tmp16 == uip_listenports[c]) ++ goto found_listen; ++ } ++ ++ /* No matching connection found, so we send a RST packet. */ ++ UIP_STAT(++uip_stat.tcp.synrst); ++ reset: ++ ++ /* We do not send resets in response to resets. */ ++ if(BUF->flags & TCP_RST) ++ goto drop; ++ ++ UIP_STAT(++uip_stat.tcp.rst); ++ ++ BUF->flags = TCP_RST | TCP_ACK; ++ uip_len = 40; ++ BUF->tcpoffset = 5 << 4; ++ ++ /* Flip the seqno and ackno fields in the TCP header. */ ++ c = BUF->seqno[3]; ++ BUF->seqno[3] = BUF->ackno[3]; ++ BUF->ackno[3] = c; ++ ++ c = BUF->seqno[2]; ++ BUF->seqno[2] = BUF->ackno[2]; ++ BUF->ackno[2] = c; ++ ++ c = BUF->seqno[1]; ++ BUF->seqno[1] = BUF->ackno[1]; ++ BUF->ackno[1] = c; ++ ++ c = BUF->seqno[0]; ++ BUF->seqno[0] = BUF->ackno[0]; ++ BUF->ackno[0] = c; ++ ++ /* We also have to increase the sequence number we are ++ acknowledging. If the least significant byte overflowed, we need ++ to propagate the carry to the other bytes as well. */ ++ if(++BUF->ackno[3] == 0) { ++ if(++BUF->ackno[2] == 0) { ++ if(++BUF->ackno[1] == 0) { ++ ++BUF->ackno[0]; ++ } ++ } ++ } ++ ++ /* Swap port numbers. */ ++ tmp16 = BUF->srcport; ++ BUF->srcport = BUF->destport; ++ BUF->destport = tmp16; ++ ++ /* Swap IP addresses. */ ++ tmp16 = BUF->destipaddr[0]; ++ BUF->destipaddr[0] = BUF->srcipaddr[0]; ++ BUF->srcipaddr[0] = tmp16; ++ tmp16 = BUF->destipaddr[1]; ++ BUF->destipaddr[1] = BUF->srcipaddr[1]; ++ BUF->srcipaddr[1] = tmp16; ++ ++ ++ /* And send out the RST packet! */ ++ goto tcp_send_noconn; ++ ++ /* This label will be jumped to if we matched the incoming packet ++ with a connection in LISTEN. In that case, we should create a new ++ connection and send a SYNACK in return. */ ++ found_listen: ++ /* First we check if there are any connections avaliable. Unused ++ connections are kept in the same table as used connections, but ++ unused ones have the tcpstate set to CLOSED. Also, connections in ++ TIME_WAIT are kept track of and we'll use the oldest one if no ++ CLOSED connections are found. Thanks to Eddie C. Dost for a very ++ nice algorithm for the TIME_WAIT search. */ ++ uip_connr = 0; ++ for(c = 0; c < UIP_CONNS; ++c) { ++ if(uip_conns[c].tcpstateflags == CLOSED) { ++ uip_connr = &uip_conns[c]; ++ break; ++ } ++ if(uip_conns[c].tcpstateflags == TIME_WAIT) { ++ if(uip_connr == 0 || ++ uip_conns[c].timer > uip_connr->timer) { ++ uip_connr = &uip_conns[c]; ++ } ++ } ++ } ++ ++ if(uip_connr == 0) { ++ /* All connections are used already, we drop packet and hope that ++ the remote end will retransmit the packet at a time when we ++ have more spare connections. */ ++ UIP_STAT(++uip_stat.tcp.syndrop); ++ UIP_LOG("tcp: found no unused connections."); ++ goto drop; ++ } ++ uip_conn = uip_connr; ++ ++ /* Fill in the necessary fields for the new connection. */ ++ uip_connr->rto = uip_connr->timer = UIP_RTO; ++ uip_connr->sa = 0; ++ uip_connr->sv = 4; ++ uip_connr->nrtx = 0; ++ uip_connr->lport = BUF->destport; ++ uip_connr->rport = BUF->srcport; ++ uip_connr->ripaddr[0] = BUF->srcipaddr[0]; ++ uip_connr->ripaddr[1] = BUF->srcipaddr[1]; ++ uip_connr->tcpstateflags = SYN_RCVD; ++ ++ uip_connr->snd_nxt[0] = iss[0]; ++ uip_connr->snd_nxt[1] = iss[1]; ++ uip_connr->snd_nxt[2] = iss[2]; ++ uip_connr->snd_nxt[3] = iss[3]; ++ uip_connr->len = 1; ++ ++ /* rcv_nxt should be the seqno from the incoming packet + 1. */ ++ uip_connr->rcv_nxt[3] = BUF->seqno[3]; ++ uip_connr->rcv_nxt[2] = BUF->seqno[2]; ++ uip_connr->rcv_nxt[1] = BUF->seqno[1]; ++ uip_connr->rcv_nxt[0] = BUF->seqno[0]; ++ uip_add_rcv_nxt(1); ++ ++ /* Parse the TCP MSS option, if present. */ ++ if((BUF->tcpoffset & 0xf0) > 0x50) { ++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { ++ opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; ++ if(opt == 0x00) { ++ /* End of options. */ ++ break; ++ } else if(opt == 0x01) { ++ ++c; ++ /* NOP option. */ ++ } else if(opt == 0x02 && ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { ++ /* An MSS option with the right option length. */ ++ tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | ++ (unsigned short int)uip_buf[40 + UIP_LLH_LEN + 3 + c]; ++ uip_connr->initialmss = uip_connr->mss = ++ tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; ++ ++ /* And we are done processing options. */ ++ break; ++ } else { ++ /* All other options have a length field, so that we easily ++ can skip past them. */ ++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { ++ /* If the length field is zero, the options are malformed ++ and we don't process them further. */ ++ break; ++ } ++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; ++ } ++ } ++ } ++ ++ /* Our response will be a SYNACK. */ ++#if UIP_ACTIVE_OPEN ++ tcp_send_synack: ++ BUF->flags = TCP_ACK; ++ ++ tcp_send_syn: ++ BUF->flags |= TCP_SYN; ++#else /* UIP_ACTIVE_OPEN */ ++ tcp_send_synack: ++ BUF->flags = TCP_SYN | TCP_ACK; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ /* We send out the TCP Maximum Segment Size option with our ++ SYNACK. */ ++ BUF->optdata[0] = 2; ++ BUF->optdata[1] = 4; ++ BUF->optdata[2] = (UIP_TCP_MSS) / 256; ++ BUF->optdata[3] = (UIP_TCP_MSS) & 255; ++ uip_len = 44; ++ BUF->tcpoffset = 6 << 4; ++ goto tcp_send; ++ ++ /* This label will be jumped to if we found an active connection. */ ++ found: ++ uip_conn = uip_connr; ++ uip_flags = 0; ++ ++ /* We do a very naive form of TCP reset processing; we just accept ++ any RST and kill our connection. We should in fact check if the ++ sequence number of this reset is wihtin our advertised window ++ before we accept the reset. */ ++ if(BUF->flags & TCP_RST) { ++ uip_connr->tcpstateflags = CLOSED; ++ UIP_LOG("tcp: got reset, aborting connection."); ++ uip_flags = UIP_ABORT; ++ UIP_APPCALL(); ++ goto drop; ++ } ++ /* Calculated the length of the data, if the application has sent ++ any data to us. */ ++ c = (BUF->tcpoffset >> 4) << 2; ++ /* uip_len will contain the length of the actual TCP data. This is ++ calculated by subtracing the length of the TCP header (in ++ c) and the length of the IP header (20 bytes). */ ++ uip_len = uip_len - c - 20; ++ ++ /* First, check if the sequence number of the incoming packet is ++ what we're expecting next. If not, we send out an ACK with the ++ correct numbers in. */ ++ if(uip_len > 0 && ++ (BUF->seqno[0] != uip_connr->rcv_nxt[0] || ++ BUF->seqno[1] != uip_connr->rcv_nxt[1] || ++ BUF->seqno[2] != uip_connr->rcv_nxt[2] || ++ BUF->seqno[3] != uip_connr->rcv_nxt[3])) { ++ goto tcp_send_ack; ++ } ++ ++ /* Next, check if the incoming segment acknowledges any outstanding ++ data. If so, we update the sequence number, reset the length of ++ the outstanding data, calculate RTT estimations, and reset the ++ retransmission timer. */ ++ if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { ++ uip_add32(uip_connr->snd_nxt, uip_connr->len); ++ if(BUF->ackno[0] == uip_acc32[0] && ++ BUF->ackno[1] == uip_acc32[1] && ++ BUF->ackno[2] == uip_acc32[2] && ++ BUF->ackno[3] == uip_acc32[3]) { ++ /* Update sequence number. */ ++ uip_connr->snd_nxt[0] = uip_acc32[0]; ++ uip_connr->snd_nxt[1] = uip_acc32[1]; ++ uip_connr->snd_nxt[2] = uip_acc32[2]; ++ uip_connr->snd_nxt[3] = uip_acc32[3]; ++ ++ ++ /* Do RTT estimation, unless we have done retransmissions. */ ++ if(uip_connr->nrtx == 0) { ++ signed char m; ++ m = uip_connr->rto - uip_connr->timer; ++ /* This is taken directly from VJs original code in his paper */ ++ m = m - (uip_connr->sa >> 3); ++ uip_connr->sa += m; ++ if(m < 0) { ++ m = -m; ++ } ++ m = m - (uip_connr->sv >> 2); ++ uip_connr->sv += m; ++ uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; ++ ++ } ++ /* Set the acknowledged flag. */ ++ uip_flags = UIP_ACKDATA; ++ /* Reset the retransmission timer. */ ++ uip_connr->timer = uip_connr->rto; ++ } ++ ++ } ++ ++ /* Do different things depending on in what state the connection is. */ ++ switch(uip_connr->tcpstateflags & TS_MASK) { ++ /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not ++ implemented, since we force the application to close when the ++ peer sends a FIN (hence the application goes directly from ++ ESTABLISHED to LAST_ACK). */ ++ case SYN_RCVD: ++ /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and ++ we are waiting for an ACK that acknowledges the data we sent ++ out the last time. Therefore, we want to have the UIP_ACKDATA ++ flag set. If so, we enter the ESTABLISHED state. */ ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = ESTABLISHED; ++ uip_flags = UIP_CONNECTED; ++ uip_connr->len = 0; ++ if(uip_len > 0) { ++ uip_flags |= UIP_NEWDATA; ++ uip_add_rcv_nxt(uip_len); ++ } ++ uip_slen = 0; ++ UIP_APPCALL(); ++ goto appsend; ++ } ++ goto drop; ++#if UIP_ACTIVE_OPEN ++ case SYN_SENT: ++ /* In SYN_SENT, we wait for a SYNACK that is sent in response to ++ our SYN. The rcv_nxt is set to sequence number in the SYNACK ++ plus one, and we send an ACK. We move into the ESTABLISHED ++ state. */ ++ if((uip_flags & UIP_ACKDATA) && ++ BUF->flags == (TCP_SYN | TCP_ACK)) { ++ ++ /* Parse the TCP MSS option, if present. */ ++ if((BUF->tcpoffset & 0xf0) > 0x50) { ++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { ++ opt = uip_buf[40 + UIP_LLH_LEN + c]; ++ if(opt == 0x00) { ++ /* End of options. */ ++ break; ++ } else if(opt == 0x01) { ++ ++c; ++ /* NOP option. */ ++ } else if(opt == 0x02 && ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { ++ /* An MSS option with the right option length. */ ++ tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; ++ uip_connr->initialmss = ++ uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; ++ ++ /* And we are done processing options. */ ++ break; ++ } else { ++ /* All other options have a length field, so that we easily ++ can skip past them. */ ++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { ++ /* If the length field is zero, the options are malformed ++ and we don't process them further. */ ++ break; ++ } ++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; ++ } ++ } ++ } ++ uip_connr->tcpstateflags = ESTABLISHED; ++ uip_connr->rcv_nxt[0] = BUF->seqno[0]; ++ uip_connr->rcv_nxt[1] = BUF->seqno[1]; ++ uip_connr->rcv_nxt[2] = BUF->seqno[2]; ++ uip_connr->rcv_nxt[3] = BUF->seqno[3]; ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CONNECTED | UIP_NEWDATA; ++ uip_connr->len = 0; ++ uip_len = 0; ++ uip_slen = 0; ++ UIP_APPCALL(); ++ goto appsend; ++ } ++ goto reset; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ case ESTABLISHED: ++ /* In the ESTABLISHED state, we call upon the application to feed ++ data into the uip_buf. If the UIP_ACKDATA flag is set, the ++ application should put new data into the buffer, otherwise we are ++ retransmitting an old segment, and the application should put that ++ data into the buffer. ++ ++ If the incoming packet is a FIN, we should close the connection on ++ this side as well, and we send out a FIN and enter the LAST_ACK ++ state. We require that there is no outstanding data; otherwise the ++ sequence numbers will be screwed up. */ ++ ++ if(BUF->flags & TCP_FIN) { ++ if(uip_outstanding(uip_connr)) { ++ goto drop; ++ } ++ uip_add_rcv_nxt(1 + uip_len); ++ uip_flags = UIP_CLOSE; ++ if(uip_len > 0) { ++ uip_flags |= UIP_NEWDATA; ++ } ++ UIP_APPCALL(); ++ uip_connr->len = 1; ++ uip_connr->tcpstateflags = LAST_ACK; ++ uip_connr->nrtx = 0; ++ tcp_send_finack: ++ BUF->flags = TCP_FIN | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ /* Check the URG flag. If this is set, the segment carries urgent ++ data that we must pass to the application. */ ++ if(BUF->flags & TCP_URG) { ++#if UIP_URGDATA > 0 ++ uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ if(uip_urglen > uip_len) { ++ /* There is more urgent data in the next segment to come. */ ++ uip_urglen = uip_len; ++ } ++ uip_add_rcv_nxt(uip_urglen); ++ uip_len -= uip_urglen; ++ uip_urgdata = uip_appdata; ++ uip_appdata += uip_urglen; ++ } else { ++ uip_urglen = 0; ++#endif /* UIP_URGDATA > 0 */ ++ uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ } ++ ++ ++ /* If uip_len > 0 we have TCP data in the packet, and we flag this ++ by setting the UIP_NEWDATA flag and update the sequence number ++ we acknowledge. If the application has stopped the dataflow ++ using uip_stop(), we must not accept any data packets from the ++ remote host. */ ++ if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { ++ uip_flags |= UIP_NEWDATA; ++ uip_add_rcv_nxt(uip_len); ++ } ++ ++ /* Check if the available buffer space advertised by the other end ++ is smaller than the initial MSS for this connection. If so, we ++ set the current MSS to the window size to ensure that the ++ application does not send more data than the other end can ++ handle. ++ ++ If the remote host advertises a zero window, we set the MSS to ++ the initial MSS so that the application will send an entire MSS ++ of data. This data will not be acknowledged by the receiver, ++ and the application will retransmit it. This is called the ++ "persistent timer" and uses the retransmission mechanim. ++ */ ++ tmp16 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1]; ++ if(tmp16 > uip_connr->initialmss || ++ tmp16 == 0) { ++ tmp16 = uip_connr->initialmss; ++ } ++ uip_connr->mss = tmp16; ++ ++ /* If this packet constitutes an ACK for outstanding data (flagged ++ by the UIP_ACKDATA flag, we should call the application since it ++ might want to send more data. If the incoming packet had data ++ from the peer (as flagged by the UIP_NEWDATA flag), the ++ application must also be notified. ++ ++ When the application is called, the global variable uip_len ++ contains the length of the incoming data. The application can ++ access the incoming data through the global pointer ++ uip_appdata, which usually points 40 bytes into the uip_buf ++ array. ++ ++ If the application wishes to send any data, this data should be ++ put into the uip_appdata and the length of the data should be ++ put into uip_len. If the application don't have any data to ++ send, uip_len must be set to 0. */ ++ if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { ++ uip_slen = 0; ++ UIP_APPCALL(); ++ ++ appsend: ++ ++ if(uip_flags & UIP_ABORT) { ++ uip_slen = 0; ++ uip_connr->tcpstateflags = CLOSED; ++ BUF->flags = TCP_RST | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ if(uip_flags & UIP_CLOSE) { ++ uip_slen = 0; ++ uip_connr->len = 1; ++ uip_connr->tcpstateflags = FIN_WAIT_1; ++ uip_connr->nrtx = 0; ++ BUF->flags = TCP_FIN | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ /* If uip_slen > 0, the application has data to be sent. */ ++ if(uip_slen > 0) { ++ ++ /* If the connection has acknowledged data, the contents of ++ the ->len variable should be discarded. */ ++ if((uip_flags & UIP_ACKDATA) != 0) { ++ uip_connr->len = 0; ++ } ++ ++ /* If the ->len variable is non-zero the connection has ++ already data in transit and cannot send anymore right ++ now. */ ++ if(uip_connr->len == 0) { ++ ++ /* The application cannot send more than what is allowed by ++ the mss (the minumum of the MSS and the available ++ window). */ ++ if(uip_slen > uip_connr->mss) { ++ uip_slen = uip_connr->mss; ++ } ++ ++ /* Remember how much data we send out now so that we know ++ when everything has been acknowledged. */ ++ uip_connr->len = uip_slen; ++ } else { ++ ++ /* If the application already had unacknowledged data, we ++ make sure that the application does not send (i.e., ++ retransmit) out more than it previously sent out. */ ++ uip_slen = uip_connr->len; ++ } ++ } else { ++ uip_connr->len = 0; ++ } ++ uip_connr->nrtx = 0; ++ apprexmit: ++ uip_appdata = uip_sappdata; ++ ++ /* If the application has data to be sent, or if the incoming ++ packet had new data in it, we must send out a packet. */ ++ if(uip_slen > 0 && uip_connr->len > 0) { ++ /* Add the length of the IP and TCP headers. */ ++ uip_len = uip_connr->len + UIP_TCPIP_HLEN; ++ /* We always set the ACK flag in response packets. */ ++ BUF->flags = TCP_ACK | TCP_PSH; ++ /* Send the packet. */ ++ goto tcp_send_noopts; ++ } ++ /* If there is no data to send, just send out a pure ACK if ++ there is newdata. */ ++ if(uip_flags & UIP_NEWDATA) { ++ uip_len = UIP_TCPIP_HLEN; ++ BUF->flags = TCP_ACK; ++ goto tcp_send_noopts; ++ } ++ } ++ goto drop; ++ case LAST_ACK: ++ /* We can close this connection if the peer has acknowledged our ++ FIN. This is indicated by the UIP_ACKDATA flag. */ ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = CLOSED; ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ } ++ break; ++ ++ case FIN_WAIT_1: ++ /* The application has closed the connection, but the remote host ++ hasn't closed its end yet. Thus we do nothing but wait for a ++ FIN from the other side. */ ++ if(uip_len > 0) { ++ uip_add_rcv_nxt(uip_len); ++ } ++ if(BUF->flags & TCP_FIN) { ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ uip_connr->len = 0; ++ } else { ++ uip_connr->tcpstateflags = CLOSING; ++ } ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ goto tcp_send_ack; ++ } else if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = FIN_WAIT_2; ++ uip_connr->len = 0; ++ goto drop; ++ } ++ if(uip_len > 0) { ++ goto tcp_send_ack; ++ } ++ goto drop; ++ ++ case FIN_WAIT_2: ++ if(uip_len > 0) { ++ uip_add_rcv_nxt(uip_len); ++ } ++ if(BUF->flags & TCP_FIN) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ goto tcp_send_ack; ++ } ++ if(uip_len > 0) { ++ goto tcp_send_ack; ++ } ++ goto drop; ++ ++ case TIME_WAIT: ++ goto tcp_send_ack; ++ ++ case CLOSING: ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ } ++ } ++ goto drop; ++ ++ ++ /* We jump here when we are ready to send the packet, and just want ++ to set the appropriate TCP sequence numbers in the TCP header. */ ++ tcp_send_ack: ++ BUF->flags = TCP_ACK; ++ tcp_send_nodata: ++ uip_len = 40; ++ tcp_send_noopts: ++ BUF->tcpoffset = 5 << 4; ++ tcp_send: ++ /* We're done with the input processing. We are now ready to send a ++ reply. Our job is to fill in all the fields of the TCP and IP ++ headers before calculating the checksum and finally send the ++ packet. */ ++ BUF->ackno[0] = uip_connr->rcv_nxt[0]; ++ BUF->ackno[1] = uip_connr->rcv_nxt[1]; ++ BUF->ackno[2] = uip_connr->rcv_nxt[2]; ++ BUF->ackno[3] = uip_connr->rcv_nxt[3]; ++ ++ BUF->seqno[0] = uip_connr->snd_nxt[0]; ++ BUF->seqno[1] = uip_connr->snd_nxt[1]; ++ BUF->seqno[2] = uip_connr->snd_nxt[2]; ++ BUF->seqno[3] = uip_connr->snd_nxt[3]; ++ ++ BUF->proto = UIP_PROTO_TCP; ++ ++ BUF->srcport = uip_connr->lport; ++ BUF->destport = uip_connr->rport; ++ ++ BUF->srcipaddr[0] = uip_hostaddr[0]; ++ BUF->srcipaddr[1] = uip_hostaddr[1]; ++ BUF->destipaddr[0] = uip_connr->ripaddr[0]; ++ BUF->destipaddr[1] = uip_connr->ripaddr[1]; ++ ++ ++ if(uip_connr->tcpstateflags & UIP_STOPPED) { ++ /* If the connection has issued uip_stop(), we advertise a zero ++ window so that the remote host will stop sending data. */ ++ BUF->wnd[0] = BUF->wnd[1] = 0; ++ } else { ++ BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); ++ BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); ++ } ++ ++ tcp_send_noconn: ++ ++ BUF->len[0] = (uip_len >> 8); ++ BUF->len[1] = (uip_len & 0xff); ++ ++ /* Calculate TCP checksum. */ ++ BUF->tcpchksum = 0; ++ BUF->tcpchksum = ~(uip_tcpchksum()); ++ ++ //ip_send_nolen: ++ ++ BUF->vhl = 0x45; ++ BUF->tos = 0; ++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; ++ BUF->ttl = UIP_TTL; ++ ++ipid; ++ BUF->ipid[0] = ipid >> 8; ++ BUF->ipid[1] = ipid & 0xff; ++ ++ /* Calculate IP checksum. */ ++ BUF->ipchksum = 0; ++ BUF->ipchksum = ~(uip_ipchksum()); ++ ++ UIP_STAT(++uip_stat.tcp.sent); ++ send: ++ UIP_STAT(++uip_stat.ip.sent); ++ /* Return and let the caller do the actual transmission. */ ++ return; ++ drop: ++ uip_len = 0; ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/*unsigned short int ++htons(unsigned short int val) ++{ ++ return HTONS(val); ++}*/ ++/*-----------------------------------------------------------------------------------*/ ++/** @} */ +--- /dev/null ++++ b/net/uip-0.9/uip.h +@@ -0,0 +1,1066 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \file ++ * Header file for the uIP TCP/IP stack. ++ * \author Adam Dunkels ++ * ++ * The uIP TCP/IP stack header file contains definitions for a number ++ * of C macros that are used by uIP programs as well as internal uIP ++ * structures, TCP/IP header structures and function declarations. ++ * ++ */ ++ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_H__ ++#define __UIP_H__ ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include "uipopt.h" ++ ++/*-----------------------------------------------------------------------------------*/ ++/* First, the functions that should be called from the ++ * system. Initialization, the periodic timer and incoming packets are ++ * handled by the following three functions. ++ */ ++ ++/** ++ * \defgroup uipconffunc uIP configuration functions ++ * @{ ++ * ++ * The uIP configuration functions are used for setting run-time ++ * parameters in uIP such as IP addresses. ++ */ ++ ++/** ++ * Set the IP address of this host. ++ * ++ * The IP address is represented as a 4-byte array where the first ++ * octet of the IP address is put in the first member of the 4-byte ++ * array. ++ * ++ * \param addr A pointer to a 4-byte representation of the IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \ ++ uip_hostaddr[1] = addr[1]; } while(0) ++ ++/** ++ * Get the IP address of this host. ++ * ++ * The IP address is represented as a 4-byte array where the first ++ * octet of the IP address is put in the first member of the 4-byte ++ * array. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the currently configured IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \ ++ addr[1] = uip_hostaddr[1]; } while(0) ++ ++/** @} */ ++ ++/** ++ * \defgroup uipinit uIP initialization functions ++ * @{ ++ * ++ * The uIP initialization functions are used for booting uIP. ++ */ ++ ++/** ++ * uIP initialization function. ++ * ++ * This function should be called at boot up to initilize the uIP ++ * TCP/IP stack. ++ */ ++void uip_init(void); ++ ++/** @} */ ++ ++/** ++ * \defgroup uipdevfunc uIP device driver functions ++ * @{ ++ * ++ * These functions are used by a network device driver for interacting ++ * with uIP. ++ */ ++ ++/** ++ * Process an incoming packet. ++ * ++ * This function should be called when the device driver has received ++ * a packet from the network. The packet from the device driver must ++ * be present in the uip_buf buffer, and the length of the packet ++ * should be placed in the uip_len variable. ++ * ++ * When the function returns, there may be an outbound packet placed ++ * in the uip_buf packet buffer. If so, the uip_len variable is set to ++ * the length of the packet. If no packet is to be sent out, the ++ * uip_len variable is set to 0. ++ * ++ * The usual way of calling the function is presented by the source ++ * code below. ++ \code ++ uip_len = devicedriver_poll(); ++ if(uip_len > 0) { ++ uip_input(); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note If you are writing a uIP device driver that needs ARP ++ * (Address Resolution Protocol), e.g., when running uIP over ++ * Ethernet, you will need to call the uIP ARP code before calling ++ * this function: ++ \code ++ #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ uip_len = ethernet_devicedrver_poll(); ++ if(uip_len > 0) { ++ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); ++ if(uip_len > 0) { ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \hideinitializer ++ */ ++#define uip_input() uip_process(UIP_DATA) ++ ++/** ++ * Periodic processing for a connection identified by its number. ++ * ++ * This function does the necessary periodic processing (timers, ++ * polling) for a uIP TCP conneciton, and should be called when the ++ * periodic uIP timer goes off. It should be called for every ++ * connection, regardless of whether they are open of closed. ++ * ++ * When the function returns, it may have an outbound packet waiting ++ * for service in the uIP packet buffer, and if so the uip_len ++ * variable is set to a value larger than zero. The device driver ++ * should be called to send out the packet. ++ * ++ * The ususal way of calling the function is through a for() loop like ++ * this: ++ \code ++ for(i = 0; i < UIP_CONNS; ++i) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note If you are writing a uIP device driver that needs ARP ++ * (Address Resolution Protocol), e.g., when running uIP over ++ * Ethernet, you will need to call the uip_arp_out() function before ++ * calling the device driver: ++ \code ++ for(i = 0; i < UIP_CONNS; ++i) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \param conn The number of the connection which is to be periodically polled. ++ * ++ * \hideinitializer ++ */ ++#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ ++ uip_process(UIP_TIMER); } while (0) ++ ++/** ++ * Periodic processing for a connection identified by a pointer to its structure. ++ * ++ * Same as uip_periodic() but takes a pointer to the actual uip_conn ++ * struct instead of an integer as its argument. This function can be ++ * used to force periodic processing of a specific connection. ++ * ++ * \param conn A pointer to the uip_conn struct for the connection to ++ * be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_periodic_conn(conn) do { uip_conn = conn; \ ++ uip_process(UIP_TIMER); } while (0) ++ ++#if UIP_UDP ++/** ++ * Periodic processing for a UDP connection identified by its number. ++ * ++ * This function is essentially the same as uip_prerioic(), but for ++ * UDP connections. It is called in a similar fashion as the ++ * uip_periodic() function: ++ \code ++ for(i = 0; i < UIP_UDP_CONNS; i++) { ++ uip_udp_periodic(i); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note As for the uip_periodic() function, special care has to be ++ * taken when using uIP together with ARP and Ethernet: ++ \code ++ for(i = 0; i < UIP_UDP_CONNS; i++) { ++ uip_udp_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \param conn The number of the UDP connection to be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ ++ uip_process(UIP_UDP_TIMER); } while (0) ++ ++/** ++ * Periodic processing for a UDP connection identified by a pointer to ++ * its structure. ++ * ++ * Same as uip_udp_periodic() but takes a pointer to the actual ++ * uip_conn struct instead of an integer as its argument. This ++ * function can be used to force periodic processing of a specific ++ * connection. ++ * ++ * \param conn A pointer to the uip_udp_conn struct for the connection ++ * to be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ ++ uip_process(UIP_UDP_TIMER); } while (0) ++ ++ ++#endif /* UIP_UDP */ ++ ++/** ++ * The uIP packet buffer. ++ * ++ * The uip_buf array is used to hold incoming and outgoing ++ * packets. The device driver should place incoming data into this ++ * buffer. When sending data, the device driver should read the link ++ * level headers and the TCP/IP headers from this buffer. The size of ++ * the link level headers is configured by the UIP_LLH_LEN define. ++ * ++ * \note The application data need not be placed in this buffer, so ++ * the device driver must read it from the place pointed to by the ++ * uip_appdata pointer as illustrated by the following example: ++ \code ++ void ++ devicedriver_send(void) ++ { ++ hwsend(&uip_buf[0], UIP_LLH_LEN); ++ hwsend(&uip_buf[UIP_LLH_LEN], 40); ++ hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN); ++ } ++ \endcode ++ */ ++extern u8_t uip_buf[UIP_BUFSIZE+2]; ++ ++/** @} */ ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Functions that are used by the uIP application program. Opening and ++ * closing connections, sending and receiving data, etc. is all ++ * handled by the functions below. ++*/ ++/** ++ * \defgroup uipappfunc uIP application functions ++ * @{ ++ * ++ * Functions used by an application running of top of uIP. ++ */ ++ ++/** ++ * Start listening to the specified port. ++ * ++ * \note Since this function expects the port number in network byte ++ * order, a conversion using HTONS() or htons() is necessary. ++ * ++ \code ++ uip_listen(HTONS(80)); ++ \endcode ++ * ++ * \param port A 16-bit port number in network byte order. ++ */ ++void uip_listen(u16_t port); ++ ++/** ++ * Stop listening to the specified port. ++ * ++ * \note Since this function expects the port number in network byte ++ * order, a conversion using HTONS() or htons() is necessary. ++ * ++ \code ++ uip_unlisten(HTONS(80)); ++ \endcode ++ * ++ * \param port A 16-bit port number in network byte order. ++ */ ++void uip_unlisten(u16_t port); ++ ++/** ++ * Connect to a remote host using TCP. ++ * ++ * This function is used to start a new connection to the specified ++ * port on the specied host. It allocates a new connection identifier, ++ * sets the connection to the SYN_SENT state and sets the ++ * retransmission timer to 0. This will cause a TCP SYN segment to be ++ * sent out the next time this connection is periodically processed, ++ * which usually is done within 0.5 seconds after the call to ++ * uip_connect(). ++ * ++ * \note This function is avaliable only if support for active open ++ * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. ++ * ++ * \note Since this function requires the port number to be in network ++ * byte order, a convertion using HTONS() or htons() is necessary. ++ * ++ \code ++ u16_t ipaddr[2]; ++ ++ uip_ipaddr(ipaddr, 192,168,1,2); ++ uip_connect(ipaddr, HTONS(80)); ++ \endcode ++ * ++ * \param ripaddr A pointer to a 4-byte array representing the IP ++ * address of the remote hot. ++ * ++ * \param port A 16-bit port number in network byte order. ++ * ++ * \return A pointer to the uIP connection identifier for the new connection, ++ * or NULL if no connection could be allocated. ++ * ++ */ ++struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port); ++ ++ ++ ++/** ++ * \internal ++ * ++ * Check if a connection has outstanding (i.e., unacknowledged) data. ++ * ++ * \param conn A pointer to the uip_conn structure for the connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_outstanding(conn) ((conn)->len) ++ ++/** ++ * Send data on the current connection. ++ * ++ * This function is used to send out a single segment of TCP ++ * data. Only applications that have been invoked by uIP for event ++ * processing can send data. ++ * ++ * The amount of data that actually is sent out after a call to this ++ * funcion is determined by the maximum amount of data TCP allows. uIP ++ * will automatically crop the data so that only the appropriate ++ * amount of data is sent. The function uip_mss() can be used to query ++ * uIP for the amount of data that actually will be sent. ++ * ++ * \note This function does not guarantee that the sent data will ++ * arrive at the destination. If the data is lost in the network, the ++ * application will be invoked with the uip_rexmit() event being ++ * set. The application will then have to resend the data using this ++ * function. ++ * ++ * \param data A pointer to the data which is to be sent. ++ * ++ * \param len The maximum amount of data bytes to be sent. ++ * ++ * \hideinitializer ++ */ ++#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0) ++ ++/** ++ * The length of any incoming data that is currently avaliable (if avaliable) ++ * in the uip_appdata buffer. ++ * ++ * The test function uip_data() must first be used to check if there ++ * is any data available at all. ++ * ++ * \hideinitializer ++ */ ++#define uip_datalen() uip_len ++ ++/** ++ * The length of any out-of-band data (urgent data) that has arrived ++ * on the connection. ++ * ++ * \note The configuration parameter UIP_URGDATA must be set for this ++ * function to be enabled. ++ * ++ * \hideinitializer ++ */ ++#define uip_urgdatalen() uip_urglen ++ ++/** ++ * Close the current connection. ++ * ++ * This function will close the current connection in a nice way. ++ * ++ * \hideinitializer ++ */ ++#define uip_close() (uip_flags = UIP_CLOSE) ++ ++/** ++ * Abort the current connection. ++ * ++ * This function will abort (reset) the current connection, and is ++ * usually used when an error has occured that prevents using the ++ * uip_close() function. ++ * ++ * \hideinitializer ++ */ ++#define uip_abort() (uip_flags = UIP_ABORT) ++ ++/** ++ * Tell the sending host to stop sending data. ++ * ++ * This function will close our receiver's window so that we stop ++ * receiving data for the current connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) ++ ++/** ++ * Find out if the current connection has been previously stopped with ++ * uip_stop(). ++ * ++ * \hideinitializer ++ */ ++#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) ++ ++/** ++ * Restart the current connection, if is has previously been stopped ++ * with uip_stop(). ++ * ++ * This function will open the receiver's window again so that we ++ * start receiving data for the current connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ ++ uip_conn->tcpstateflags &= ~UIP_STOPPED; \ ++ } while(0) ++ ++ ++/* uIP tests that can be made to determine in what state the current ++ connection is, and what the application function should do. */ ++ ++/** ++ * Is new incoming data available? ++ * ++ * Will reduce to non-zero if there is new data for the application ++ * present at the uip_appdata pointer. The size of the data is ++ * avaliable through the uip_len variable. ++ * ++ * \hideinitializer ++ */ ++#define uip_newdata() (uip_flags & UIP_NEWDATA) ++ ++/** ++ * Has previously sent data been acknowledged? ++ * ++ * Will reduce to non-zero if the previously sent data has been ++ * acknowledged by the remote host. This means that the application ++ * can send new data. ++ * ++ * \hideinitializer ++ */ ++#define uip_acked() (uip_flags & UIP_ACKDATA) ++ ++/** ++ * Has the connection just been connected? ++ * ++ * Reduces to non-zero if the current connection has been connected to ++ * a remote host. This will happen both if the connection has been ++ * actively opened (with uip_connect()) or passively opened (with ++ * uip_listen()). ++ * ++ * \hideinitializer ++ */ ++#define uip_connected() (uip_flags & UIP_CONNECTED) ++ ++/** ++ * Has the connection been closed by the other end? ++ * ++ * Is non-zero if the connection has been closed by the remote ++ * host. The application may then do the necessary clean-ups. ++ * ++ * \hideinitializer ++ */ ++#define uip_closed() (uip_flags & UIP_CLOSE) ++ ++/** ++ * Has the connection been aborted by the other end? ++ * ++ * Non-zero if the current connection has been aborted (reset) by the ++ * remote host. ++ * ++ * \hideinitializer ++ */ ++#define uip_aborted() (uip_flags & UIP_ABORT) ++ ++/** ++ * Has the connection timed out? ++ * ++ * Non-zero if the current connection has been aborted due to too many ++ * retransmissions. ++ * ++ * \hideinitializer ++ */ ++#define uip_timedout() (uip_flags & UIP_TIMEDOUT) ++ ++/** ++ * Do we need to retransmit previously data? ++ * ++ * Reduces to non-zero if the previously sent data has been lost in ++ * the network, and the application should retransmit it. The ++ * application should send the exact same data as it did the last ++ * time, using the uip_send() function. ++ * ++ * \hideinitializer ++ */ ++#define uip_rexmit() (uip_flags & UIP_REXMIT) ++ ++/** ++ * Is the connection being polled by uIP? ++ * ++ * Is non-zero if the reason the application is invoked is that the ++ * current connection has been idle for a while and should be ++ * polled. ++ * ++ * The polling event can be used for sending data without having to ++ * wait for the remote host to send data. ++ * ++ * \hideinitializer ++ */ ++#define uip_poll() (uip_flags & UIP_POLL) ++ ++/** ++ * Get the initial maxium segment size (MSS) of the current ++ * connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_initialmss() (uip_conn->initialmss) ++ ++/** ++ * Get the current maxium segment size that can be sent on the current ++ * connection. ++ * ++ * The current maxiumum segment size that can be sent on the ++ * connection is computed from the receiver's window and the MSS of ++ * the connection (which also is available by calling ++ * uip_initialmss()). ++ * ++ * \hideinitializer ++ */ ++#define uip_mss() (uip_conn->mss) ++ ++/** ++ * Set up a new UDP connection. ++ * ++ * \param ripaddr A pointer to a 4-byte structure representing the IP ++ * address of the remote host. ++ * ++ * \param rport The remote port number in network byte order. ++ * ++ * \return The uip_udp_conn structure for the new connection or NULL ++ * if no connection could be allocated. ++ */ ++struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport); ++ ++/** ++ * Removed a UDP connection. ++ * ++ * \param conn A pointer to the uip_udp_conn structure for the connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_remove(conn) (conn)->lport = 0 ++ ++/** ++ * Send a UDP datagram of length len on the current connection. ++ * ++ * This function can only be called in response to a UDP event (poll ++ * or newdata). The data must be present in the uip_buf buffer, at the ++ * place pointed to by the uip_appdata pointer. ++ * ++ * \param len The length of the data in the uip_buf buffer. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_send(len) uip_slen = (len) ++ ++/** @} */ ++ ++/* uIP convenience and converting functions. */ ++ ++/** ++ * \defgroup uipconvfunc uIP conversion functions ++ * @{ ++ * ++ * These functions can be used for converting between different data ++ * formats used by uIP. ++ */ ++ ++/** ++ * Pack an IP address into a 4-byte array which is used by uIP to ++ * represent IP addresses. ++ * ++ * Example: ++ \code ++ u16_t ipaddr[2]; ++ ++ uip_ipaddr(&ipaddr, 192,168,1,2); ++ \endcode ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the IP addres. ++ * \param addr0 The first octet of the IP address. ++ * \param addr1 The second octet of the IP address. ++ * \param addr2 The third octet of the IP address. ++ * \param addr3 The forth octet of the IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ ++ (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \ ++ (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \ ++ } while(0) ++ ++/** ++ * Convert 16-bit quantity from host byte order to network byte order. ++ * ++ * This macro is primarily used for converting constants from host ++ * byte order to network byte order. For converting variables to ++ * network byte order, use the htons() function instead. ++ * ++ * \hideinitializer ++ */ ++#ifndef HTONS ++# if BYTE_ORDER == BIG_ENDIAN ++# define HTONS(n) (n) ++# else /* BYTE_ORDER == BIG_ENDIAN */ ++# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) ++# endif /* BYTE_ORDER == BIG_ENDIAN */ ++#endif /* HTONS */ ++ ++/** ++ * Convert 16-bit quantity from host byte order to network byte order. ++ * ++ * This function is primarily used for converting variables from host ++ * byte order to network byte order. For converting constants to ++ * network byte order, use the HTONS() macro instead. ++ */ ++#ifndef htons ++u16_t htons(u16_t val); ++#endif /* htons */ ++ ++/** @} */ ++ ++/** ++ * Pointer to the application data in the packet buffer. ++ * ++ * This pointer points to the application data when the application is ++ * called. If the application wishes to send data, the application may ++ * use this space to write the data into before calling uip_send(). ++ */ ++extern volatile u8_t *uip_appdata; ++extern volatile u8_t *uip_sappdata; ++ ++#if UIP_URGDATA > 0 ++/* u8_t *uip_urgdata: ++ * ++ * This pointer points to any urgent data that has been received. Only ++ * present if compiled with support for urgent data (UIP_URGDATA). ++ */ ++extern volatile u8_t *uip_urgdata; ++#endif /* UIP_URGDATA > 0 */ ++ ++ ++/* u[8|16]_t uip_len: ++ * ++ * When the application is called, uip_len contains the length of any ++ * new data that has been received from the remote host. The ++ * application should set this variable to the size of any data that ++ * the application wishes to send. When the network device driver ++ * output function is called, uip_len should contain the length of the ++ * outgoing packet. ++ */ ++extern volatile u16_t uip_len, uip_slen; ++ ++#if UIP_URGDATA > 0 ++extern volatile u8_t uip_urglen, uip_surglen; ++#endif /* UIP_URGDATA > 0 */ ++ ++ ++/** ++ * Representation of a uIP TCP connection. ++ * ++ * The uip_conn structure is used for identifying a connection. All ++ * but one field in the structure are to be considered read-only by an ++ * application. The only exception is the appstate field whos purpose ++ * is to let the application store application-specific state (e.g., ++ * file pointers) for the connection. The size of this field is ++ * configured in the "uipopt.h" header file. ++ */ ++struct uip_conn { ++ u16_t ripaddr[2]; /**< The IP address of the remote host. */ ++ ++ u16_t lport; /**< The local TCP port, in network byte order. */ ++ u16_t rport; /**< The local remote TCP port, in network byte ++ order. */ ++ ++ u8_t rcv_nxt[4]; /**< The sequence number that we expect to ++ receive next. */ ++ u8_t snd_nxt[4]; /**< The sequence number that was last sent by ++ us. */ ++ u16_t len; /**< Length of the data that was previously sent. */ ++ u16_t mss; /**< Current maximum segment size for the ++ connection. */ ++ u16_t initialmss; /**< Initial maximum segment size for the ++ connection. */ ++ u8_t sa; /**< Retransmission time-out calculation state ++ variable. */ ++ u8_t sv; /**< Retransmission time-out calculation state ++ variable. */ ++ u8_t rto; /**< Retransmission time-out. */ ++ u8_t tcpstateflags; /**< TCP state and flags. */ ++ u8_t timer; /**< The retransmission timer. */ ++ u8_t nrtx; /**< The number of retransmissions for the last ++ segment sent. */ ++ ++ /** The application state. */ ++ u8_t appstate[UIP_APPSTATE_SIZE]; ++}; ++ ++ ++/* Pointer to the current connection. */ ++extern struct uip_conn *uip_conn; ++/* The array containing all uIP connections. */ ++extern struct uip_conn uip_conns[UIP_CONNS]; ++/** ++ * \addtogroup uiparch ++ * @{ ++ */ ++ ++/** ++ * 4-byte array used for the 32-bit sequence number calculations. ++ */ ++extern volatile u8_t uip_acc32[4]; ++ ++/** @} */ ++ ++ ++#if UIP_UDP ++/** ++ * Representation of a uIP UDP connection. ++ */ ++struct uip_udp_conn { ++ u16_t ripaddr[2]; /**< The IP address of the remote peer. */ ++ u16_t lport; /**< The local port number in network byte order. */ ++ u16_t rport; /**< The remote port number in network byte order. */ ++}; ++ ++extern struct uip_udp_conn *uip_udp_conn; ++extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; ++#endif /* UIP_UDP */ ++ ++/** ++ * The structure holding the TCP/IP statistics that are gathered if ++ * UIP_STATISTICS is set to 1. ++ * ++ */ ++struct uip_stats { ++ struct { ++ uip_stats_t drop; /**< Number of dropped packets at the IP ++ layer. */ ++ uip_stats_t recv; /**< Number of received packets at the IP ++ layer. */ ++ uip_stats_t sent; /**< Number of sent packets at the IP ++ layer. */ ++ uip_stats_t vhlerr; /**< Number of packets dropped due to wrong ++ IP version or header length. */ ++ uip_stats_t hblenerr; /**< Number of packets dropped due to wrong ++ IP length, high byte. */ ++ uip_stats_t lblenerr; /**< Number of packets dropped due to wrong ++ IP length, low byte. */ ++ uip_stats_t fragerr; /**< Number of packets dropped since they ++ were IP fragments. */ ++ uip_stats_t chkerr; /**< Number of packets dropped due to IP ++ checksum errors. */ ++ uip_stats_t protoerr; /**< Number of packets dropped since they ++ were neither ICMP, UDP nor TCP. */ ++ } ip; /**< IP statistics. */ ++ struct { ++ uip_stats_t drop; /**< Number of dropped ICMP packets. */ ++ uip_stats_t recv; /**< Number of received ICMP packets. */ ++ uip_stats_t sent; /**< Number of sent ICMP packets. */ ++ uip_stats_t typeerr; /**< Number of ICMP packets with a wrong ++ type. */ ++ } icmp; /**< ICMP statistics. */ ++ struct { ++ uip_stats_t drop; /**< Number of dropped TCP segments. */ ++ uip_stats_t recv; /**< Number of recived TCP segments. */ ++ uip_stats_t sent; /**< Number of sent TCP segments. */ ++ uip_stats_t chkerr; /**< Number of TCP segments with a bad ++ checksum. */ ++ uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK ++ number. */ ++ uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ ++ uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ ++ uip_stats_t syndrop; /**< Number of dropped SYNs due to too few ++ connections was avaliable. */ ++ uip_stats_t synrst; /**< Number of SYNs for closed ports, ++ triggering a RST. */ ++ } tcp; /**< TCP statistics. */ ++}; ++ ++/** ++ * The uIP TCP/IP statistics. ++ * ++ * This is the variable in which the uIP TCP/IP statistics are gathered. ++ */ ++extern struct uip_stats uip_stat; ++ ++ ++/*-----------------------------------------------------------------------------------*/ ++/* All the stuff below this point is internal to uIP and should not be ++ * used directly by an application or by a device driver. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++/* u8_t uip_flags: ++ * ++ * When the application is called, uip_flags will contain the flags ++ * that are defined in this file. Please read below for more ++ * infomation. ++ */ ++extern volatile u8_t uip_flags; ++ ++/* The following flags may be set in the global variable uip_flags ++ before calling the application callback. The UIP_ACKDATA and ++ UIP_NEWDATA flags may both be set at the same time, whereas the ++ others are mutualy exclusive. Note that these flags should *NOT* be ++ accessed directly, but through the uIP functions/macros. */ ++ ++#define UIP_ACKDATA 1 /* Signifies that the outstanding data was ++ acked and the application should send ++ out new data instead of retransmitting ++ the last data. */ ++#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent ++ us new data. */ ++#define UIP_REXMIT 4 /* Tells the application to retransmit the ++ data that was last sent. */ ++#define UIP_POLL 8 /* Used for polling the application, to ++ check if the application has data that ++ it wants to send. */ ++#define UIP_CLOSE 16 /* The remote host has closed the ++ connection, thus the connection has ++ gone away. Or the application signals ++ that it wants to close the ++ connection. */ ++#define UIP_ABORT 32 /* The remote host has aborted the ++ connection, thus the connection has ++ gone away. Or the application signals ++ that it wants to abort the ++ connection. */ ++#define UIP_CONNECTED 64 /* We have got a connection from a remote ++ host and have set up a new connection ++ for it, or an active connection has ++ been successfully established. */ ++ ++#define UIP_TIMEDOUT 128 /* The connection has been aborted due to ++ too many retransmissions. */ ++ ++ ++/* uip_process(flag): ++ * ++ * The actual uIP function which does all the work. ++ */ ++void uip_process(u8_t flag); ++ ++/* The following flags are passed as an argument to the uip_process() ++ function. They are used to distinguish between the two cases where ++ uip_process() is called. It can be called either because we have ++ incoming data that should be processed, or because the periodic ++ timer has fired. */ ++ ++#define UIP_DATA 1 /* Tells uIP that there is incoming data in ++ the uip_buf buffer. The length of the ++ data is stored in the global variable ++ uip_len. */ ++#define UIP_TIMER 2 /* Tells uIP that the periodic timer has ++ fired. */ ++#if UIP_UDP ++#define UIP_UDP_TIMER 3 ++#endif /* UIP_UDP */ ++ ++/* The TCP states used in the uip_conn->tcpstateflags. */ ++#define CLOSED 0 ++#define SYN_RCVD 1 ++#define SYN_SENT 2 ++#define ESTABLISHED 3 ++#define FIN_WAIT_1 4 ++#define FIN_WAIT_2 5 ++#define CLOSING 6 ++#define TIME_WAIT 7 ++#define LAST_ACK 8 ++#define TS_MASK 15 ++ ++#define UIP_STOPPED 16 ++ ++#define UIP_TCPIP_HLEN 40 ++ ++/* The TCP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ ++ /* TCP header. */ ++ u16_t srcport, ++ destport; ++ u8_t seqno[4], ++ ackno[4], ++ tcpoffset, ++ flags, ++ wnd[2]; ++ u16_t tcpchksum; ++ u8_t urgp[2]; ++ u8_t optdata[4]; ++} uip_tcpip_hdr; ++ ++/* The ICMP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ /* ICMP (echo) header. */ ++ u8_t type, icode; ++ u16_t icmpchksum; ++ u16_t id, seqno; ++} uip_icmpip_hdr; ++ ++ ++/* The UDP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ ++ /* UDP header. */ ++ u16_t srcport, ++ destport; ++ u16_t udplen; ++ u16_t udpchksum; ++} uip_udpip_hdr; ++ ++#define UIP_PROTO_ICMP 1 ++#define UIP_PROTO_TCP 6 ++#define UIP_PROTO_UDP 17 ++ ++#if UIP_FIXEDADDR ++extern const u16_t uip_hostaddr[2]; ++#else /* UIP_FIXEDADDR */ ++extern u16_t uip_hostaddr[2]; ++#endif /* UIP_FIXEDADDR */ ++ ++#endif /* __UIP_H__ */ ++ ++ ++/** @} */ ++ +--- /dev/null ++++ b/net/uip-0.9/uipopt.h +@@ -0,0 +1,557 @@ ++/** ++ * \defgroup uipopt Configuration options for uIP ++ * @{ ++ * ++ * uIP is configured using the per-project configuration file ++ * "uipopt.h". This file contains all compile-time options for uIP and ++ * should be tweaked to match each specific project. The uIP ++ * distribution contains a documented example "uipopt.h" that can be ++ * copied and modified for each project. ++ */ ++ ++/** ++ * \file ++ * Configuration options for uIP. ++ * \author Adam Dunkels ++ * ++ * This file is used for tweaking various configuration options for ++ * uIP. You should make a copy of this file into one of your project's ++ * directories instead of editing this example "uipopt.h" file that ++ * comes with the uIP distribution. ++ */ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uipopt.h,v 1.16.2.5 2003/10/07 13:22:51 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIPOPT_H__ ++#define __UIPOPT_H__ ++ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipopttypedef uIP type definitions ++ * @{ ++ */ ++ ++/** ++ * The 8-bit unsigned data type. ++ * ++ * This may have to be tweaked for your particular compiler. "unsigned ++ * char" works for most compilers. ++ */ ++typedef unsigned char u8_t; ++ ++/** ++ * The 16-bit unsigned data type. ++ * ++ * This may have to be tweaked for your particular compiler. "unsigned ++ * short" works for most compilers. ++ */ ++typedef unsigned short u16_t; ++ ++/** ++ * The statistics data type. ++ * ++ * This datatype determines how high the statistics counters are able ++ * to count. ++ */ ++typedef unsigned short uip_stats_t; ++ ++/** @} */ ++ ++/*------------------------------------------------------------------------------*/ ++ ++/** ++ * \defgroup uipoptstaticconf Static configuration options ++ * @{ ++ * ++ * These configuration options can be used for setting the IP address ++ * settings statically, but only if UIP_FIXEDADDR is set to 1. The ++ * configuration options for a specific node includes IP address, ++ * netmask and default router as well as the Ethernet address. The ++ * netmask, default router and Ethernet address are appliciable only ++ * if uIP should be run over Ethernet. ++ * ++ * All of these should be changed to suit your project. ++*/ ++ ++/** ++ * Determines if uIP should use a fixed IP address or not. ++ * ++ * If uIP should use a fixed IP address, the settings are set in the ++ * uipopt.h file. If not, the macros uip_sethostaddr(), ++ * uip_setdraddr() and uip_setnetmask() should be used instead. ++ * ++ * \hideinitializer ++ */ ++#define UIP_FIXEDADDR 0 ++ ++/** ++ * Ping IP address asignment. ++ * ++ * uIP uses a "ping" packets for setting its own IP address if this ++ * option is set. If so, uIP will start with an empty IP address and ++ * the destination IP address of the first incoming "ping" (ICMP echo) ++ * packet will be used for setting the hosts IP address. ++ * ++ * \note This works only if UIP_FIXEDADDR is 0. ++ * ++ * \hideinitializer ++ */ ++#define UIP_PINGADDRCONF 0 ++ ++#define UIP_IPADDR0 192 /**< The first octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_IPADDR1 168 /**< The second octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_IPADDR2 0 /**< The third octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_IPADDR3 250 /**< The fourth octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++ ++#define UIP_NETMASK0 255 /**< The first octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_NETMASK1 255 /**< The second octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_NETMASK2 255 /**< The third octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_NETMASK3 0 /**< The fourth octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++ ++#define UIP_DRIPADDR0 192 /**< The first octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_DRIPADDR1 168 /**< The second octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_DRIPADDR2 0 /**< The third octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_DRIPADDR3 1 /**< The fourth octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++ ++/** ++ * Specifies if the uIP ARP module should be compiled with a fixed ++ * Ethernet MAC address or not. ++ * ++ * If this configuration option is 0, the macro uip_setethaddr() can ++ * be used to specify the Ethernet address at run-time. ++ * ++ * \hideinitializer ++ */ ++#define UIP_FIXEDETHADDR 0 ++ ++#define UIP_ETHADDR0 0x00 /**< The first octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR1 0xbd /**< The second octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR2 0x3b /**< The third octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR3 0x33 /**< The fourth octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR4 0x05 /**< The fifth octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR5 0x71 /**< The sixth octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptip IP configuration options ++ * @{ ++ * ++ */ ++/** ++ * The IP TTL (time to live) of IP packets sent by uIP. ++ * ++ * This should normally not be changed. ++ */ ++#define UIP_TTL 255 ++ ++/** ++ * Turn on support for IP packet reassembly. ++ * ++ * uIP supports reassembly of fragmented IP packets. This features ++ * requires an additonal amount of RAM to hold the reassembly buffer ++ * and the reassembly code size is approximately 700 bytes. The ++ * reassembly buffer is of the same size as the uip_buf buffer ++ * (configured by UIP_BUFSIZE). ++ * ++ * \note IP packet reassembly is not heavily tested. ++ * ++ * \hideinitializer ++ */ ++#define UIP_REASSEMBLY 0 ++ ++/** ++ * The maximum time an IP fragment should wait in the reassembly ++ * buffer before it is dropped. ++ * ++ */ ++#define UIP_REASS_MAXAGE 40 ++ ++/** @} */ ++ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptudp UDP configuration options ++ * @{ ++ * ++ * \note The UDP support in uIP is still not entirely complete; there ++ * is no support for sending or receiving broadcast or multicast ++ * packets, but it works well enough to support a number of vital ++ * applications such as DNS queries, though ++ */ ++ ++/** ++ * Toggles wether UDP support should be compiled in or not. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP 0 ++ ++/** ++ * Toggles if UDP checksums should be used or not. ++ * ++ * \note Support for UDP checksums is currently not included in uIP, ++ * so this option has no function. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP_CHECKSUMS 0 ++ ++/** ++ * The maximum amount of concurrent UDP connections. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP_CONNS 10 ++ ++/** ++ * The name of the function that should be called when UDP datagrams arrive. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP_APPCALL udp_appcall ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipopttcp TCP configuration options ++ * @{ ++ */ ++ ++/** ++ * Determines if support for opening connections from uIP should be ++ * compiled in. ++ * ++ * If the applications that are running on top of uIP for this project ++ * do not need to open outgoing TCP connections, this configration ++ * option can be turned off to reduce the code size of uIP. ++ * ++ * \hideinitializer ++ */ ++#define UIP_ACTIVE_OPEN 1 ++ ++/** ++ * The maximum number of simultaneously open TCP connections. ++ * ++ * Since the TCP connections are statically allocated, turning this ++ * configuration knob down results in less RAM used. Each TCP ++ * connection requires approximatly 30 bytes of memory. ++ * ++ * \hideinitializer ++ */ ++#define UIP_CONNS 10 ++ ++/** ++ * The maximum number of simultaneously listening TCP ports. ++ * ++ * Each listening TCP port requires 2 bytes of memory. ++ * ++ * \hideinitializer ++ */ ++#define UIP_LISTENPORTS 10 ++ ++/** ++ * The size of the advertised receiver's window. ++ * ++ * Should be set low (i.e., to the size of the uip_buf buffer) is the ++ * application is slow to process incoming data, or high (32768 bytes) ++ * if the application processes data quickly. ++ * ++ * \hideinitializer ++ */ ++#define UIP_RECEIVE_WINDOW 32768 ++ ++/** ++ * Determines if support for TCP urgent data notification should be ++ * compiled in. ++ * ++ * Urgent data (out-of-band data) is a rarely used TCP feature that ++ * very seldom would be required. ++ * ++ * \hideinitializer ++ */ ++#define UIP_URGDATA 1 ++ ++/** ++ * The initial retransmission timeout counted in timer pulses. ++ * ++ * This should not be changed. ++ */ ++#define UIP_RTO 3 ++ ++/** ++ * The maximum number of times a segment should be retransmitted ++ * before the connection should be aborted. ++ * ++ * This should not be changed. ++ */ ++#define UIP_MAXRTX 8 ++ ++/** ++ * The maximum number of times a SYN segment should be retransmitted ++ * before a connection request should be deemed to have been ++ * unsuccessful. ++ * ++ * This should not need to be changed. ++ */ ++#define UIP_MAXSYNRTX 3 ++ ++/** ++ * The TCP maximum segment size. ++ * ++ * This is should not be to set to more than UIP_BUFSIZE - UIP_LLH_LEN - 40. ++ */ ++#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - 40) ++ ++/** ++ * How long a connection should stay in the TIME_WAIT state. ++ * ++ * This configiration option has no real implication, and it should be ++ * left untouched. ++ */ ++#define UIP_TIME_WAIT_TIMEOUT 120 ++ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptarp ARP configuration options ++ * @{ ++ */ ++ ++/** ++ * The size of the ARP table. ++ * ++ * This option should be set to a larger value if this uIP node will ++ * have many connections from the local network. ++ * ++ * \hideinitializer ++ */ ++#define UIP_ARPTAB_SIZE 8 ++ ++/** ++ * The maxium age of ARP table entries measured in 10ths of seconds. ++ * ++ * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD ++ * default). ++ */ ++#define UIP_ARP_MAXAGE 120 ++ ++/** @} */ ++ ++/*------------------------------------------------------------------------------*/ ++ ++/** ++ * \defgroup uipoptgeneral General configuration options ++ * @{ ++ */ ++ ++/** ++ * The size of the uIP packet buffer. ++ * ++ * The uIP packet buffer should not be smaller than 60 bytes, and does ++ * not need to be larger than 1500 bytes. Lower size results in lower ++ * TCP throughput, larger size results in higher TCP throughput. ++ * ++ * \hideinitializer ++ */ ++#define UIP_BUFSIZE 1500 ++ ++ ++/** ++ * Determines if statistics support should be compiled in. ++ * ++ * The statistics is useful for debugging and to show the user. ++ * ++ * \hideinitializer ++ */ ++#define UIP_STATISTICS 1 ++ ++/** ++ * Determines if logging of certain events should be compiled in. ++ * ++ * This is useful mostly for debugging. The function uip_log() ++ * must be implemented to suit the architecture of the project, if ++ * logging is turned on. ++ * ++ * \hideinitializer ++ */ ++#define UIP_LOGGING 0 ++ ++/** ++ * Print out a uIP log message. ++ * ++ * This function must be implemented by the module that uses uIP, and ++ * is called by uIP whenever a log message is generated. ++ */ ++void uip_log(char *msg); ++ ++/** ++ * The link level header length. ++ * ++ * This is the offset into the uip_buf where the IP header can be ++ * found. For Ethernet, this should be set to 14. For SLIP, this ++ * should be set to 0. ++ * ++ * \hideinitializer ++ */ ++#define UIP_LLH_LEN 14 ++ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptcpu CPU architecture configuration ++ * @{ ++ * ++ * The CPU architecture configuration is where the endianess of the ++ * CPU on which uIP is to be run is specified. Most CPUs today are ++ * little endian, and the most notable exception are the Motorolas ++ * which are big endian. The BYTE_ORDER macro should be changed to ++ * reflect the CPU architecture on which uIP is to be run. ++ */ ++#ifndef LITTLE_ENDIAN ++#define LITTLE_ENDIAN 3412 ++#endif /* LITTLE_ENDIAN */ ++#ifndef BIG_ENDIAN ++#define BIG_ENDIAN 1234 ++#endif /* BIGE_ENDIAN */ ++ ++/** ++ * The byte order of the CPU architecture on which uIP is to be run. ++ * ++ * This option can be either BIG_ENDIAN (Motorola byte order) or ++ * LITTLE_ENDIAN (Intel byte order). ++ * ++ * \hideinitializer ++ */ ++/*#ifndef BYTE_ORDER*/ ++#define BYTE_ORDER BIG_ENDIAN ++/*#endif*/ /* BYTE_ORDER */ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++ ++/** ++ * \defgroup uipoptapp Appication specific configurations ++ * @{ ++ * ++ * An uIP application is implemented using a single application ++ * function that is called by uIP whenever a TCP/IP event occurs. The ++ * name of this function must be registered with uIP at compile time ++ * using the UIP_APPCALL definition. ++ * ++ * uIP applications can store the application state within the ++ * uip_conn structure by specifying the size of the application ++ * structure with the UIP_APPSTATE_SIZE macro. ++ * ++ * The file containing the definitions must be included in the ++ * uipopt.h file. ++ * ++ * The following example illustrates how this can look. ++ \code ++ ++void httpd_appcall(void); ++#define UIP_APPCALL httpd_appcall ++ ++struct httpd_state { ++ u8_t state; ++ u16_t count; ++ char *dataptr; ++ char *script; ++}; ++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) ++ \endcode ++ */ ++ ++/** ++ * \var #define UIP_APPCALL ++ * ++ * The name of the application function that uIP should call in ++ * response to TCP/IP events. ++ * ++ */ ++ ++/** ++ * \var #define UIP_APPSTATE_SIZE ++ * ++ * The size of the application state that is to be stored in the ++ * uip_conn structure. ++ */ ++/** @} */ ++ ++/* Include the header file for the application program that should be ++ used. If you don't use the example web server, you should change ++ this. */ ++#include "httpd.h" ++ ++ ++#endif /* __UIPOPT_H__ */ From 05c930e80a27d5caac4ab057a906a075f59635ea Mon Sep 17 00:00:00 2001 From: ralph Date: Tue, 30 Mar 2010 13:56:30 +0000 Subject: [PATCH 15/45] [uboot-lantiq] add preliminary AR9 support attention: if caches enabled the network is broken attention: the network of the flash image doesn't work because of enabled caches git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20606 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/uboot-lantiq/easy50812.conf | 55 ++ .../files/board/infineon/easy50812/Makefile | 47 ++ .../files/board/infineon/easy50812/ar9.c | 666 ++++++++++++++++++ .../infineon/easy50812/ar9_ddr111_settings.h | 51 ++ .../infineon/easy50812/ar9_ddr166_settings.h | 51 ++ .../infineon/easy50812/ar9_ddr196_settings.h | 51 ++ .../infineon/easy50812/ar9_ddr221_settings.h | 51 ++ .../infineon/easy50812/ar9_ddr250_settings.h | 51 ++ .../files/board/infineon/easy50812/config.mk | 60 ++ .../board/infineon/easy50812/lowlevel_init.S | 543 ++++++++++++++ .../board/infineon/easy50812/pmuenable.S | 48 ++ .../files/board/infineon/easy50812/u-boot.lds | 70 ++ .../uboot-lantiq/files/cpu/mips/ar9/Makefile | 46 ++ .../uboot-lantiq/files/cpu/mips/ar9/clock.c | 67 ++ .../files/cpu/mips/ar9/ifx_cache.S | 60 ++ .../uboot-lantiq/files/drivers/net/ifx_etop.c | 29 +- .../uboot-lantiq/files/include/asm-mips/ar9.h | 424 +++++++++++ .../files/include/configs/easy50812.h | 104 +++ .../patches/100-ifx_targets.patch | 26 +- 19 files changed, 2496 insertions(+), 4 deletions(-) create mode 100644 package/uboot-lantiq/easy50812.conf create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/Makefile create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/ar9.c create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/config.mk create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S create mode 100644 package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds create mode 100644 package/uboot-lantiq/files/cpu/mips/ar9/Makefile create mode 100644 package/uboot-lantiq/files/cpu/mips/ar9/clock.c create mode 100644 package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S create mode 100644 package/uboot-lantiq/files/include/asm-mips/ar9.h create mode 100644 package/uboot-lantiq/files/include/configs/easy50812.h diff --git a/package/uboot-lantiq/easy50812.conf b/package/uboot-lantiq/easy50812.conf new file mode 100644 index 000000000..d28198c2f --- /dev/null +++ b/package/uboot-lantiq/easy50812.conf @@ -0,0 +1,55 @@ +0xbf800060 0x0000000f +0xbf800010 0x00000000 +0xbf800020 0x00000000 +0xbf800200 0x00000002 +0xbf800210 0x00000000 +0xbf801000 0x00001b1b +0xbf801010 0x00000000 +0xbf801020 0x00000000 +0xbf801030 0x00000000 +0xbf801040 0x00000000 +0xbf801050 0x00000200 +0xbf801060 0x00000306 +0xbf801070 0x00000303 +0xbf801080 0x00000102 +0xbf801090 0x0000070a +0xbf8010a0 0x00000203 +0xbf8010b0 0x00000c02 +0xbf8010c0 0x000001c8 +0xbf8010d0 0x00000001 +0xbf8010e0 0x00000000 +0xbf8010f0 0x00000139 +0xbf801100 0x00002200 +0xbf801110 0x0000000d +0xbf801120 0x00000301 +0xbf801130 0x00000200 +0xbf801140 0x00000a04 +0xbf801150 0x00001800 +0xbf801160 0x00001818 +0xbf801170 0x00000000 +0xbf801180 0x00000059 +0xbf801190 0x00000000 +0xbf8011a0 0x00000000 +0xbf8011b0 0x00000000 +0xbf8011c0 0x00000514 +0xbf8011d0 0x00002d93 +0xbf8011e0 0x00008235 +0xbf8011f0 0x00000000 +0xbf801200 0x00000000 +0xbf801210 0x00000000 +0xbf801220 0x00000000 +0xbf801230 0x00000000 +0xbf801240 0x00000000 +0xbf801250 0x00000000 +0xbf801260 0x00000000 +0xbf801270 0x00000000 +0xbf801280 0x00000000 +0xbf801290 0x00000000 +0xbf8012a0 0x00000000 +0xbf8012b0 0x00000000 +0xbf8012c0 0x00000000 +0xbf8012d0 0x00000600 +0xbf8012e0 0x00000000 +0xbf800060 0x0000000d +0xbf801030 0x00000100 + diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/Makefile b/package/uboot-lantiq/files/board/infineon/easy50812/Makefile new file mode 100644 index 000000000..44d8ea344 --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +#COBJS := $(BOARD).o +COBJS-y += ar9.o + +SOBJS = lowlevel_init.o pmuenable.o + +SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c b/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c new file mode 100644 index 000000000..dd6be9bdf --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c @@ -0,0 +1,666 @@ +/* +* (C) Copyright 2003 +* Wolfgang Denk, DENX Software Engineering, wd@denx.de. +* +* (C) Copyright 2010 +* Thomas Langer, Ralph Hempel +* +* See file CREDITS for list of people who contributed to this +* project. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, +* MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_CMD_HTTPD) +#include +#endif + +extern ulong ifx_get_ddr_hz(void); +extern ulong ifx_get_cpuclk(void); + +/* definitions for external PHYs / Switches */ +/* Split values into phy address and register address */ +#define PHYADDR(_reg) ((_reg >> 5) & 0xff), (_reg & 0x1f) + +/* IDs and registers of known external switches */ +#define ID_SAMURAI_0 0x1020 +#define ID_SAMURAI_1 0x0007 +#define SAMURAI_ID_REG0 0xA0 +#define SAMURAI_ID_REG1 0xA1 +#define ID_TANTOS 0x2599 + +#define RGMII_MODE 0 +#define MII_MODE 1 +#define REV_MII_MODE 2 +#define RED_MII_MODE_IC 3 /*Input clock */ +#define RGMII_MODE_100MB 4 +#define TURBO_REV_MII_MODE 6 /*Turbo Rev Mii mode */ +#define RED_MII_MODE_OC 7 /*Output clock */ +#define RGMII_MODE_10MB 8 + +#define mdelay(n) udelay((n)*1000) + +static void ar9_sw_chip_init(u8 port, u8 mode); +static void ar9_enable_sw_port(u8 port, u8 state); +static void ar9_configure_sw_port(u8 port, u8 mode); +static u16 ar9_smi_reg_read(u16 reg); +static u16 ar9_smi_reg_write(u16 reg, u16 data); +static char * const name = "lq_cpe_eth"; +static int external_switch_init(void); + +void _machine_restart(void) +{ + *AR9_RCU_RST_REQ |= AR9_RST_ALL; +} + +#ifdef CONFIG_SYS_RAMBOOT +phys_size_t initdram(int board_type) +{ + return get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MAX_RAM); +} +#elif defined(CONFIG_USE_DDR_RAM) +phys_size_t initdram(int board_type) +{ + return (CONFIG_SYS_MAX_RAM); +} +#else + +static ulong max_sdram_size(void) /* per Chip Select */ +{ + /* The only supported SDRAM data width is 16bit. + */ +#define CFG_DW 4 + + /* The only supported number of SDRAM banks is 4. + */ +#define CFG_NB 4 + + ulong cfgpb0 = *AR9_SDRAM_MC_CFGPB0; + int cols = cfgpb0 & 0xF; + int rows = (cfgpb0 & 0xF0) >> 4; + ulong size = (1 << (rows + cols)) * CFG_DW * CFG_NB; + + return size; +} + +/* +* Check memory range for valid RAM. A simple memory test determines +* the actually available RAM size between addresses `base' and +* `base + maxsize'. +*/ + +static long int dram_size(long int *base, long int maxsize) +{ + volatile long int *addr; + ulong cnt, val; + ulong save[32]; /* to make test non-destructive */ + unsigned char i = 0; + + for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) { + addr = base + cnt; /* pointer arith! */ + + save[i++] = *addr; + *addr = ~cnt; + } + + /* write 0 to base address */ + addr = base; + save[i] = *addr; + *addr = 0; + + /* check at base address */ + if ((val = *addr) != 0) { + *addr = save[i]; + return (0); + } + + for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + val = *addr; + *addr = save[--i]; + + if (val != (~cnt)) { + return (cnt * sizeof (long)); + } + } + return (maxsize); +} + +phys_size_t initdram(int board_type) +{ + int rows, cols, best_val = *AR9_SDRAM_MC_CFGPB0; + ulong size, max_size = 0; + ulong our_address; + + /* load t9 into our_address */ + asm volatile ("move %0, $25" : "=r" (our_address) :); + + /* Can't probe for RAM size unless we are running from Flash. + * find out whether running from DRAM or Flash. + */ + if (CPHYSADDR(our_address) < CPHYSADDR(PHYS_FLASH_1)) + { + return max_sdram_size(); + } + + for (cols = 0x8; cols <= 0xC; cols++) + { + for (rows = 0xB; rows <= 0xD; rows++) + { + *AR9_SDRAM_MC_CFGPB0 = (0x14 << 8) | + (rows << 4) | cols; + size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, + max_sdram_size()); + + if (size > max_size) + { + best_val = *AR9_SDRAM_MC_CFGPB0; + max_size = size; + } + } + } + + *AR9_SDRAM_MC_CFGPB0 = best_val; + return max_size; +} +#endif + +int checkboard (void) +{ + unsigned long chipid = *AR9_MPS_CHIPID; + int part_num; + + puts ("Board: "); + + part_num = AR9_MPS_CHIPID_PARTNUM_GET(chipid); + switch (part_num) + { + case 0x16C: + puts("ARX188 "); + break; + case 0x16D: + puts("ARX168 "); + break; + case 0x16F: + puts("ARX182 "); + break; + case 0x170: + puts("GRX188 "); + break; + case 0x171: + puts("GRX168 "); + break; + default: + printf ("unknown, chip part number 0x%03X ", part_num); + break; + } + printf ("V1.%ld, ", AR9_MPS_CHIPID_VERSION_GET(chipid)); + + printf("DDR Speed %ld MHz, ", ifx_get_ddr_hz()/1000000); + printf("CPU Speed %ld MHz\n", ifx_get_cpuclk()/1000000); + + return 0; +} + +#ifdef CONFIG_SKIP_LOWLEVEL_INIT +int board_early_init_f(void) +{ +#ifdef CONFIG_EBU_ADDSEL0 + (*AR9_EBU_ADDSEL0) = CONFIG_EBU_ADDSEL0; +#endif +#ifdef CONFIG_EBU_ADDSEL1 + (*AR9_EBU_ADDSEL1) = CONFIG_EBU_ADDSEL1; +#endif +#ifdef CONFIG_EBU_ADDSEL2 + (*AR9_EBU_ADDSEL2) = CONFIG_EBU_ADDSEL2; +#endif +#ifdef CONFIG_EBU_ADDSEL3 + (*AR9_EBU_ADDSEL3) = CONFIG_EBU_ADDSEL3; +#endif +#ifdef CONFIG_EBU_BUSCON0 + (*AR9_EBU_BUSCON0) = CONFIG_EBU_BUSCON0; +#endif +#ifdef CONFIG_EBU_BUSCON1 + (*AR9_EBU_BUSCON1) = CONFIG_EBU_BUSCON1; +#endif +#ifdef CONFIG_EBU_BUSCON2 + (*AR9_EBU_BUSCON2) = CONFIG_EBU_BUSCON2; +#endif +#ifdef CONFIG_EBU_BUSCON3 + (*AR9_EBU_BUSCON3) = CONFIG_EBU_BUSCON3; +#endif + + return 0; +} +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +int board_eth_init(bd_t *bis) +{ +#if defined(CONFIG_IFX_ETOP) + + *AR9_PMU_PWDCR &= 0xFFFFEFDF; + *AR9_PMU_PWDCR &= ~AR9_PMU_DMA; /* enable DMA from PMU */ + + if (lq_eth_initialize(bis) < 0) + return -1; + + *AR9_RCU_RST_REQ |= 1; + udelay(200000); + *AR9_RCU_RST_REQ &= (unsigned long)~1; + udelay(1000); + +#ifdef CONFIG_EXTRA_SWITCH + if (external_switch_init()<0) + return -1; +#endif /* CONFIG_EXTRA_SWITCH */ +#endif /* CONFIG_IFX_ETOP */ + + return 0; +} + +static void ar9_configure_sw_port(u8 port, u8 mode) +{ + if(port) + { + if (mode == 1) //MII mode + { + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0xf000); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0xf000); + *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR & ~(0xf000)) | 0x2000; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0x2000; + } + else if(mode == 2 || mode == 6) //Rev Mii mode + { + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0xf000); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0xf000); + *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR | (0xf000)) & ~0x2000; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0xd000; + } + } + else //Port 0 + { + if (mode == 1) //MII mode + { + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0x0303); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0x0303); + *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR & ~(0x0303)) | 0x0100; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0x0100; + } + else if(mode ==2 || mode ==6) //Rev Mii mode + { + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0x0303); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0x0303); + *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR | (0x0303)) & ~0x0100; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0x0203; + } + } +} + +/* +Call this function to place either MAC port 0 or 1 into working mode. +Parameters: +port - select ports 0 or 1. +state of interface : state +0: RGMII +1: MII +2: Rev MII +3: Reduce MII (input clock) +4: RGMII 100mb +5: Reserve +6: Turbo Rev MII +7: Reduce MII (output clock) +*/ +void ar9_enable_sw_port(u8 port, u8 state) +{ + REG32(AR9_SW_GCTL0) |= 0x80000000; + if (port == 0) + { + REG32(AR9_SW_RGMII_CTL) &= 0xffcffc0e ; + //#if AR9_REFBOARD_TANTOS + REG32(0xbf20302c) &= 0xffff81ff; + REG32(0xbf20302c) |= 4<<9 ; + //#endif + REG32(AR9_SW_RGMII_CTL) |= ((u32)(state &0x3))<<8; + if((state &0x3) == 0) + { + REG32(AR9_SW_RGMII_CTL) &= 0xfffffff3; + if(state == 4) + REG32(AR9_SW_RGMII_CTL) |= 0x4; + else + REG32(AR9_SW_RGMII_CTL) |= 0x8; + } + if(state == 6) + REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<20)); + if(state == 7) + REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<21)); + } +// *AR9_PPE32_ETOP_CFG = *AR9_PPE32_ETOP_CFG & 0xfffffffe; + else + { + REG32(AR9_SW_RGMII_CTL) &= 0xff303fff ; + REG32(AR9_SW_RGMII_CTL) |= ((u32)(state &0x3))<<18; + if((state &0x3) == 0) + { + REG32(AR9_SW_RGMII_CTL) &= 0xffffcfff; + if(state == 4) + REG32(AR9_SW_RGMII_CTL) |= 0x1000; + else + REG32(AR9_SW_RGMII_CTL) |= 0x2000; + } + if(state == 6) + REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<22)); + if(state == 7) + REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<23)); + } +} + +void pci_reset(void) +{ + int i,j; +#define AR9_V1_PCI_RST_FIX 1 +#if AR9_V1_PCI_RST_FIX // 5th June 2008 Add GPIO19 to control EJTAG_TRST + *AR9_GPIO_P1_ALTSEL0 = *AR9_GPIO_P1_ALTSEL0 & ~0x8; + *AR9_GPIO_P1_ALTSEL1 = *AR9_GPIO_P1_ALTSEL1 & ~0x8; + *AR9_GPIO_P1_DIR = *AR9_GPIO_P1_DIR | 0x8; + *AR9_GPIO_P1_OD = *AR9_GPIO_P1_OD | 0x8; + *AR9_GPIO_P1_OUT = *AR9_GPIO_P1_OUT | 0x8; + *AR9_GPIO_P0_ALTSEL0 = *AR9_GPIO_P0_ALTSEL0 & ~0x4000; + *AR9_GPIO_P0_ALTSEL1 = *AR9_GPIO_P0_ALTSEL1 & ~0x4000; + *AR9_GPIO_P0_DIR = *AR9_GPIO_P0_DIR | 0x4000; + *AR9_GPIO_P0_OD = *AR9_GPIO_P0_OD | 0x4000; + for(j=0;j<5;j++) { + *AR9_GPIO_P0_OUT = *AR9_GPIO_P0_OUT & ~0x4000; + for(i=0;i<0x10000;i++); + *AR9_GPIO_P0_OUT = *AR9_GPIO_P0_OUT | 0x4000; + for(i=0;i<0x10000;i++); + } + *AR9_GPIO_P0_DIR = *AR9_GPIO_P0_DIR & ~0x4000; + *AR9_GPIO_P1_DIR = *AR9_GPIO_P1_DIR & ~0x8; +#endif +} + +static u16 ar9_smi_reg_read(u16 reg) +{ + int i; + while(REG32(AR9_SW_MDIO_CTL) & 0x8000); + REG32(AR9_SW_MDIO_CTL) = 0x8000| 0x2<<10 | ((u32) (reg&0x3ff)) ; /*0x10=MDIO_OP_READ*/ + for(i=0;i<0x3fff;i++); + udelay(50); + while(REG32(AR9_SW_MDIO_CTL) & 0x8000); + return((u16) (REG32(AR9_SW_MDIO_DATA))); +} + +static u16 ar9_smi_reg_write(u16 reg, u16 data) +{ + int i; + while(REG32(AR9_SW_MDIO_CTL) & 0x8000); + REG32(AR9_SW_MDIO_CTL) = 0x8000| (((u32) data)<<16) | 0x01<<10 | ((u32) (reg&0x3ff)) ; /*0x01=MDIO_OP_WRITE*/ + for(i=0;i<0x3fff;i++); + udelay(50); + return 0; +} + +static void ar9_sw_chip_init(u8 port, u8 mode) +{ + int i; + u16 chipid; + + debug("\nsearching for switches ... "); + + asm("sync"); + pci_reset(); + + /* 25mhz clock out */ + *AR9_CGU_IFCCR &= ~(3<<10); + *AR9_GPIO_P0_ALTSEL0 = *AR9_GPIO_P0_ALTSEL0 | (1<<3); + *AR9_GPIO_P0_ALTSEL1 = *AR9_GPIO_P0_ALTSEL1 & ~(1<<3); + *AR9_GPIO_P0_DIR = *AR9_GPIO_P0_DIR | (1<<3); + *AR9_GPIO_P0_OD = *AR9_GPIO_P0_OD | (1<<3); + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 & ~(1<<0); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(1<<0); + *AR9_GPIO_P2_DIR = *AR9_GPIO_P2_DIR | (1<<0); + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | (1<<0); + + *AR9_PMU_PWDCR = (*AR9_PMU_PWDCR & 0xFFFBDFDF) ; + *AR9_PMU_PWDCR = (*AR9_PMU_PWDCR & ~(AR9_PMU_DMA | AR9_PMU_SWITCH)); + *AR9_PMU_PWDCR = (*AR9_PMU_PWDCR | AR9_PMU_USB0 | AR9_PMU_USB0_P); + + *AR9_GPIO_P2_OUT &= ~(1<<0); + asm("sync"); + + ar9_configure_sw_port(port, mode); + ar9_enable_sw_port(port, mode); + REG32(AR9_SW_P0_CTL) |= 0x400000; /* disable mdio polling for tantos */ + asm("sync"); + + /*GPIO 55(P3.7) used as output, set high*/ + *AR9_GPIO_P3_OD |=(1<<7); + *AR9_GPIO_P3_DIR |= (1<<7); + *AR9_GPIO_P3_ALTSEL0 &=~(1<<7); + *AR9_GPIO_P3_ALTSEL1 &=~(1<<7); + asm("sync"); + udelay(10); + + *AR9_GPIO_P3_OUT &= ~(1<<7); + for(i=0;i<1000;i++) + udelay(110); + *AR9_GPIO_P3_OUT |=(1<<7); + udelay(100); + + if(port==0) + REG32(AR9_SW_P0_CTL) |= 0x40001; + else + REG32(AR9_SW_P1_CTL) |= 0x40001; + + REG32(AR9_SW_P2_CTL) |= 0x40001; + REG32(AR9_SW_PMAC_HD_CTL) |= 0x40000; /* enable CRC */ + + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0xc00); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0xc00); + *AR9_GPIO_P2_DIR = *AR9_GPIO_P2_DIR | 0xc00; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0xc00; + + asm("sync"); + chipid = (unsigned short)(ar9_smi_reg_read(0x101)); + printf("\nswitch chip id=%08x\n",chipid); + if (chipid != ID_TANTOS) { + debug("whatever detected\n"); + ar9_smi_reg_write(0x1,0x840f); + ar9_smi_reg_write(0x3,0x840f); + ar9_smi_reg_write(0x5,0x840f); + ar9_smi_reg_write(0x7,0x840f); + ar9_smi_reg_write(0x8,0x840f); + ar9_smi_reg_write(0x12,0x3602); +#ifdef CLK_OUT2_25MHZ + ar9_smi_reg_write(0x33,0x4000); +#endif + } else { // Tantos switch ship + debug("Tantos switch detected\n"); + ar9_smi_reg_write(0xa1,0x0004); /*port 5 force link up*/ + ar9_smi_reg_write(0xc1,0x0004); /*port 6 force link up*/ + ar9_smi_reg_write(0xf5,0x0BBB); /*port 4 duplex mode, flow control enable,1000Mbit/s*/ + /*port 5 duplex mode, flow control enable, 1000Mbit/s*/ + /*port 6 duplex mode, flow control enable, 1000Mbit/s*/ + } + asm("sync"); + + /*reset GPHY*/ + mdelay(200); + *AR9_RCU_RST_REQ |= (AR9_RCU_RST_REQ_DMA | AR9_RCU_RST_REQ_PPE) ; + udelay(50); + *AR9_GPIO_P2_OUT |= (1<<0); +} + +static void ar9_dma_init(void) +{ + /* select port */ + *AR9_DMA_PS = 0; + + /* + TXWGT 14:12 rw Port Weight for Transmit Direction (the default value “001”) + + TXENDI 11:10 rw Endianness for Transmit Direction + Determine a byte swap between memory interface (left hand side) and + peripheral interface (right hand side). + 00B B0_B1_B2_B3 No byte switching + 01B B1_B0_B3_B2 B0B1B2B3 => B1B0B3B2 + 10B B2_B3_B0_B1 B0B1B2B3 => B2B3B0B1 + + RXENDI 9:8 rw Endianness for Receive Direction + Determine a byte swap between peripheral (left hand side) and memory + interface (right hand side). + 00B B0_B1_B2_B3 No byte switching + 01B B1_B0_B3_B2 B0B1B2B3 => B1B0B3B2 + 10B B2_B3_B0_B1 B0B1B2B3 => B2B3B0B1 + 11B B3_B2_B1_B0 B0B1B2B3 => B3B2B1B0 + + TXBL 5:4 rw Burst Length for Transmit Direction + Selects burst length for TX direction. + Others are reserved and will result in 2_WORDS burst length. + 01B 2_WORDS 2 words + 10B 4_WORDS 4 words + 11B 8_WORDS 8 words + + RXBL 3:2 rw Burst Length for Receive Direction + Selects burst length for RX direction. + Others are reserved and will result in 2_WORDS burst length. + 01B 2_WORDS 2 words + 10B 4_WORDS 4 words + 11B 8_WORDS 8 words + */ + *AR9_DMA_PCTRL = 0x1f28; +} + +#ifdef CONFIG_EXTRA_SWITCH +static int external_switch_init(void) +{ + ar9_sw_chip_init(0, RGMII_MODE); + + ar9_dma_init(); + + return 0; +} +#endif /* CONFIG_EXTRA_SWITCH */ + +#if defined(CONFIG_CMD_HTTPD) + +static int image_info (ulong addr) +{ + void *hdr = (void *)addr; + + printf ("\n## Checking Image at %08lx ...\n", addr); + + switch (genimg_get_format (hdr)) { + case IMAGE_FORMAT_LEGACY: + puts (" Legacy image found\n"); + if (!image_check_magic (hdr)) { + puts (" Bad Magic Number\n"); + return 1; + } + + if (!image_check_hcrc (hdr)) { + puts (" Bad Header Checksum\n"); + return 1; + } + + image_print_contents (hdr); + + puts (" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + puts (" Bad Data CRC\n"); + return 1; + } + puts ("OK\n"); + return 0; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + puts (" FIT image found\n"); + + if (!fit_check_format (hdr)) { + puts ("Bad FIT image format!\n"); + return 1; + } + + fit_print_contents (hdr); + + if (!fit_all_image_check_hashes (hdr)) { + puts ("Bad hash in FIT image!\n"); + return 1; + } + + return 0; +#endif + default: + puts ("Unknown image format!\n"); + break; + } + + return 1; +} + +int do_http_upgrade(const unsigned char *data, const ulong size) +{ + /* check the image */ + if(image_info(data)) { + return -1; + } + /* write the image to the flash */ + puts("http ugrade ...\n"); + return 0; +} + +int do_http_progress(const int state) +{ + /* toggle LED's here */ + switch(state) { + case HTTP_PROGRESS_START: + puts("http start\n"); + break; + case HTTP_PROGRESS_TIMEOUT: + break; + case HTTP_PROGRESS_UPLOAD_READY: + puts("http upload ready\n"); + break; + case HTTP_PROGRESS_UGRADE_READY: + puts("http ugrade ready\n"); + break; + case HTTP_PROGRESS_UGRADE_FAILED: + puts("http ugrade failed\n"); + break; + } + return 0; +} + +unsigned long do_http_tmp_address(void) +{ + char *s = getenv ("ram_addr"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + return 0 /*0x80a00000*/; +} + +#endif diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h new file mode 100644 index 000000000..766f1e00d --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x139 /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0x2200 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1800 +#define MC_DC22_VALUE 0x1818 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x59 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x514 +#define MC_DC29_VALUE 0x2d93 +#define MC_DC30_VALUE 0x8235 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h new file mode 100644 index 000000000..6d940ac6c --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x13f /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0x2200 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1600 +#define MC_DC22_VALUE 0x1616 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x5d /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x514 +#define MC_DC29_VALUE 0x2d93 +#define MC_DC30_VALUE 0x8235 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h new file mode 100644 index 000000000..b00177e0a --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x80B +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xD02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x144 /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xF +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1200 +#define MC_DC22_VALUE 0x1212 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x66 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x5FB +#define MC_DC29_VALUE 0x35DF +#define MC_DC30_VALUE 0x99E9 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h new file mode 100644 index 000000000..7f87d43f7 --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for AR9 Ref Board DDR 221 Mhz - by Ng Aik Ann 16th May 2008 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x403 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x90c +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xf02 +#define MC_DC12_VALUE 0x2c8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x12f /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xc800 +#define MC_DC17_VALUE 0xf +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1500 +#define MC_DC22_VALUE 0x1515 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x57 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x6b8 +#define MC_DC29_VALUE 0x3c84 +#define MC_DC30_VALUE 0xace5 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h new file mode 100644 index 000000000..2e49db99d --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for AR9 Ref Board DDR 221 Mhz - by Ng Aik Ann 16th May 2008 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x403 +#define MC_DC8_VALUE 0x103 +#define MC_DC9_VALUE 0xb0e +#define MC_DC10_VALUE 0x204 +#define MC_DC11_VALUE 0x1102 +#define MC_DC12_VALUE 0x2c8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x155 /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xc800 +#define MC_DC17_VALUE 0x13 +#define MC_DC18_VALUE 0x401 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0xc00 +#define MC_DC22_VALUE 0xc0c +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x74 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x798 +#define MC_DC29_VALUE 0x445d +#define MC_DC30_VALUE 0xc351 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/config.mk b/package/uboot-lantiq/files/board/infineon/easy50812/config.mk new file mode 100644 index 000000000..c0e5d8244 --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/config.mk @@ -0,0 +1,60 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# Danube board with MIPS 24Kc CPU core +# +sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp + +ifdef CONFIG_LZMA_BOOTSTRAP + +ifdef BUILD_BOOTSTRAP + +$(info BUILD_BOOTSTRAP ) +#TEXT_BASE = 0xB0000000 +TEXT_BASE = 0x80010000 + +else # BUILD_BOOTSTRAP + +ifndef TEXT_BASE +$(info redefine TEXT_BASE = 0x80040000 ) +TEXT_BASE = 0x80040000 +endif + +endif # BUILD_BOOTSTRAP + +else + +ifdef BUILD_BOOTSTRAP +$(error BUILD_BOOTSTRAP but not enabled in config) +endif + +ifndef TEXT_BASE +## Standard: boot from ebu +$(info redefine TEXT_BASE = 0xB0000000 ) +TEXT_BASE = 0xB0000000 +## For testing: boot from RAM +# TEXT_BASE = 0x80100000 +endif + +endif # CONFIG_LZMA_BOOTSTRAP diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S b/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S new file mode 100644 index 000000000..58f7a16ea --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S @@ -0,0 +1,543 @@ +/* + * Memory sub-system initialization code for AR9 board. + * + * Copyright (c) 2003 Wolfgang Denk + * Copyright (c) 2005 Andre Messerschmidt Infineon + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/* History: + peng liu May 25, 2006, for PLL setting after reset, 05252006 + */ +#include +#include +#include + +#if defined(CONFIG_USE_DDR_RAM) + +#if defined(CONFIG_CPU_111M_RAM_111M) || defined(CONFIG_CPU_333M_RAM_111M) +# include "ar9_ddr111_settings.h" +#elif defined(CONFIG_CPU_166M_RAM_166M) || defined(CONFIG_CPU_333M_RAM_166M) || defined(CONFIG_CPU_500M_RAM_166M) +# include "ar9_ddr166_settings.h" +#elif defined(CONFIG_CPU_442M_RAM_147M) +# include "ar9_ddr166_settings.h" +#elif defined(CONFIG_CPU_393M_RAM_196M) +# ifdef CONFIG_ETRON_RAM +# include "etron_ddr196_settings.h" +# else +# include "ar9_ddr196_settings.h" +# endif +#elif defined(CONFIG_CPU_442M_RAM_221M) +# include "ar9_ddr221_settings.h" +#elif defined(CONFIG_CPU_500M_RAM_250M) +# include "ar9_ddr250_settings.h" +#else +# warning "missing definition for ddr_settings.h, use default!" +# include "ar9_ddr_settings.h" +#endif +#endif /* CONFIG_USE_DDR_RAM */ + +#if defined(CONFIG_USE_DDR_RAM) && !defined(MC_DC0_VALUE) +#error "missing include of ddr_settings.h" +#endif + +#define EBU_MODUL_BASE 0xBE105300 +#define EBU_CLC(value) 0x0000(value) +#define EBU_CON(value) 0x0010(value) +#define EBU_ADDSEL0(value) 0x0020(value) +#define EBU_ADDSEL1(value) 0x0024(value) +#define EBU_ADDSEL2(value) 0x0028(value) +#define EBU_ADDSEL3(value) 0x002C(value) +#define EBU_BUSCON0(value) 0x0060(value) +#define EBU_BUSCON1(value) 0x0064(value) +#define EBU_BUSCON2(value) 0x0068(value) +#define EBU_BUSCON3(value) 0x006C(value) + +#define MC_MODUL_BASE 0xBF800000 +#define MC_ERRCAUSE(value) 0x0010(value) +#define MC_ERRADDR(value) 0x0020(value) +#define MC_CON(value) 0x0060(value) + +#define MC_SRAM_ENABLE 0x00000004 +#define MC_SDRAM_ENABLE 0x00000002 +#define MC_DDRRAM_ENABLE 0x00000001 + +#define MC_SDR_MODUL_BASE 0xBF800200 +#define MC_IOGP(value) 0x0000(value) +#define MC_CTRLENA(value) 0x0010(value) +#define MC_MRSCODE(value) 0x0020(value) +#define MC_CFGDW(value) 0x0030(value) +#define MC_CFGPB0(value) 0x0040(value) +#define MC_LATENCY(value) 0x0080(value) +#define MC_TREFRESH(value) 0x0090(value) +#define MC_SELFRFSH(value) 0x00A0(value) + +#define MC_DDR_MODUL_BASE 0xBF801000 +#define MC_DC00(value) 0x0000(value) +#define MC_DC01(value) 0x0010(value) +#define MC_DC02(value) 0x0020(value) +#define MC_DC03(value) 0x0030(value) +#define MC_DC04(value) 0x0040(value) +#define MC_DC05(value) 0x0050(value) +#define MC_DC06(value) 0x0060(value) +#define MC_DC07(value) 0x0070(value) +#define MC_DC08(value) 0x0080(value) +#define MC_DC09(value) 0x0090(value) +#define MC_DC10(value) 0x00A0(value) +#define MC_DC11(value) 0x00B0(value) +#define MC_DC12(value) 0x00C0(value) +#define MC_DC13(value) 0x00D0(value) +#define MC_DC14(value) 0x00E0(value) +#define MC_DC15(value) 0x00F0(value) +#define MC_DC16(value) 0x0100(value) +#define MC_DC17(value) 0x0110(value) +#define MC_DC18(value) 0x0120(value) +#define MC_DC19(value) 0x0130(value) +#define MC_DC20(value) 0x0140(value) +#define MC_DC21(value) 0x0150(value) +#define MC_DC22(value) 0x0160(value) +#define MC_DC23(value) 0x0170(value) +#define MC_DC24(value) 0x0180(value) +#define MC_DC25(value) 0x0190(value) +#define MC_DC26(value) 0x01A0(value) +#define MC_DC27(value) 0x01B0(value) +#define MC_DC28(value) 0x01C0(value) +#define MC_DC29(value) 0x01D0(value) +#define MC_DC30(value) 0x01E0(value) +#define MC_DC31(value) 0x01F0(value) +#define MC_DC32(value) 0x0200(value) +#define MC_DC33(value) 0x0210(value) +#define MC_DC34(value) 0x0220(value) +#define MC_DC35(value) 0x0230(value) +#define MC_DC36(value) 0x0240(value) +#define MC_DC37(value) 0x0250(value) +#define MC_DC38(value) 0x0260(value) +#define MC_DC39(value) 0x0270(value) +#define MC_DC40(value) 0x0280(value) +#define MC_DC41(value) 0x0290(value) +#define MC_DC42(value) 0x02A0(value) +#define MC_DC43(value) 0x02B0(value) +#define MC_DC44(value) 0x02C0(value) +#define MC_DC45(value) 0x02D0(value) +#define MC_DC46(value) 0x02E0(value) + +#define RCU_OFFSET 0xBF203000 +#define RCU_RST_REQ (RCU_OFFSET + 0x0010) +#define RCU_STS (RCU_OFFSET + 0x0014) + +#define CGU_OFFSET 0xBF103000 +#define PLL0_CFG (CGU_OFFSET + 0x0004) +#define PLL1_CFG (CGU_OFFSET + 0x0008) +#define PLL2_CFG (CGU_OFFSET + 0x000C) +#define CGU_SYS (CGU_OFFSET + 0x0010) +#define CGU_UPDATE (CGU_OFFSET + 0x0014) +#define IF_CLK (CGU_OFFSET + 0x0018) +#define CGU_SMD (CGU_OFFSET + 0x0020) +#define CGU_CT1SR (CGU_OFFSET + 0x0028) +#define CGU_CT2SR (CGU_OFFSET + 0x002C) +#define CGU_PCMCR (CGU_OFFSET + 0x0030) +#define PCI_CR_PCI (CGU_OFFSET + 0x0034) +#define CGU_OSC_CTRL (CGU_OFFSET + 0x001C) +#define CGU_MIPS_PWR_DWN (CGU_OFFSET + 0x0038) +#define CLK_MEASURE (CGU_OFFSET + 0x003C) + +#define pll1_36MHz_CONFIG 0x9800f25f + + .set noreorder + + +/* + * void ebu_init(void) + */ + .globl ebu_init + .ent ebu_init +ebu_init: + +#if defined(CONFIG_EBU_ADDSEL0) || defined(CONFIG_EBU_ADDSEL1) || \ + defined(CONFIG_EBU_ADDSEL2) || defined(CONFIG_EBU_ADDSEL3) || \ + defined(CONFIG_EBU_BUSCON0) || defined(CONFIG_EBU_BUSCON1) || \ + defined(CONFIG_EBU_BUSCON2) || defined(CONFIG_EBU_BUSCON3) + + li t1, EBU_MODUL_BASE +#if defined(CONFIG_EBU_ADDSEL0) + li t2, CONFIG_EBU_ADDSEL0 + sw t2, EBU_ADDSEL0(t1) +#endif +#if defined(CONFIG_EBU_ADDSEL1) + li t2, CONFIG_EBU_ADDSEL1 + sw t2, EBU_ADDSEL1(t1) +#endif +#if defined(CONFIG_EBU_ADDSEL2) + li t2, CONFIG_EBU_ADDSEL2 + sw t2, EBU_ADDSEL2(t1) +#endif +#if defined(CONFIG_EBU_ADDSEL3) + li t2, CONFIG_EBU_ADDSEL3 + sw t2, EBU_ADDSEL3(t1) +#endif + +#if defined(CONFIG_EBU_BUSCON0) + li t2, CONFIG_EBU_BUSCON0 + sw t2, EBU_BUSCON0(t1) +#endif +#if defined(CONFIG_EBU_BUSCON1) + li t2, CONFIG_EBU_BUSCON1 + sw t2, EBU_BUSCON1(t1) +#endif +#if defined(CONFIG_EBU_BUSCON2) + li t2, CONFIG_EBU_BUSCON2 + sw t2, EBU_BUSCON2(t1) +#endif +#if defined(CONFIG_EBU_BUSCON3) + li t2, CONFIG_EBU_BUSCON3 + sw t2, EBU_BUSCON3(t1) +#endif + +#endif + + j ra + nop + + .end ebu_init + + +/* + * void cgu_init(long) + * + * a0 has the clock value + */ + .globl cgu_init + .ent cgu_init +cgu_init: + li t2, CGU_SYS + lw t2,0(t2) + beq t2,a0,freq_up2date + nop + li t1, CGU_SYS + sw a0,0(t1) + +#if defined(CONFIG_CPU_333M_RAM_166M) && defined(CONFIG_USE_PLL1) + li t1, PLL1_CFG + li a1, pll1_36MHz_CONFIG + sw a1, 0(t1) +#endif + +#if defined(CONFIG_CLASS_II_DDR_PAD) + li t1, CGU_SMD + li a1, 0x200000 + sw a1, 0(t1) // Turn on DDR PAD Class II to INC drive. +#endif + + li t1, RCU_RST_REQ + li t2, 0x40000008 + sw t2,0(t1) + b wait_reset + nop + +wait_reset: + b wait_reset + nop + +freq_up2date: + j ra + nop + .end cgu_init + + +#ifndef CONFIG_USE_DDR_RAM +/* + * void sdram_init(long) + * + * a0 has the clock value + */ + .globl sdram_init + .ent sdram_init +sdram_init: + + /* SDRAM Initialization + */ + li t1, MC_MODUL_BASE + + /* Clear Error log registers */ + sw zero, MC_ERRCAUSE(t1) + sw zero, MC_ERRADDR(t1) + + /* Enable SDRAM module in memory controller */ + li t3, MC_SDRAM_ENABLE + lw t2, MC_CON(t1) + or t3, t2, t3 + sw t3, MC_CON(t1) + + li t1, MC_SDR_MODUL_BASE + + /* disable the controller */ + li t2, 0 + sw t2, MC_CTRLENA(t1) + + li t2, 0x822 + sw t2, MC_IOGP(t1) + + li t2, 0x2 + sw t2, MC_CFGDW(t1) + + /* Set CAS Latency */ + li t2, 0x00000020 + sw t2, MC_MRSCODE(t1) + + /* Set CS0 to SDRAM parameters */ + li t2, 0x000014d8 + sw t2, MC_CFGPB0(t1) + + /* Set SDRAM latency parameters */ + li t2, 0x00036325; /* BC PC100 */ + sw t2, MC_LATENCY(t1) + + /* Set SDRAM refresh rate */ + li t2, 0x00000C30 + sw t2, MC_TREFRESH(t1) + + /* Clear Power-down registers */ + sw zero, MC_SELFRFSH(t1) + + /* Finally enable the controller */ + li t2, 1 + sw t2, MC_CTRLENA(t1) + + j ra + nop + + .end sdram_init + +#endif /* !CONFIG_USE_DDR_RAM */ + +#ifdef CONFIG_USE_DDR_RAM +/* + * void ddrram_init(long) + * + * a0 has the clock value + */ + .globl ddrram_init + .ent ddrram_init +ddrram_init: + + /* DDR-DRAM Initialization + */ + li t1, MC_MODUL_BASE + + /* Clear Error log registers */ + sw zero, MC_ERRCAUSE(t1) + sw zero, MC_ERRADDR(t1) + + /* Enable DDR module in memory controller */ + li t3, MC_DDRRAM_ENABLE + lw t2, MC_CON(t1) + or t3, t2, t3 + sw t3, MC_CON(t1) + + li t1, MC_DDR_MODUL_BASE + + /* Write configuration to DDR controller registers */ + li t2, MC_DC0_VALUE + sw t2, MC_DC00(t1) + + li t2, MC_DC1_VALUE + sw t2, MC_DC01(t1) + + li t2, MC_DC2_VALUE + sw t2, MC_DC02(t1) + + li t2, MC_DC3_VALUE + sw t2, MC_DC03(t1) + + li t2, MC_DC4_VALUE + sw t2, MC_DC04(t1) + + li t2, MC_DC5_VALUE + sw t2, MC_DC05(t1) + + li t2, MC_DC6_VALUE + sw t2, MC_DC06(t1) + + li t2, MC_DC7_VALUE + sw t2, MC_DC07(t1) + + li t2, MC_DC8_VALUE + sw t2, MC_DC08(t1) + + li t2, MC_DC9_VALUE + sw t2, MC_DC09(t1) + + li t2, MC_DC10_VALUE + sw t2, MC_DC10(t1) + + li t2, MC_DC11_VALUE + sw t2, MC_DC11(t1) + + li t2, MC_DC12_VALUE + sw t2, MC_DC12(t1) + + li t2, MC_DC13_VALUE + sw t2, MC_DC13(t1) + + li t2, MC_DC14_VALUE + sw t2, MC_DC14(t1) + + li t2, MC_DC15_VALUE + sw t2, MC_DC15(t1) + + li t2, MC_DC16_VALUE + sw t2, MC_DC16(t1) + + li t2, MC_DC17_VALUE + sw t2, MC_DC17(t1) + + li t2, MC_DC18_VALUE + sw t2, MC_DC18(t1) + + li t2, MC_DC19_VALUE + sw t2, MC_DC19(t1) + + li t2, MC_DC20_VALUE + sw t2, MC_DC20(t1) + + li t2, MC_DC21_VALUE + sw t2, MC_DC21(t1) + + li t2, MC_DC22_VALUE + sw t2, MC_DC22(t1) + + li t2, MC_DC23_VALUE + sw t2, MC_DC23(t1) + + li t2, MC_DC24_VALUE + sw t2, MC_DC24(t1) + + li t2, MC_DC25_VALUE + sw t2, MC_DC25(t1) + + li t2, MC_DC26_VALUE + sw t2, MC_DC26(t1) + + li t2, MC_DC27_VALUE + sw t2, MC_DC27(t1) + + li t2, MC_DC28_VALUE + sw t2, MC_DC28(t1) + + li t2, MC_DC29_VALUE + sw t2, MC_DC29(t1) + + li t2, MC_DC30_VALUE + sw t2, MC_DC30(t1) + + li t2, MC_DC31_VALUE + sw t2, MC_DC31(t1) + + li t2, MC_DC32_VALUE + sw t2, MC_DC32(t1) + + li t2, MC_DC33_VALUE + sw t2, MC_DC33(t1) + + li t2, MC_DC34_VALUE + sw t2, MC_DC34(t1) + + li t2, MC_DC35_VALUE + sw t2, MC_DC35(t1) + + li t2, MC_DC36_VALUE + sw t2, MC_DC36(t1) + + li t2, MC_DC37_VALUE + sw t2, MC_DC37(t1) + + li t2, MC_DC38_VALUE + sw t2, MC_DC38(t1) + + li t2, MC_DC39_VALUE + sw t2, MC_DC39(t1) + + li t2, MC_DC40_VALUE + sw t2, MC_DC40(t1) + + li t2, MC_DC41_VALUE + sw t2, MC_DC41(t1) + + li t2, MC_DC42_VALUE + sw t2, MC_DC42(t1) + + li t2, MC_DC43_VALUE + sw t2, MC_DC43(t1) + + li t2, MC_DC44_VALUE + sw t2, MC_DC44(t1) + + li t2, MC_DC45_VALUE + sw t2, MC_DC45(t1) + + li t2, MC_DC46_VALUE + sw t2, MC_DC46(t1) + + li t2, 0x00000100 + sw t2, MC_DC03(t1) + + j ra + nop + + .end ddrram_init +#endif /* CONFIG_USE_DDR_RAM */ + + .globl lowlevel_init + .ent lowlevel_init +lowlevel_init: + /* EBU, CGU and SDRAM/DDR-RAM Initialization. + */ + move t0, ra + /* We rely on the fact that non of the following ..._init() functions + * modify t0 + */ +#if defined(CONFIG_SYS_EBU_BOOT) +/* + using PPL1 value +*/ + li a0,0x90 + bal cgu_init + nop +#endif /* CONFIG_SYS_EBU_BOOT */ + + bal ebu_init + nop + +#ifdef CONFIG_SYS_EBU_BOOT +#ifndef CONFIG_SYS_RAMBOOT +#ifdef CONFIG_USE_DDR_RAM + bal ddrram_init + nop +#else + bal sdram_init + nop +#endif +#endif /* CONFIG_SYS_RAMBOOT */ +#endif /* CONFIG_SYS_EBU_BOOT */ + + move ra, t0 + j ra + nop + + .end lowlevel_init diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S b/package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S new file mode 100644 index 000000000..e0d7971d8 --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S @@ -0,0 +1,48 @@ +/* + * Power Management unit initialization code for AMAZON development board. + * + * Copyright (c) 2003 Ou Ke, Infineon. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +#define PMU_PWDCR 0xBF10201C +#define PMU_SR 0xBF102020 + + .globl pmuenable + +pmuenable: + li t0, PMU_PWDCR + li t1, 0x2 /* enable everything */ + sw t1, 0(t0) +#if 0 +1: + li t0, PMU_SR + lw t2, 0(t0) + bne t1, t2, 1b + nop +#endif + j ra + nop + + diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds b/package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds new file mode 100644 index 000000000..9a6cd1b8a --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* +OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips") +*/ +OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips") +OUTPUT_ARCH(mips) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.text) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { *(.data) } + + . = .; + _gp = ALIGN(16) + 0x7ff0; + + .got : { + __got_start = .; + *(.got) + __got_end = .; + } + + .sdata : { *(.sdata) } + + .u_boot_cmd : { + __u_boot_cmd_start = .; + *(.u_boot_cmd) + __u_boot_cmd_end = .; + } + + uboot_end_data = .; + num_got_entries = (__got_end - __got_start) >> 2; + + . = ALIGN(4); + .sbss (NOLOAD) : { *(.sbss) } + .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } + uboot_end = .; +} diff --git a/package/uboot-lantiq/files/cpu/mips/ar9/Makefile b/package/uboot-lantiq/files/cpu/mips/ar9/Makefile new file mode 100644 index 000000000..c48d02eaa --- /dev/null +++ b/package/uboot-lantiq/files/cpu/mips/ar9/Makefile @@ -0,0 +1,46 @@ +######################################################################### +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS = clock.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/package/uboot-lantiq/files/cpu/mips/ar9/clock.c b/package/uboot-lantiq/files/cpu/mips/ar9/clock.c new file mode 100644 index 000000000..a8aecb422 --- /dev/null +++ b/package/uboot-lantiq/files/cpu/mips/ar9/clock.c @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +ulong ifx_get_ddr_hz(void) +{ + switch((*AR9_CGU_SYS) & 0x05) { + case 0x01: + case 0x05: + return CLOCK_111M; + + case 0x00: + case 0x04: + return CLOCK_166M; + } + + return 0; +} + +ulong ifx_get_cpuclk(void) +{ + switch((*AR9_CGU_SYS) & 0x05) { + case 0x00: + case 0x01: + return CLOCK_333M; + + case 0x04: + return CLOCK_166M; + + case 0x05: + return CLOCK_111M; + } + + return 0; +} + +ulong get_bus_freq(ulong dummy) +{ + unsigned int ddr_clock=ifx_get_ddr_hz(); + if((*AR9_CGU_SYS) & 0x40){ + return ddr_clock/2; + } else { + return ddr_clock; + } +} diff --git a/package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S b/package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S new file mode 100644 index 000000000..fc482dcd6 --- /dev/null +++ b/package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S @@ -0,0 +1,60 @@ + +#define IFX_CACHE_EXTRA_INVALID_TAG \ + mtc0 zero, CP0_TAGLO, 1; \ + mtc0 zero, CP0_TAGLO, 2; \ + mtc0 zero, CP0_TAGLO, 3; \ + mtc0 zero, CP0_TAGLO, 4; + +#define IFX_CACHE_EXTRA_OPERATION \ + /* set WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ECCF_WST; \ + or a0, a1; \ + mtc0 a0, CP0_ECC; \ + \ + li a0, K0BASE; \ + move a2, t2; /* icacheSize */ \ + move a3, t4; /* icacheLineSize */ \ + move a1, a2; \ + icacheop(a0,a1,a2,a3,(Index_Store_Tag_I)); \ + \ + /* clear WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ~ECCF_WST; \ + and a0, a1; \ + mtc0 a0, CP0_ECC; \ + \ + /* 1: initialise dcache tags. */ \ + \ + /* cache line size */ \ + li a2, CFG_CACHELINE_SIZE; \ + /* kseg0 mem address */ \ + li a1, 0; \ + li a3, CFG_CACHE_SETS * CFG_CACHE_WAYS; \ +1: \ + /* store tag (invalid, not locked) */ \ + cache 0x8, 0(a1); \ + cache 0x9, 0(a1); \ + \ + add a3, -1; \ + bne a3, zero, 1b; \ + add a1, a2; \ + \ + /* set WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ECCF_WST; \ + or a0, a1; \ + mtc0 a0, CP0_ECC; \ + \ + li a0, K0BASE; \ + move a2, t3; /* dcacheSize */ \ + move a3, t5; /* dcacheLineSize */ \ + move a1, a2; \ + icacheop(a0,a1,a2,a3,(Index_Store_Tag_D)); \ + \ + /* clear WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ~ECCF_WST; \ + and a0, a1; \ + mtc0 a0, CP0_ECC; + diff --git a/package/uboot-lantiq/files/drivers/net/ifx_etop.c b/package/uboot-lantiq/files/drivers/net/ifx_etop.c index 9a9e51fa0..8a03683c0 100644 --- a/package/uboot-lantiq/files/drivers/net/ifx_etop.c +++ b/package/uboot-lantiq/files/drivers/net/ifx_etop.c @@ -36,11 +36,17 @@ #include #include #include +#include #include "ifx_etop.h" +#if defined(CONFIG_AR9) +#define TX_CHAN_NO 1 +#define RX_CHAN_NO 0 +#else #define TX_CHAN_NO 7 #define RX_CHAN_NO 6 +#endif #define NUM_RX_DESC PKTBUFSRX #define NUM_TX_DESC 8 @@ -245,7 +251,19 @@ static void lq_eth_halt(struct eth_device *dev) } } -static int lq_eth_send(struct eth_device *dev, volatile void *packet,int length) +#ifdef DEBUG +static void lq_dump(const u8 *data, const u32 length) +{ + u32 i; + debug("\n"); + for(i=0;istatus.field.DataLen = (u32)length; flush_cache((u32)packet, tx_desc->status.field.DataLen); + asm("SYNC"); tx_desc->status.field.OWN=1; res=length; tx_num++; if (tx_num==NUM_TX_DESC) tx_num=0; +#ifdef DEBUG + lq_dump(tx_desc->DataPtr, tx_desc->status.field.DataLen); +#endif + dma_writel(dma_cs, TX_CHAN_NO); if (!(dma_readl(dma_cctrl) & 1)) { dma_writel(dma_cctrl, dma_readl(dma_cctrl) | 1); @@ -298,6 +321,10 @@ static int lq_eth_recv(struct eth_device *dev) if ((rx_desc->status.field.C == 0) || (rx_desc->status.field.OWN == 1)) { return 0; } + debug("rx"); +#ifdef DEBUG + lq_dump(rx_desc->DataPtr, rx_desc->status.field.DataLen); +#endif length = rx_desc->status.field.DataLen; if (length > 4) { invalidate_dcache_range((u32)CKSEG0ADDR(rx_desc->DataPtr), (u32) CKSEG0ADDR(rx_desc->DataPtr) + length); diff --git a/package/uboot-lantiq/files/include/asm-mips/ar9.h b/package/uboot-lantiq/files/include/asm-mips/ar9.h new file mode 100644 index 000000000..cfafe4490 --- /dev/null +++ b/package/uboot-lantiq/files/include/asm-mips/ar9.h @@ -0,0 +1,424 @@ +/* + * (C) Copyright 2010 + * Ralph Hempel + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/***********************************************************************/ +/* Module : PMU register address and bits */ +/***********************************************************************/ +#define AR9_PMU (0xBF102000) +/* PMU Power down Control Register */ +#define AR9_PMU_PWDCR ((volatile u32*)(AR9_PMU + 0x001C)) +/* PMU Status Register */ +#define AR9_PMU_SR ((volatile u32*)(AR9_PMU + 0x0020)) +/** DMA block */ +#define AR9_PMU_DMA (1<<5) +#define AR9_PMU_SDIO (1<<16) +#define AR9_PMU_USB0 (1<<6) +#define AR9_PMU_USB0_P (1<<0) +#define AR9_PMU_SWITCH (1<<28) + + +/***********************************************************************/ +/* Module : RCU register address and bits */ +/***********************************************************************/ +#define AR9_RCU_BASE_ADDR (0xBF203000) +#define AR9_RCU_RST_REQ ((volatile u32*)(AR9_RCU_BASE_ADDR + 0x0010)) +#define AR9_RCU_RST_STAT ((volatile u32*)(AR9_RCU_BASE_ADDR + 0x0014)) +#define AR9_RST_ALL (1 << 30) + +/*** Reset Request Register Bits ***/ +#define AR9_RCU_RST_REQ_SRST (1 << 30) +#define AR9_RCU_RST_REQ_ARC_JTAG (1 << 20) +#define AR9_RCU_RST_REQ_PCI (1 << 13) +#define AR9_RCU_RST_REQ_AFE (1 << 11) +#define AR9_RCU_RST_REQ_SDIO (1 << 19) +#define AR9_RCU_RST_REQ_DMA (1 << 9) +#define AR9_RCU_RST_REQ_PPE (1 << 8) +#define AR9_RCU_RST_REQ_DFE (1 << 7) + +/***********************************************************************/ +/* Module : GPIO register address and bits */ +/***********************************************************************/ +#define AR9_GPIO (0xBE100B00) +/***Port 0 Data Output Register (0010H)***/ +#define AR9_GPIO_P0_OUT ((volatile u32 *)(AR9_GPIO+ 0x0010)) +/***Port 1 Data Output Register (0040H)***/ +#define AR9_GPIO_P1_OUT ((volatile u32 *)(AR9_GPIO+ 0x0040)) +/***Port 2 Data Output Register (0070H)***/ +#define AR9_GPIO_P2_OUT ((volatile u32 *)(AR9_GPIO+ 0x0070)) +/***Port 3 Data Output Register (00A0H)***/ +#define AR9_GPIO_P3_OUT ((volatile u32 *)(AR9_GPIO+ 0x00A0)) +/***Port 0 Data Input Register (0014H)***/ +#define AR9_GPIO_P0_IN ((volatile u32 *)(AR9_GPIO+ 0x0014)) +/***Port 1 Data Input Register (0044H)***/ +#define AR9_GPIO_P1_IN ((volatile u32 *)(AR9_GPIO+ 0x0044)) +/***Port 2 Data Input Register (0074H)***/ +#define AR9_GPIO_P2_IN ((volatile u32 *)(AR9_GPIO+ 0x0074)) +/***Port 3 Data Input Register (00A4H)***/ +#define AR9_GPIO_P3_IN ((volatile u32 *)(AR9_GPIO+ 0x00A4)) +/***Port 0 Direction Register (0018H)***/ +#define AR9_GPIO_P0_DIR ((volatile u32 *)(AR9_GPIO+ 0x0018)) +/***Port 1 Direction Register (0048H)***/ +#define AR9_GPIO_P1_DIR ((volatile u32 *)(AR9_GPIO+ 0x0048)) +/***Port 2 Direction Register (0078H)***/ +#define AR9_GPIO_P2_DIR ((volatile u32 *)(AR9_GPIO+ 0x0078)) +/***Port 3 Direction Register (0048H)***/ +#define AR9_GPIO_P3_DIR ((volatile u32 *)(AR9_GPIO+ 0x00A8)) +/***Port 0 Alternate Function Select Register 0 (001C H) ***/ +#define AR9_GPIO_P0_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x001C)) +/***Port 1 Alternate Function Select Register 0 (004C H) ***/ +#define AR9_GPIO_P1_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x004C)) +/***Port 2 Alternate Function Select Register 0 (007C H) ***/ +#define AR9_GPIO_P2_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x007C)) +/***Port 3 Alternate Function Select Register 0 (00AC H) ***/ +#define AR9_GPIO_P3_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x00AC)) +/***Port 0 Alternate Function Select Register 1 (0020 H) ***/ +#define AR9_GPIO_P0_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0020)) +/***Port 1 Alternate Function Select Register 0 (0050 H) ***/ +#define AR9_GPIO_P1_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0050)) +/***Port 2 Alternate Function Select Register 0 (0080 H) ***/ +#define AR9_GPIO_P2_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0080)) +/***Port 3 Alternate Function Select Register 0 (0064 H) ***/ +#define AR9_GPIO_P3_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0064)) +/***Port 0 Open Drain Control Register (0024H)***/ +#define AR9_GPIO_P0_OD ((volatile u32 *)(AR9_GPIO+ 0x0024)) +/***Port 1 Open Drain Control Register (0054H)***/ +#define AR9_GPIO_P1_OD ((volatile u32 *)(AR9_GPIO+ 0x0054)) +/***Port 2 Open Drain Control Register (0084H)***/ +#define AR9_GPIO_P2_OD ((volatile u32 *)(AR9_GPIO+ 0x0084)) +/***Port 3 Open Drain Control Register (0034H)***/ +#define AR9_GPIO_P3_OD ((volatile u32 *)(AR9_GPIO+ 0x0034)) +/***Port 0 Input Schmitt-Trigger Off Register (0028 H) ***/ +#define AR9_GPIO_P0_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0028)) +/***Port 1 Input Schmitt-Trigger Off Register (0058 H) ***/ +#define AR9_GPIO_P1_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0058)) +/***Port 2 Input Schmitt-Trigger Off Register (0088 H) ***/ +#define AR9_GPIO_P2_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0088)) +/***Port 3 Input Schmitt-Trigger Off Register (0094 H) ***/ +//#define AR9_GPIO_P3_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0094)) +/***Port 0 Pull Up/Pull Down Select Register (002C H)***/ +#define AR9_GPIO_P0_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x002C)) +/***Port 1 Pull Up/Pull Down Select Register (005C H)***/ +#define AR9_GPIO_P1_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x005C)) +/***Port 2 Pull Up/Pull Down Select Register (008C H)***/ +#define AR9_GPIO_P2_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x008C)) +/***Port 3 Pull Up/Pull Down Select Register (0038 H)***/ +#define AR9_GPIO_P3_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x0038)) +/***Port 0 Pull Up Device Enable Register (0030 H)***/ +#define AR9_GPIO_P0_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x0030)) +/***Port 1 Pull Up Device Enable Register (0060 H)***/ +#define AR9_GPIO_P1_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x0060)) +/***Port 2 Pull Up Device Enable Register (0090 H)***/ +#define AR9_GPIO_P2_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x0090)) +/***Port 3 Pull Up Device Enable Register (003c H)***/ +#define AR9_GPIO_P3_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x003C)) + +/***********************************************************************/ +/* Module : CGU register address and bits */ +/***********************************************************************/ +#define AR9_CGU (0xBF103000) +/***CGU Clock PLL0 ***/ +#define AR9_CGU_PLL0_CFG ((volatile u32*)(AR9_CGU+ 0x0004)) +/***CGU Clock PLL1 ***/ +#define AR9_CGU_PLL1_CFG ((volatile u32*)(AR9_CGU+ 0x0008)) +/***CGU Clock SYS Mux Register***/ +#define AR9_CGU_SYS ((volatile u32*)(AR9_CGU+ 0x0010)) +/***CGU Interface Clock Control Register***/ +#define AR9_CGU_IFCCR ((volatile u32*)(AR9_CGU+ 0x0018)) +/***CGU PCI Clock Control Register**/ +#define AR9_CGU_PCICR ((volatile u32*)(AR9_CGU+ 0x0034)) +#define CLOCK_60M 60000000 +#define CLOCK_83M 83333333 +#define CLOCK_111M 111111111 +#define CLOCK_133M 133333333 +#define CLOCK_166M 166666667 +#define CLOCK_196M 196666667 +#define CLOCK_333M 333333333 +#define CLOCK_366M 366666667 +#define CLOCK_500M 500000000 + +/***********************************************************************/ +/* Module : MPS register address and bits */ +/***********************************************************************/ +#define AR9_MPS (KSEG1+0x1F107000) +#define AR9_MPS_CHIPID ((volatile u32*)(AR9_MPS + 0x0344)) +#define AR9_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1)) +#define AR9_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1)) +#define AR9_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1)) + +/***********************************************************************/ +/* Module : EBU register address and bits */ +/***********************************************************************/ +#define AR9_EBU (0xBE105300) + +#define AR9_EBU_CLC ((volatile u32*)(AR9_EBU+ 0x0000)) +#define AR9_EBU_CLC_DISS (1 << 1) +#define AR9_EBU_CLC_DISR (1 << 0) + +#define AR9_EBU_ID ((volatile u32*)(AR9_EBU+ 0x0008)) + +/***EBU Global Control Register***/ +#define AR9_EBU_CON ((volatile u32*)(AR9_EBU+ 0x0010)) +#define AR9_EBU_CON_DTACS (value) (((( 1 << 3) - 1) & (value)) << 20) +#define AR9_EBU_CON_DTARW (value) (((( 1 << 3) - 1) & (value)) << 16) +#define AR9_EBU_CON_TOUTC (value) (((( 1 << 8) - 1) & (value)) << 8) +#define AR9_EBU_CON_ARBMODE (value) (((( 1 << 2) - 1) & (value)) << 6) +#define AR9_EBU_CON_ARBSYNC (1 << 5) +//#define AR9_EBU_CON_1 (1 << 3) + +/***EBU Address Select Register 0***/ +#define AR9_EBU_ADDSEL0 ((volatile u32*)(AR9_EBU + 0x0020)) +/***EBU Address Select Register 1***/ +#define AR9_EBU_ADDSEL1 ((volatile u32*)(AR9_EBU + 0x0024)) +/***EBU Address Select Register 2***/ +#define AR9_EBU_ADDSEL2 ((volatile u32*)(AR9_EBU + 0x0028)) +/***EBU Address Select Register 3***/ +#define AR9_EBU_ADDSEL3 ((volatile u32*)(AR9_EBU + 0x002C)) +#define AR9_EBU_ADDSEL_BASE (value) (((( 1 << 20) - 1) & (value)) << 12) +#define AR9_EBU_ADDSEL_MASK (value) (((( 1 << 4) - 1) & (value)) << 4) +#define AR9_EBU_ADDSEL_MIRRORE (1 << 1) +#define AR9_EBU_ADDSEL_REGEN (1 << 0) + +/***EBU Bus Configuration Register 0***/ +#define AR9_EBU_BUSCON0 ((volatile u32*)(AR9_EBU+ 0x0060)) +#define AR9_EBU_BUSCON0_WRDIS (1 << 31) +#define AR9_EBU_BUSCON0_ADSWP (value) (1 << 30) +#define AR9_EBU_BUSCON0_PG_EN (value) (1 << 29) +#define AR9_EBU_BUSCON0_AGEN (value) (((( 1 << 3) - 1) & (value)) << 24) +#define AR9_EBU_BUSCON0_SETUP (1 << 22) +#define AR9_EBU_BUSCON0_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define AR9_EBU_BUSCON0_WAITINV (1 << 19) +#define AR9_EBU_BUSCON0_VN_EN (1 << 18) +#define AR9_EBU_BUSCON0_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define AR9_EBU_BUSCON0_ALEC (value) (((( 1 << 2) - 1) & (value)) << 14) +#define AR9_EBU_BUSCON0_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 12) +#define AR9_EBU_BUSCON0_WAITWDC (value) (((( 1 << 4) - 1) & (value)) << 8) +#define AR9_EBU_BUSCON0_WAITRRC (value) (((( 1 << 2) - 1) & (value)) << 6) +#define AR9_EBU_BUSCON0_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define AR9_EBU_BUSCON0_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define AR9_EBU_BUSCON0_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***EBU Bus Configuration Register 1***/ +#define AR9_EBU_BUSCON1 ((volatile u32*)(AR9_EBU+ 0x0064)) +#define AR9_EBU_BUSCON1_WRDIS (1 << 31) +#define AR9_EBU_BUSCON1_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29) +#define AR9_EBU_BUSCON1_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27) +#define AR9_EBU_BUSCON1_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24) +#define AR9_EBU_BUSCON1_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22) +#define AR9_EBU_BUSCON1_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define AR9_EBU_BUSCON1_WAITINV (1 << 19) +#define AR9_EBU_BUSCON1_SETUP (1 << 18) +#define AR9_EBU_BUSCON1_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define AR9_EBU_BUSCON1_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9) +#define AR9_EBU_BUSCON1_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6) +#define AR9_EBU_BUSCON1_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define AR9_EBU_BUSCON1_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define AR9_EBU_BUSCON1_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***EBU Bus Configuration Register 2***/ +#define AR9_EBU_BUSCON2 ((volatile u32*)(AR9_EBU+ 0x0068)) +#define AR9_EBU_BUSCON2_WRDIS (1 << 31) +#define AR9_EBU_BUSCON2_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29) +#define AR9_EBU_BUSCON2_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27) +#define AR9_EBU_BUSCON2_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24) +#define AR9_EBU_BUSCON2_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22) +#define AR9_EBU_BUSCON2_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define AR9_EBU_BUSCON2_WAITINV (1 << 19) +#define AR9_EBU_BUSCON2_SETUP (1 << 18) +#define AR9_EBU_BUSCON2_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define AR9_EBU_BUSCON2_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9) +#define AR9_EBU_BUSCON2_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6) +#define AR9_EBU_BUSCON2_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define AR9_EBU_BUSCON2_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define AR9_EBU_BUSCON2_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***EBU Bus Configuration Register 2***/ +#define AR9_EBU_BUSCON3 ((volatile u32*)(AR9_EBU+ 0x006C)) +#define AR9_EBU_BUSCON3_WRDIS (1 << 31) +#define AR9_EBU_BUSCON3_ADSWP (value) (1 << 30) +#define AR9_EBU_BUSCON3_PG_EN (value) (1 << 29) +#define AR9_EBU_BUSCON3_AGEN (value) (((( 1 << 3) - 1) & (value)) << 24) +#define AR9_EBU_BUSCON3_SETUP (1 << 22) +#define AR9_EBU_BUSCON3_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define AR9_EBU_BUSCON3_WAITINV (1 << 19) +#define AR9_EBU_BUSCON3_VN_EN (1 << 18) +#define AR9_EBU_BUSCON3_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define AR9_EBU_BUSCON3_ALEC (value) (((( 1 << 2) - 1) & (value)) << 14) +#define AR9_EBU_BUSCON3_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 12) +#define AR9_EBU_BUSCON3_WAITWDC (value) (((( 1 << 4) - 1) & (value)) << 8) +#define AR9_EBU_BUSCON3_WAITRRC (value) (((( 1 << 2) - 1) & (value)) << 6) +#define AR9_EBU_BUSCON3_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define AR9_EBU_BUSCON3_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define AR9_EBU_BUSCON3_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***********************************************************************/ +/* Module : SDRAM register address and bits */ +/***********************************************************************/ +#define AR9_SDRAM (0xBF800000) + +/***********************************************************************/ +/* Module : ASC0 register address and bits */ +/***********************************************************************/ +#define AR9_ASC0 (KSEG1 | 0x1E100400) +#define AR9_ASC0_TBUF ((volatile u32*)(AR9_ASC0 + 0x0020)) +#define AR9_ASC0_RBUF ((volatile u32*)(AR9_ASC0 + 0x0024)) +#define AR9_ASC0_FSTAT ((volatile u32*)(AR9_ASC0 + 0x0048)) + +/***********************************************************************/ +/* Module : ASC1 register address and bits */ +/***********************************************************************/ +#define AR9_ASC1 (KSEG1 | 0x1E100C00) +#define AR9_ASC1_TBUF ((volatile u32*)(AR9_ASC1 + 0x0020)) +#define AR9_ASC1_RBUF ((volatile u32*)(AR9_ASC1 + 0x0024)) +#define AR9_ASC1_FSTAT ((volatile u32*)(AR9_ASC1 + 0x0048)) + +/***********************************************************************/ +/* Module : DMA register address and bits */ +/***********************************************************************/ +#define AR9_DMA_OFFSET (0xBE104100) +/***********************************************************************/ +#define AR9_DMA_CLC ((volatile u32*)(AR9_DMA_OFFSET + 0x0000)) +#define AR9_DMA_ID ((volatile u32*)(AR9_DMA_OFFSET + 0x0008)) +#define AR9_DMA_CTRL (volatile u32*)(AR9_DMA_BASE + 0x10) + +/** DMA Port Select Register */ +#define AR9_DMA_PS ((volatile u32*)(AR9_DMA_OFFSET + 0x0040)) +/** DMA Port Control Register */ +#define AR9_DMA_PCTRL ((volatile u32*)(AR9_DMA_OFFSET + 0x0044)) +#define AR9_DMA_IRNEN ((volatile u32*)(AR9_DMA_OFFSET + 0x00F4)) +#define AR9_DMA_IRNCR ((volatile u32*)(AR9_DMA_OFFSET + 0x00F8)) +#define AR9_DMA_IRNICR ((volatile u32*)(AR9_DMA_OFFSET + 0x00FC)) + +#define AR9_DMA_CS ((volatile u32*)(AR9_DMA_OFFSET + 0x0018)) +#define AR9_DMA_CCTRL ((volatile u32*)(AR9_DMA_OFFSET + 0x001C)) +#define AR9_DMA_CDBA ((volatile u32*)(AR9_DMA_OFFSET + 0x0020)) +#define AR9_DMA_CIE ((volatile u32*)(AR9_DMA_OFFSET + 0x002C)) +#define AR9_DMA_CIS ((volatile u32*)(AR9_DMA_OFFSET + 0x0028)) +#define AR9_DMA_CDLEN ((volatile u32*)(AR9_DMA_OFFSET + 0x0024)) +#define AR9_DMA_CPOLL ((volatile u32*)(AR9_DMA_OFFSET + 0x0014)) + +/***********************************************************************/ +/* Module : GPORT switch register */ +/***********************************************************************/ +#define AR9_SW (0xBE108000) +#define AR9_SW_PS (AR9_SW + 0x000) +#define AR9_SW_P0_CTL (AR9_SW + 0x004) +#define AR9_SW_P1_CTL (AR9_SW + 0x008) +#define AR9_SW_P2_CTL (AR9_SW + 0x00C) +#define AR9_SW_P0_VLAN (AR9_SW + 0x010) +#define AR9_SW_P1_VLAN (AR9_SW + 0x014) +#define AR9_SW_P2_VLAN (AR9_SW + 0x018) +#define AR9_SW_P0_INCTL (AR9_SW + 0x020) +#define AR9_SW_P1_INCTL (AR9_SW + 0x024) +#define AR9_SW_P2_INCTL (AR9_SW + 0x028) +#define AR9_SW_DF_PORTMAP (AR9_SW + 0x02C) +#define AR9_SW_P0_ECS_Q32 (AR9_SW + 0x030) +#define AR9_SW_P0_ECS_Q10 (AR9_SW + 0x034) +#define AR9_SW_P0_ECW_Q32 (AR9_SW + 0x038) +#define AR9_SW_P0_ECW_Q10 (AR9_SW + 0x03C) +#define AR9_SW_P1_ECS_Q32 (AR9_SW + 0x040) +#define AR9_SW_P1_ECS_Q10 (AR9_SW + 0x044) +#define AR9_SW_P1_ECW_Q32 (AR9_SW + 0x048) +#define AR9_SW_P1_ECW_Q10 (AR9_SW + 0x04C) +#define AR9_SW_P2_ECS_Q32 (AR9_SW + 0x050) +#define AR9_SW_P2_ECS_Q10 (AR9_SW + 0x054) +#define AR9_SW_P2_ECW_Q32 (AR9_SW + 0x058) +#define AR9_SW_P2_ECW_Q10 (AR9_SW + 0x05C) +#define AR9_SW_INT_ENA (AR9_SW + 0x060) +#define AR9_SW_INT_ST (AR9_SW + 0x064) +#define AR9_SW_GCTL0 (AR9_SW + 0x068) +#define AR9_SW_GCTL1 (AR9_SW + 0x06C) +#define AR9_SW_ARP (AR9_SW + 0x070) +#define AR9_SW_STRM_CTL (AR9_SW + 0x074) +#define AR9_SW_RGMII_CTL (AR9_SW + 0x078) +#define AR9_SW_1P_PRT (AR9_SW + 0x07C) +#define AR9_SW_GBKT_SZBS (AR9_SW + 0x080) +#define AR9_SW_GBKT_SZEBS (AR9_SW + 0x084) +#define AR9_SW_BF_TH (AR9_SW + 0x088) +#define AR9_SW_PMAC_HD_CTL (AR9_SW + 0x08C) +#define AR9_SW_PMAC_SA1 (AR9_SW + 0x090) +#define AR9_SW_PMAC_SA2 (AR9_SW + 0x094) +#define AR9_SW_PMAC_DA1 (AR9_SW + 0x098) +#define AR9_SW_PMAC_DA2 (AR9_SW + 0x09C) +#define AR9_SW_PMAC_VLAN (AR9_SW + 0x0A0) +#define AR9_SW_PMAC_TX_IPG (AR9_SW + 0x0A4) +#define AR9_SW_PMAC_RX_IPG (AR9_SW + 0x0A8) +#define AR9_SW_ADR_TB_CTL0 (AR9_SW + 0x0AC) +#define AR9_SW_ADR_TB_CTL1 (AR9_SW + 0x0B0) +#define AR9_SW_ADR_TB_CTL2 (AR9_SW + 0x0B4) +#define AR9_SW_ADR_TB_ST0 (AR9_SW + 0x0B8) +#define AR9_SW_ADR_TB_ST1 (AR9_SW + 0x0BC) +#define AR9_SW_ADR_TB_ST2 (AR9_SW + 0x0C0) +#define AR9_SW_RMON_CTL (AR9_SW + 0x0C4) +#define AR9_SW_RMON_ST (AR9_SW + 0x0C8) +#define AR9_SW_MDIO_CTL (AR9_SW + 0x0CC) +#define AR9_SW_MDIO_DATA (AR9_SW + 0x0D0) +#define AR9_SW_TP_FLT_ACT (AR9_SW + 0x0D4) +#define AR9_SW_PRTCL_FLT_ACT (AR9_SW + 0x0D8) +#define AR9_SW_VLAN_FLT0 (AR9_SW + 0x100) +#define AR9_SW_VLAN_FLT1 (AR9_SW + 0x104) +#define AR9_SW_VLAN_FLT2 (AR9_SW + 0x108) +#define AR9_SW_VLAN_FLT3 (AR9_SW + 0x10C) +#define AR9_SW_VLAN_FLT4 (AR9_SW + 0x110) +#define AR9_SW_VLAN_FLT5 (AR9_SW + 0x114) +#define AR9_SW_VLAN_FLT6 (AR9_SW + 0x118) +#define AR9_SW_VLAN_FLT7 (AR9_SW + 0x11C) +#define AR9_SW_VLAN_FLT8 (AR9_SW + 0x120) +#define AR9_SW_VLAN_FLT9 (AR9_SW + 0x124) +#define AR9_SW_VLAN_FLT10 (AR9_SW + 0x128) +#define AR9_SW_VLAN_FLT11 (AR9_SW + 0x12C) +#define AR9_SW_VLAN_FLT12 (AR9_SW + 0x130) +#define AR9_SW_VLAN_FLT13 (AR9_SW + 0x134) +#define AR9_SW_VLAN_FLT14 (AR9_SW + 0x138) +#define AR9_SW_VLAN_FLT15 (AR9_SW + 0x13C) +#define AR9_SW_TP_FLT10 (AR9_SW + 0x140) +#define AR9_SW_TP_FLT32 (AR9_SW + 0x144) +#define AR9_SW_TP_FLT54 (AR9_SW + 0x148) +#define AR9_SW_TP_FLT76 (AR9_SW + 0x14C) +#define AR9_SW_DFSRV_MAP0 (AR9_SW + 0x150) +#define AR9_SW_DFSRV_MAP1 (AR9_SW + 0x154) +#define AR9_SW_DFSRV_MAP2 (AR9_SW + 0x158) +#define AR9_SW_DFSRV_MAP3 (AR9_SW + 0x15C) +#define AR9_SW_TCP_PF0 (AR9_SW + 0x160) +#define AR9_SW_TCP_PF1 (AR9_SW + 0x164) +#define AR9_SW_TCP_PF2 (AR9_SW + 0x168) +#define AR9_SW_TCP_PF3 (AR9_SW + 0x16C) +#define AR9_SW_TCP_PF4 (AR9_SW + 0x170) +#define AR9_SW_TCP_PF5 (AR9_SW + 0x174) +#define AR9_SW_TCP_PF6 (AR9_SW + 0x178) +#define AR9_SW_TCP_PF7 (AR9_SW + 0x17C) +#define AR9_SW_RA_03_00 (AR9_SW + 0x180) +#define AR9_SW_RA_07_04 (AR9_SW + 0x184) +#define AR9_SW_RA_0B_08 (AR9_SW + 0x188) +#define AR9_SW_RA_0F_0C (AR9_SW + 0x18C) +#define AR9_SW_RA_13_10 (AR9_SW + 0x190) +#define AR9_SW_RA_17_14 (AR9_SW + 0x194) +#define AR9_SW_RA_1B_18 (AR9_SW + 0x198) +#define AR9_SW_RA_1F_1C (AR9_SW + 0x19C) +#define AR9_SW_RA_23_20 (AR9_SW + 0x1A0) +#define AR9_SW_RA_27_24 (AR9_SW + 0x1A4) +#define AR9_SW_RA_2B_28 (AR9_SW + 0x1A8) +#define AR9_SW_RA_2F_2C (AR9_SW + 0x1AC) +#define AR9_SW_F0 (AR9_SW + 0x1B0) +#define AR9_SW_F1 (AR9_SW + 0x1B4) + +#define REG32(addr) *((volatile u32 *)(addr)) diff --git a/package/uboot-lantiq/files/include/configs/easy50812.h b/package/uboot-lantiq/files/include/configs/easy50812.h new file mode 100644 index 000000000..c7e96c1bc --- /dev/null +++ b/package/uboot-lantiq/files/include/configs/easy50812.h @@ -0,0 +1,104 @@ +/* + * (C) Copyright 2003-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * This file contains the configuration parameters for the Danube reference board. + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* #define DEBUG */ + +#define CONFIG_MIPS32 1 /* MIPS32 CPU compatible */ +#define CONFIG_MIPS34KC 1 /* MIPS 34Kc CPU core */ +#define CONFIG_AR9 1 /* an AR9 device */ +#define CONFIG_EASY50812 1 /* on the AR9 reference board */ +#define CONFIG_SYS_MAX_RAM 32*1024*1024 /* 32 MB */ +#define CONFIG_FLASH_CFI_DRIVER 1 /* using CFI flash driver */ + +#define CONFIG_SYS_INIT_RAM_LOCK_MIPS + +/* use PPL1 and fixed values for CPU / DDR and bus speed */ +#define CONFIG_USE_PLL1 +#define CONFIG_CPU_333M_RAM_166M +#define CONFIG_CLASS_II_DDR_PAD + +#ifdef CONFIG_SYS_RAMBOOT + #define CONFIG_SKIP_LOWLEVEL_INIT /* no cache */ +#else + #define CONFIG_SYS_EBU_BOOT + #define INFINEON_EBU_BOOTCFG 0x688C688C /* CMULT = 8 for 150 MHz */ +#endif + +#ifndef CPU_CLOCK_RATE +#define CPU_CLOCK_RATE (ifx_get_cpuclk()) +#endif + +#define CONFIG_SYS_PROMPT "AR9 => " /* Monitor Command Prompt */ +#undef CONFIG_SYS_HUSH_PARSER /* Use the HUSH parser */ + +/* + * Include common defines/options for all Lantiq boards + */ +#include "ifx-common.h" + +/* + * Cache Configuration (cpu/chip specific, ar9) + */ +#define CONFIG_SYS_DCACHE_SIZE (16384) +#define CONFIG_SYS_ICACHE_SIZE (16384) +#define CONFIG_SYS_CACHELINE_SIZE (32) +#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NO_WA + +#define CONFIG_NET_MULTI +#if 0 +#define CONFIG_M4530_ETH +#define CONFIG_M4530_FPGA +#endif + +#define CONFIG_IFX_ETOP /* lantiq ethernet cpe interface */ +#define CLK_OUT2_25MHZ +#define CONFIG_EXTRA_SWITCH /* search for external switches like tantos */ +#define CONFIG_RMII /* use interface in RMII mode */ +#define CONFIG_MII +#define CONFIG_CMD_MII /* enable MII command */ + +#define CONFIG_IFX_ASC /* use lantiq ASC driver */ +#ifdef CONFIG_USE_ASC0 +#define CONFIG_SYS_IFX_ASC_BASE 0x1E100400 +#else +#define CONFIG_SYS_IFX_ASC_BASE 0x1E100C00 +#endif + +#ifdef CONFIG_SYS_RAMBOOT +/* Configuration of EBU: */ +/* starting address from 0xb0000000 */ +/* make the flash available from RAM boot */ +# define CONFIG_EBU_ADDSEL0 0x10000031 +# define CONFIG_EBU_BUSCON0 0x0001D7FF +#endif + +#define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */ + +#endif /* __CONFIG_H */ diff --git a/package/uboot-lantiq/patches/100-ifx_targets.patch b/package/uboot-lantiq/patches/100-ifx_targets.patch index 9c313e0a4..da4cd4864 100644 --- a/package/uboot-lantiq/patches/100-ifx_targets.patch +++ b/package/uboot-lantiq/patches/100-ifx_targets.patch @@ -23,7 +23,7 @@ ${LIST_au1xx0} \ --- a/Makefile +++ b/Makefile -@@ -474,7 +475,7 @@ $(obj)include/autoconf.mk: $(obj)include +@@ -474,7 +474,7 @@ $(obj)include/autoconf.mk: $(obj)include set -e ; \ : Extract the config macros ; \ $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \ @@ -32,7 +32,7 @@ mv $@.tmp $@ ######################################################################### -@@ -3354,7 +3355,7 @@ incaip_config: unconfig +@@ -3354,7 +3354,7 @@ incaip_config: unconfig { echo "#define CPU_CLOCK_RATE 150000000" >>$(obj)include/config.h ; \ $(XECHO) "... with 150MHz system clock" ; \ } @@ -41,7 +41,7 @@ tb0229_config: unconfig @$(MKCONFIG) $(@:_config=) mips mips tb0229 -@@ -3395,6 +3396,30 @@ vct_platinumavc_onenand_small_config: un +@@ -3395,6 +3395,50 @@ vct_platinumavc_onenand_small_config: un @$(MKCONFIG) -a vct mips mips vct micronas ######################################################################### @@ -68,6 +68,26 @@ + fi + @$(MKCONFIG) -a $(word 1,$(subst _, ,$@)) mips mips easy50712 infineon danube + ++easy50812%config : unconfig ++ @mkdir -p $(obj)include ++ @mkdir -p $(obj)board/infineon/easy50812 ++ @[ -z "$(findstring ramboot,$@)" ] || \ ++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/infineon/easy50812/config.tmp ; \ ++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \ ++ $(XECHO) "... with ramboot configuration" ; \ ++ } ++ @if [ "$(findstring _DDR,$@)" ] ; then \ ++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \ ++ DDR=$(subst DDR,,$(filter DDR%,$(subst _, ,$@))); \ ++ case "$${DDR}" in \ ++ 111M|166M|e111M|e166M|promos400|samsung166|psc166) \ ++ $(XECHO) "... with DDR RAM config $${DDR}" ; \ ++ echo "#define CONFIG_USE_DDR_RAM_CFG_$${DDR}" >>$(obj)include/config.h ;; \ ++ *) $(XECHO) "... DDR RAM config \\\"$${DDR}\\\" unknown, use default"; \ ++ esac; \ ++ fi ++ @$(MKCONFIG) -a $(word 1,$(subst _, ,$@)) mips mips easy50812 infineon ar9 ++ +######################################################################### ## MIPS32 AU1X00 ######################################################################### From ced0222eb7ae70d05c1f41f7751a6037dd7a7f44 Mon Sep 17 00:00:00 2001 From: ralph Date: Tue, 30 Mar 2010 16:17:38 +0000 Subject: [PATCH 16/45] [uboot-lantiq] httpd failsafe - add image check and flash access git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20610 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/uboot-lantiq/Makefile | 2 +- .../files/board/infineon/easy50712/danube.c | 66 +++-------------- .../files/board/infineon/easy50812/ar9.c | 73 ++++--------------- package/uboot-lantiq/patches/300-httpd.patch | 5 +- 4 files changed, 27 insertions(+), 119 deletions(-) diff --git a/package/uboot-lantiq/Makefile b/package/uboot-lantiq/Makefile index 48f468316..985f3638a 100644 --- a/package/uboot-lantiq/Makefile +++ b/package/uboot-lantiq/Makefile @@ -84,7 +84,7 @@ define Package/uboot-lantiq/install of=$(1)/$(UBOOT_CONFIG)/u-boot.bin \ bs=64k conv=sync ifeq ($(CONFIG_UBOOT_RAMBOOT),y) - if [ -e $(UBOOT_CONFIG).conf ]; then \ + if [ -e $(UBOOT_DDR_CONFIG) ]; then \ perl ./gct \ $(UBOOT_DDR_CONFIG) \ $(PKG_BUILD_DIR)/$(UBOOT_CONFIG)_ramboot/u-boot.srec \ diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/danube.c b/package/uboot-lantiq/files/board/infineon/easy50712/danube.c index f9b2b7626..0b33a3ad4 100644 --- a/package/uboot-lantiq/files/board/infineon/easy50712/danube.c +++ b/package/uboot-lantiq/files/board/infineon/easy50712/danube.c @@ -340,69 +340,22 @@ int board_eth_init(bd_t *bis) } #if defined(CONFIG_CMD_HTTPD) -static int image_info (ulong addr) -{ - void *hdr = (void *)addr; - - printf ("\n## Checking Image at %08lx ...\n", addr); - - switch (genimg_get_format (hdr)) { - case IMAGE_FORMAT_LEGACY: - puts (" Legacy image found\n"); - if (!image_check_magic (hdr)) { - puts (" Bad Magic Number\n"); - return 1; - } - - if (!image_check_hcrc (hdr)) { - puts (" Bad Header Checksum\n"); - return 1; - } - - image_print_contents (hdr); - - puts (" Verifying Checksum ... "); - if (!image_check_dcrc (hdr)) { - puts (" Bad Data CRC\n"); - return 1; - } - puts ("OK\n"); - return 0; -#if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - puts (" FIT image found\n"); - - if (!fit_check_format (hdr)) { - puts ("Bad FIT image format!\n"); - return 1; - } - - fit_print_contents (hdr); - - if (!fit_all_image_check_hashes (hdr)) { - puts ("Bad hash in FIT image!\n"); - return 1; - } - - return 0; -#endif - default: - puts ("Unknown image format!\n"); - break; - } - - return 1; -} - int do_http_upgrade(const unsigned char *data, const ulong size) { + char buf[128]; + + if(getenv ("ram_addr") == NULL) + return -1; + if(getenv ("kernel_addr") == NULL) + return -1; /* check the image */ - if(image_info(data)) { + if(run_command("imi ${ram_addr}", 0) < 0) { return -1; } /* write the image to the flash */ puts("http ugrade ...\n"); - return 0; + sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size); + return run_command(buf, 0); } int do_http_progress(const int state) @@ -413,6 +366,7 @@ int do_http_progress(const int state) puts("http start\n"); break; case HTTP_PROGRESS_TIMEOUT: + puts("."); break; case HTTP_PROGRESS_UPLOAD_READY: puts("http upload ready\n"); diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c b/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c index dd6be9bdf..d4cd049af 100644 --- a/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c @@ -48,10 +48,10 @@ extern ulong ifx_get_cpuclk(void); #define ID_SAMURAI_1 0x0007 #define SAMURAI_ID_REG0 0xA0 #define SAMURAI_ID_REG1 0xA1 -#define ID_TANTOS 0x2599 +#define ID_TANTOS 0x2599 -#define RGMII_MODE 0 -#define MII_MODE 1 +#define RGMII_MODE 0 +#define MII_MODE 1 #define REV_MII_MODE 2 #define RED_MII_MODE_IC 3 /*Input clock */ #define RGMII_MODE_100MB 4 @@ -565,70 +565,22 @@ static int external_switch_init(void) #endif /* CONFIG_EXTRA_SWITCH */ #if defined(CONFIG_CMD_HTTPD) - -static int image_info (ulong addr) -{ - void *hdr = (void *)addr; - - printf ("\n## Checking Image at %08lx ...\n", addr); - - switch (genimg_get_format (hdr)) { - case IMAGE_FORMAT_LEGACY: - puts (" Legacy image found\n"); - if (!image_check_magic (hdr)) { - puts (" Bad Magic Number\n"); - return 1; - } - - if (!image_check_hcrc (hdr)) { - puts (" Bad Header Checksum\n"); - return 1; - } - - image_print_contents (hdr); - - puts (" Verifying Checksum ... "); - if (!image_check_dcrc (hdr)) { - puts (" Bad Data CRC\n"); - return 1; - } - puts ("OK\n"); - return 0; -#if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - puts (" FIT image found\n"); - - if (!fit_check_format (hdr)) { - puts ("Bad FIT image format!\n"); - return 1; - } - - fit_print_contents (hdr); - - if (!fit_all_image_check_hashes (hdr)) { - puts ("Bad hash in FIT image!\n"); - return 1; - } - - return 0; -#endif - default: - puts ("Unknown image format!\n"); - break; - } - - return 1; -} - int do_http_upgrade(const unsigned char *data, const ulong size) { + char buf[128]; + + if(getenv ("ram_addr") == NULL) + return -1; + if(getenv ("kernel_addr") == NULL) + return -1; /* check the image */ - if(image_info(data)) { + if(run_command("imi ${ram_addr}", 0) < 0) { return -1; } /* write the image to the flash */ puts("http ugrade ...\n"); - return 0; + sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size); + return run_command(buf, 0); } int do_http_progress(const int state) @@ -639,6 +591,7 @@ int do_http_progress(const int state) puts("http start\n"); break; case HTTP_PROGRESS_TIMEOUT: + puts("."); break; case HTTP_PROGRESS_UPLOAD_READY: puts("http upload ready\n"); diff --git a/package/uboot-lantiq/patches/300-httpd.patch b/package/uboot-lantiq/patches/300-httpd.patch index f9a81e90c..25e84cde3 100644 --- a/package/uboot-lantiq/patches/300-httpd.patch +++ b/package/uboot-lantiq/patches/300-httpd.patch @@ -165,7 +165,7 @@ NetRxPacket = inpkt; NetRxPacketLen = len; et = (Ethernet_t *)inpkt; -@@ -1952,3 +1972,161 @@ ushort getenv_VLAN(char *var) +@@ -1952,3 +1972,162 @@ ushort getenv_VLAN(char *var) { return (string_to_VLAN(getenv(var))); } @@ -249,6 +249,8 @@ + NetArpWaitTxPacketSize = 0; + } + ++restart: ++ + eth_halt(); +#ifdef CONFIG_NET_MULTI + eth_set_current(); @@ -258,7 +260,6 @@ + return(-1); + } + -+restart: +#ifdef CONFIG_NET_MULTI + memcpy (NetOurEther, eth_get_dev()->enetaddr, 6); +#else From f12150b8254aebd42be8db3eff92f232047570ee Mon Sep 17 00:00:00 2001 From: blogic Date: Tue, 30 Mar 2010 21:06:27 +0000 Subject: [PATCH 17/45] [ifxmips] prepare kernel for voip git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20613 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/ifxmips/Makefile | 3 +- target/linux/ifxmips/extract.py | 9 +++++ target/linux/ifxmips/extract.sh | 36 +++++++++++++++++++ .../ifxmips/files/arch/mips/ifxmips/Makefile | 2 +- .../ifxmips/files/arch/mips/ifxmips/timer.c | 10 +++--- 5 files changed, 53 insertions(+), 7 deletions(-) create mode 100755 target/linux/ifxmips/extract.py create mode 100755 target/linux/ifxmips/extract.sh diff --git a/target/linux/ifxmips/Makefile b/target/linux/ifxmips/Makefile index addeef681..b82f78263 100644 --- a/target/linux/ifxmips/Makefile +++ b/target/linux/ifxmips/Makefile @@ -16,7 +16,8 @@ LINUX_VERSION:=2.6.30.10 CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -funit-at-a-time include $(INCLUDE_DIR)/target.mk -DEFAULT_PACKAGES+=kmod-pppoa ppp-mod-pppoa linux-atm atm-tools br2684ctl ifxmips-dsl-api ifxmips-dsl-control +DEFAULT_PACKAGES+=uboot-lantiq +#kmod-pppoa ppp-mod-pppoa linux-atm atm-tools br2684ctl ifxmips-dsl-api ifxmips-dsl-control ifx-tapidemo define Target/Description Build firmware images for Infineon Mips Controllers diff --git a/target/linux/ifxmips/extract.py b/target/linux/ifxmips/extract.py new file mode 100755 index 000000000..91b4a578d --- /dev/null +++ b/target/linux/ifxmips/extract.py @@ -0,0 +1,9 @@ +#!/usr/bin/python +from sys import stdin, stdout +while True: + c = stdin.read(2) + if len(c) < 2: + break + n1, n2 = ord(c[0]), ord(c[1]) + stdout.write(chr(((n2 & 15) << 4) + ((n2 & 240) >> 4))) + stdout.write(chr(((n1 & 15) << 4) + ((n1 & 240) >> 4))) diff --git a/target/linux/ifxmips/extract.sh b/target/linux/ifxmips/extract.sh new file mode 100755 index 000000000..4024969d1 --- /dev/null +++ b/target/linux/ifxmips/extract.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +DIR="$1/" +FILE="$1/$2" + +echo "This tool downloads the arcor a800 firmware release and extracts the voip firmware for the danube." +echo "Please only do so if it is legal in your country" + +[ ! -f ${FILE} ] && { + echo ${FILE} is missing + exit 1 +} + +[ ! -f ${DIR}bbd.crypt ] && { + dd if=${FILE} of=${DIR}bbd.crypt bs=1 skip=104 count=1472302 +} + +[ ! -f ${DIR}dsl_a.bin ] && { + dd if=${FILE} of=${DIR}dsl1.lzma bs=1 skip=2168832 count=150724 + lzma d ${DIR}dsl2.lzma ${DIR}dsl_a.bin +} + +[ ! -f ${DIR}dsl_b.bin ] && { + dd if=${FILE} of=${DIR}dsl2.lzma bs=1 skip=2320384 count=148343 + lzma d ${DIR}dsl1.lzma ${DIR}dsl_b.bin +} + +[ ! -f ${DIR}voip.bin ] && { + dd if=${FILE} of=${DIR}voip.lzma bs=1 skip=2468864 count=452105 + lzma d ${DIR}voip.lzma ${DIR}voip.bin +} +exit 0 + +# get lzma offsets +# hexdump -C arcor_A800_452CPW_FW_1.02.206\(20081201\).bin | grep "5d 00 00 80" +# hexdump -C arcor_A800_452CPW_FW_1.02.206\(20081201\).bin | grep "00 d5 08 00" diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile b/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile index 9710645b9..c330be634 100644 --- a/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile @@ -1 +1 @@ -obj-y := reset.o prom.o setup.o irq.o dma-core.o pmu.o board.o clock.o gpio.o +obj-y := reset.o prom.o setup.o irq.o dma-core.o pmu.o board.o clock.o gpio.o timer.o diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c b/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c index d05df2283..31e606c85 100644 --- a/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c @@ -13,11 +13,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #define MAX_NUM_OF_32BIT_TIMER_BLOCKS 6 From 08ce1c443c52e1d1388587e10993f0c5e050cf18 Mon Sep 17 00:00:00 2001 From: juhosg Date: Tue, 30 Mar 2010 21:24:05 +0000 Subject: [PATCH 18/45] ramips: sync kernel config git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20614 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/ramips/rt288x/config-2.6.32 | 15 ++++++++------- target/linux/ramips/rt305x/config-2.6.32 | 14 +++++++------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/target/linux/ramips/rt288x/config-2.6.32 b/target/linux/ramips/rt288x/config-2.6.32 index 7d7a45adf..fa912e044 100644 --- a/target/linux/ramips/rt288x/config-2.6.32 +++ b/target/linux/ramips/rt288x/config-2.6.32 @@ -16,8 +16,8 @@ CONFIG_BITREVERSE=y # CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set # CONFIG_CAVIUM_OCTEON_SIMULATOR is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CEVT_R4K_LIB=y CONFIG_CEVT_R4K=y +CONFIG_CEVT_R4K_LIB=y CONFIG_CFG80211_DEFAULT_PS_VALUE=0 CONFIG_CMDLINE="console=ttyS1,57600 rootfstype=squashfs,jffs2" # CONFIG_CPU_BIG_ENDIAN is not set @@ -26,9 +26,9 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_SYNC=y CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_LOONGSON2E is not set +CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS32_R1 is not set CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set CONFIG_CPU_MIPSR2=y @@ -50,8 +50,8 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_VR41XX is not set -CONFIG_CSRC_R4K_LIB=y CONFIG_CSRC_R4K=y +CONFIG_CSRC_R4K_LIB=y CONFIG_DECOMPRESS_LZMA=y CONFIG_DEVPORT=y # CONFIG_DM9000 is not set @@ -59,8 +59,8 @@ CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_DMA_NONCOHERENT=y CONFIG_EARLY_PRINTK=y # CONFIG_FSNOTIFY is not set -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_GENERIC_FIND_NEXT_BIT=y @@ -80,6 +80,8 @@ CONFIG_HW_HAS_PCI=y CONFIG_HW_RANDOM=m CONFIG_INITRAMFS_SOURCE="" CONFIG_IRQ_CPU=y +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_I4L is not set # CONFIG_LEDS_GPIO is not set # CONFIG_MACH_ALCHEMY is not set # CONFIG_MACH_DECSTATION is not set @@ -90,6 +92,7 @@ CONFIG_IRQ_CPU=y # CONFIG_MACH_VR41XX is not set # CONFIG_MII is not set # CONFIG_MIKROTIK_RB532 is not set +CONFIG_MIPS=y # CONFIG_MIPS_COBALT is not set CONFIG_MIPS_L1_CACHE_SHIFT=4 CONFIG_MIPS_MACHINE=y @@ -100,7 +103,6 @@ CONFIG_MIPS_MT_DISABLED=y CONFIG_MIPS_RALINK=y # CONFIG_MIPS_RAMIPS_NET is not set # CONFIG_MIPS_SIM is not set -CONFIG_MIPS=y # CONFIG_MTD_CFI_INTELEXT is not set # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y @@ -115,15 +117,14 @@ CONFIG_PHYLIB=y # CONFIG_PMC_YOSEMITE is not set # CONFIG_PNX8550_JBS is not set # CONFIG_PNX8550_STB810 is not set -# CONFIG_PROBE_INITRD_HEADER is not set CONFIG_RALINK_DEV_GPIO_BUTTONS=y CONFIG_RALINK_DEV_GPIO_LEDS=y CONFIG_RALINK_RT288X=y # CONFIG_RALINK_RT305X is not set CONFIG_RT288X_MACH_RT_N15=y CONFIG_RT288X_MACH_WZR_AGL300NH=y -CONFIG_RTL8366_SMI=y CONFIG_RTL8366S_PHY=y +CONFIG_RTL8366_SMI=y CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_SCSI_DMA is not set # CONFIG_SERIAL_8250_EXTENDED is not set diff --git a/target/linux/ramips/rt305x/config-2.6.32 b/target/linux/ramips/rt305x/config-2.6.32 index 6058fed0e..186000a21 100644 --- a/target/linux/ramips/rt305x/config-2.6.32 +++ b/target/linux/ramips/rt305x/config-2.6.32 @@ -16,8 +16,8 @@ CONFIG_BITREVERSE=y # CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set # CONFIG_CAVIUM_OCTEON_SIMULATOR is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CEVT_R4K_LIB=y CONFIG_CEVT_R4K=y +CONFIG_CEVT_R4K_LIB=y CONFIG_CFG80211_DEFAULT_PS_VALUE=0 CONFIG_CMDLINE="console=ttyS1,57600 rootfstype=squashfs,jffs2" # CONFIG_CPU_BIG_ENDIAN is not set @@ -26,9 +26,9 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_SYNC=y CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_LOONGSON2E is not set +CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS32_R1 is not set CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set CONFIG_CPU_MIPSR2=y @@ -50,16 +50,16 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_VR41XX is not set -CONFIG_CSRC_R4K_LIB=y CONFIG_CSRC_R4K=y +CONFIG_CSRC_R4K_LIB=y CONFIG_DECOMPRESS_LZMA=y # CONFIG_DM9000 is not set CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_DMA_NONCOHERENT=y CONFIG_EARLY_PRINTK=y # CONFIG_FSNOTIFY is not set -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_GENERIC_FIND_NEXT_BIT=y @@ -78,6 +78,8 @@ CONFIG_HAVE_OPROFILE=y CONFIG_HW_RANDOM=m CONFIG_INITRAMFS_SOURCE="" CONFIG_IRQ_CPU=y +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_I4L is not set # CONFIG_LEDS_GPIO is not set # CONFIG_MACH_ALCHEMY is not set # CONFIG_MACH_DECSTATION is not set @@ -88,6 +90,7 @@ CONFIG_IRQ_CPU=y # CONFIG_MACH_VR41XX is not set # CONFIG_MII is not set # CONFIG_MIKROTIK_RB532 is not set +CONFIG_MIPS=y # CONFIG_MIPS_COBALT is not set CONFIG_MIPS_L1_CACHE_SHIFT=5 CONFIG_MIPS_MACHINE=y @@ -98,20 +101,17 @@ CONFIG_MIPS_MT_DISABLED=y CONFIG_MIPS_RALINK=y CONFIG_MIPS_RAMIPS_NET=y # CONFIG_MIPS_SIM is not set -CONFIG_MIPS=y # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_PHYSMAP=y # CONFIG_NO_IOPORT is not set # CONFIG_NXP_STB220 is not set # CONFIG_NXP_STB225 is not set CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PCI=y CONFIG_PHYLIB=y # CONFIG_PMC_MSP is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_PNX8550_JBS is not set # CONFIG_PNX8550_STB810 is not set -# CONFIG_PROBE_INITRD_HEADER is not set CONFIG_RALINK_DEV_GPIO_BUTTONS=y CONFIG_RALINK_DEV_GPIO_LEDS=y # CONFIG_RALINK_RT288X is not set From 0e48f85042aa550aaa58b0f1770189f62ff42edf Mon Sep 17 00:00:00 2001 From: juhosg Date: Tue, 30 Mar 2010 21:24:08 +0000 Subject: [PATCH 19/45] mac80211: enable building of the rt2800 on the ramips target git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20615 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/mac80211/Makefile | 52 ++++++++++++++++--- .../patches/015-remove-rt2x00-options.patch | 26 ++++++++++ ...e-pci-code-if-CONFIG_PCI-not-defined.patch | 18 +++++++ .../601-rt2x00-lib-use-rt2x00dev-irq.patch | 11 ++++ 4 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 package/mac80211/patches/015-remove-rt2x00-options.patch create mode 100644 package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch create mode 100644 package/mac80211/patches/601-rt2x00-lib-use-rt2x00dev-irq.patch diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index 549e83896..8cec1b8ba 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 PKG_VERSION:=2010-03-24 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources # http://www.orbit-lab.org/kernel/compat-wireless-2.6/2010/11 \ # http://wireless.kernel.org/download/compat-wireless-2.6 @@ -42,12 +42,12 @@ define KernelPackage/cfg80211 $(call KernelPackage/mac80211/Default) TITLE:=cfg80211 - wireless configuration API DEPENDS+= +wireless-tools +iw @!LINUX_2_6_25 -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.33)),1) +ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.33)),1) FILES:= \ $(PKG_BUILD_DIR)/compat/compat.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/net/wireless/cfg80211.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,20,compat cfg80211) -else +else FILES:= \ $(PKG_BUILD_DIR)/compat/compat.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/compat/compat_firmware_class.$(LINUX_KMOD_SUFFIX) \ @@ -170,6 +170,11 @@ define Download/ar9170 endef $(eval $(call Download,ar9170)) +NEED_RT2X00_LIB_CRYPTO:=y +NEED_RT2X00_LIB_FIRMWARE:=y +NEED_RT2X00_LIB_HT:=y +NEED_RT2X00_LIB_LEDS:=y + define KernelPackage/rt2x00/Default $(call KernelPackage/mac80211/Default) TITLE:=Ralink Drivers for RT2x00 cards @@ -177,15 +182,19 @@ endef define KernelPackage/rt2x00-lib $(call KernelPackage/rt2x00/Default) - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +kmod-crc-itu-t + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 +kmod-crc-itu-t TITLE+= (LIB) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00lib.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,25,rt2x00lib) endef +define KernelPackage/rt2x00-lib/config + source "$(SOURCE)/Config.in.rt2x00" +endef + define KernelPackage/rt2x00-pci $(call KernelPackage/rt2x00/Default) - DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-lib +kmod-eeprom-93cx6 + DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-eeprom-93cx6 TITLE+= (PCI) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00pci.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,26,rt2x00pci) @@ -199,9 +208,17 @@ $(call KernelPackage/rt2x00/Default) AUTOLOAD:=$(call AutoLoad,26,rt2x00usb) endef +define KernelPackage/rt2x00-soc +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @TARGET_ramips +kmod-rt2x00-lib + TITLE+= (SoC) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00soc.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,26,rt2x00soc) +endef + define KernelPackage/rt2800-lib $(call KernelPackage/rt2x00/Default) - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-rt2x00-lib +USB_SUPPORT:kmod-rt2x00-usb + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +USB_SUPPORT:kmod-rt2x00-usb +TARGET_ramips:kmod-rt2x00-soc TITLE+= (rt2800 LIB) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800lib.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,27,rt2800lib) @@ -249,7 +266,7 @@ endef define KernelPackage/rt2800-pci $(call KernelPackage/rt2x00/Default) - DEPENDS+= +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-crc-ccitt + DEPENDS+= +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-crc-ccitt +TARGET_ramips:kmod-rt2x00-soc TITLE+= (RT2860 PCI) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800pci.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,28,rt2800pci) @@ -599,7 +616,17 @@ BUILDFLAGS:= \ $(if $(CONFIG_PACKAGE_ATH_DEBUG),-DCONFIG_ATH_DEBUG) \ -D__CONFIG_MAC80211_RC_DEFAULT=minstrel \ $(if $(CONFIG_ATH_USER_REGD),-DATH_USER_REGD=1) \ - $(if $(CONFIG_PACKAGE_ATH9K_USE_MINSTREL),-DATH9K_USE_MINSTREL) + $(if $(CONFIG_PACKAGE_ATH9K_USE_MINSTREL),-DATH9K_USE_MINSTREL) \ + $(if $(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS),-DCONFIG_RT2X00_LIB_DEBUGFS) \ + $(if $(NEED_RT2X00_LIB_HT),-DCONFIG_RT2X00_LIB_HT) \ + $(if $(NEED_RT2X00_LIB_CRYPTO),-DCONFIG_RT2X00_LIB_CRYPTO) \ + $(if $(NEED_RT2X00_LIB_FIRMWARE),-DCONFIG_RT2X00_LIB_FIRMWARE) \ + $(if $(NEED_RT2X00_LIB_LEDS),-DCONFIG_RT2X00_LIB_LEDS) \ + $(if $(CONFIG_PACKAGE_kmod-rt2x00-pci),-DCONFIG_RT2X00_LIB_PCI) \ + $(if $(CONFIG_PACKAGE_kmod-rt2x00-usb),-DCONFIG_RT2X00_LIB_USB) \ + $(if $(CONFIG_PACKAGE_kmod-rt2x00-soc),-DCONFIG_RT2X00_LIB_SOC) \ + $(if $(CONFIG_PCI_SUPPORT),-DCONFIG_RT2800PCI_PCI) \ + $(if $(CONFIG_TARGET_ramips),-DCONFIG_RT2800PCI_SOC) \ MAKE_OPTS:= \ CROSS_COMPILE="$(KERNEL_CROSS)" \ @@ -638,6 +665,12 @@ MAKE_OPTS:= \ CONFIG_RT2X00_LIB=$(if $(CONFIG_PACKAGE_kmod-rt2x00-lib),m) \ CONFIG_RT2X00_LIB_PCI=$(if $(CONFIG_PACKAGE_kmod-rt2x00-pci),m) \ CONFIG_RT2X00_LIB_USB=$(if $(CONFIG_PACKAGE_kmod-rt2x00-usb),m) \ + CONFIG_RT2X00_LIB_SOC=$(if $(CONFIG_PACKAGE_kmod-rt2x00-soc),m) \ + CONFIG_RT2X00_LIB_DEBUGFS=$(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS) \ + CONFIG_RT2X00_LIB_CRYPTO=$(NEED_RT2X00_LIB_CRYPTO) \ + CONFIG_RT2X00_LIB_FIRMWARE=$(NEED_RT2X00_LIB_FIRMWARE) \ + CONFIG_RT2X00_LIB_HT=$(NEED_RT2X00_LIB_HT) \ + CONFIG_RT2X00_LIB_LEDS=$(NEED_RT2X00_LIB_LEDS) \ CONFIG_RT2400PCI=$(if $(CONFIG_PACKAGE_kmod-rt2400-pci),m) \ CONFIG_RT2500PCI=$(if $(CONFIG_PACKAGE_kmod-rt2500-pci),m) \ CONFIG_RT2500USB=$(if $(CONFIG_PACKAGE_kmod-rt2500-usb),m) \ @@ -645,6 +678,8 @@ MAKE_OPTS:= \ CONFIG_RT73USB=$(if $(CONFIG_PACKAGE_kmod-rt73-usb),m) \ CONFIG_RT2800_LIB=$(if $(CONFIG_PACKAGE_kmod-rt2800-lib),m) \ CONFIG_RT2800PCI=$(if $(CONFIG_PACKAGE_kmod-rt2800-pci),m) \ + CONFIG_RT2800PCI_PCI=$(if $(CONFIG_PCI_SUPPORT),y) \ + CONFIG_RT2800PCI_SOC=$(if $(CONFIG_TARGET_ramips),y) \ CONFIG_RT2800USB=$(if $(CONFIG_PACKAGE_kmod-rt2800-usb),m) \ CONFIG_RTL8180=$(if $(CONFIG_PACKAGE_kmod-rtl8180),m) \ CONFIG_RTL8187=$(if $(CONFIG_PACKAGE_kmod-rtl8187),m) \ @@ -843,6 +878,7 @@ $(eval $(call KernelPackage,p54-usb)) $(eval $(call KernelPackage,rt2x00-lib)) $(eval $(call KernelPackage,rt2x00-pci)) $(eval $(call KernelPackage,rt2x00-usb)) +$(eval $(call KernelPackage,rt2x00-soc)) $(eval $(call KernelPackage,rt2800-lib)) $(eval $(call KernelPackage,rt2400-pci)) $(eval $(call KernelPackage,rt2500-pci)) diff --git a/package/mac80211/patches/015-remove-rt2x00-options.patch b/package/mac80211/patches/015-remove-rt2x00-options.patch new file mode 100644 index 000000000..f980979cc --- /dev/null +++ b/package/mac80211/patches/015-remove-rt2x00-options.patch @@ -0,0 +1,26 @@ +--- a/config.mk ++++ b/config.mk +@@ -276,12 +276,12 @@ CONFIG_RTL8180=m + + CONFIG_ADM8211=m + +-CONFIG_RT2X00_LIB_PCI=m ++# CONFIG_RT2X00_LIB_PCI=m + CONFIG_RT2400PCI=m + CONFIG_RT2500PCI=m + ifneq ($(CONFIG_CRC_CCITT),) + CONFIG_RT2800PCI=m +-CONFIG_RT2800PCI_PCI=y ++# CONFIG_RT2800PCI_PCI=y + # CONFIG_RT2800PCI_RT30XX=y + # CONFIG_RT2800PCI_RT35XX=y + # CONFIG_RT2800PCI_SOC=y +@@ -381,7 +381,7 @@ CONFIG_RT2800USB=m + # CONFIG_RT2800USB_RT35XX=y + # CONFIG_RT2800USB_UNKNOWN=y + endif +-CONFIG_RT2X00_LIB_USB=m ++# CONFIG_RT2X00_LIB_USB=m + NEED_RT2X00=y + # RT73USB requires firmware + ifneq ($(CONFIG_CRC_ITU_T),) diff --git a/package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch b/package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch new file mode 100644 index 000000000..3971413b0 --- /dev/null +++ b/package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/rt2x00/rt2x00pci.c ++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c +@@ -223,6 +223,7 @@ void rt2x00pci_uninitialize(struct rt2x0 + } + EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); + ++#ifdef CONFIG_PCI + /* + * PCI driver handlers. + */ +@@ -397,6 +398,7 @@ int rt2x00pci_resume(struct pci_dev *pci + } + EXPORT_SYMBOL_GPL(rt2x00pci_resume); + #endif /* CONFIG_PM */ ++#endif /* CONFIG_PCI */ + + /* + * rt2x00pci module information. diff --git a/package/mac80211/patches/601-rt2x00-lib-use-rt2x00dev-irq.patch b/package/mac80211/patches/601-rt2x00-lib-use-rt2x00dev-irq.patch new file mode 100644 index 000000000..22bfc2ebe --- /dev/null +++ b/package/mac80211/patches/601-rt2x00-lib-use-rt2x00dev-irq.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/rt2x00/rt2x00pci.c ++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c +@@ -213,7 +213,7 @@ void rt2x00pci_uninitialize(struct rt2x0 + /* + * Free irq line. + */ +- free_irq(to_pci_dev(rt2x00dev->dev)->irq, rt2x00dev); ++ free_irq(rt2x00dev->irq, rt2x00dev); + + /* + * Free DMA From c44ee422c3f7fb736b69ded2793a3673d0e51266 Mon Sep 17 00:00:00 2001 From: juhosg Date: Tue, 30 Mar 2010 21:24:10 +0000 Subject: [PATCH 20/45] ramips: register wifi device on the rt305x based boards git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20616 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../ramips/files/arch/mips/ralink/rt305x/mach-dir-300-revb.c | 1 + .../linux/ramips/files/arch/mips/ralink/rt305x/mach-fonera20n.c | 1 + .../linux/ramips/files/arch/mips/ralink/rt305x/mach-v22rw-2x2.c | 1 + .../linux/ramips/files/arch/mips/ralink/rt305x/mach-whr-g300n.c | 1 + 4 files changed, 4 insertions(+) diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-dir-300-revb.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-dir-300-revb.c index dd2a5f474..27fad6ad9 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-dir-300-revb.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-dir-300-revb.c @@ -116,6 +116,7 @@ static void __init dir_300b_init(void) ramips_register_gpio_buttons(-1, DIR_300B_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(dir_300b_gpio_buttons), dir_300b_gpio_buttons); + rt305x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_DIR_300_REVB, "DIR-300-revB", "D-Link DIR-300 revB", diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-fonera20n.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-fonera20n.c index 6dc4b9d3f..c87bdaf3e 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-fonera20n.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-fonera20n.c @@ -119,6 +119,7 @@ static void __init fonera20n_init(void) fonera20n_gpio_buttons); rt305x_register_ethernet(); + rt305x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_FONERA20N, "FONERA20N", "La Fonera 2.0N", diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-v22rw-2x2.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-v22rw-2x2.c index 89822c3cf..812dfb4a9 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-v22rw-2x2.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-v22rw-2x2.c @@ -110,6 +110,7 @@ static void __init v22rw_2x2_init(void) ramips_register_gpio_buttons(-1, V22RW_2X2_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(v22rw_2x2_gpio_buttons), v22rw_2x2_gpio_buttons); + rt305x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_V22RW_2X2, "V22RW-2X2", "Ralink AP-RT3052-V22RW-2X2", diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-whr-g300n.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-whr-g300n.c index 5d015e264..4e0e810bb 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-whr-g300n.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-whr-g300n.c @@ -136,6 +136,7 @@ static void __init whr_g300n_init(void) ramips_register_gpio_buttons(-1, WHR_G300N_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(whr_g300n_gpio_buttons), whr_g300n_gpio_buttons); + rt305x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_WHR_G300N, "WHR-G300N", "Buffalo WHR-G300N", From 7dc4c37a3ad94674f79638554fe8fe6e6bf2098f Mon Sep 17 00:00:00 2001 From: jow Date: Tue, 30 Mar 2010 23:24:46 +0000 Subject: [PATCH 21/45] [package] lua: drop refcounting patch in preparation for 10.03, it has unresolved issues resulting in random vm crashes git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20617 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/lua/Makefile | 2 +- package/lua/patches/600-refcounting.patch | 1128 --------------------- 2 files changed, 1 insertion(+), 1129 deletions(-) delete mode 100644 package/lua/patches/600-refcounting.patch diff --git a/package/lua/Makefile b/package/lua/Makefile index c8c64badf..0a5e8f343 100644 --- a/package/lua/Makefile +++ b/package/lua/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=lua PKG_VERSION:=5.1.4 -PKG_RELEASE:=5 +PKG_RELEASE:=6 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.lua.org/ftp/ \ diff --git a/package/lua/patches/600-refcounting.patch b/package/lua/patches/600-refcounting.patch deleted file mode 100644 index 554a7c42e..000000000 --- a/package/lua/patches/600-refcounting.patch +++ /dev/null @@ -1,1128 +0,0 @@ ---- a/src/lapi.c -+++ b/src/lapi.c -@@ -27,8 +27,8 @@ - #include "ltable.h" - #include "ltm.h" - #include "lundump.h" --#include "lvm.h" - #include "lnum.h" -+#include "lvm.h" - - - const char lua_ident[] = -@@ -117,6 +117,7 @@ LUA_API void lua_xmove (lua_State *from, - from->top -= n; - for (i = 0; i < n; i++) { - setobj2s(to, to->top++, from->top + i); -+ setnilvalue(from, from->top + i); - } - lua_unlock(to); - } -@@ -166,12 +167,14 @@ LUA_API void lua_settop (lua_State *L, i - if (idx >= 0) { - api_check(L, idx <= L->stack_last - L->base); - while (L->top < L->base + idx) -- setnilvalue(L->top++); -+ setnilvalue(L, L->top++); - L->top = L->base + idx; -+ setnilvalue(L, L->top); - } - else { -+ int i; - api_check(L, -(idx+1) <= (L->top - L->base)); -- L->top += idx+1; /* `subtract' index (index is negative) */ -+ setlvmtop(L, L->top + idx + 1); /* `subtract' index (index is negative) */ - } - lua_unlock(L); - } -@@ -183,7 +186,7 @@ LUA_API void lua_remove (lua_State *L, i - p = index2adr(L, idx); - api_checkvalidindex(L, p); - while (++p < L->top) setobjs2s(L, p-1, p); -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - } - -@@ -196,6 +199,7 @@ LUA_API void lua_insert (lua_State *L, i - api_checkvalidindex(L, p); - for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); - setobjs2s(L, p, L->top); -+ setnilvalue(L, L->top); - lua_unlock(L); - } - -@@ -220,7 +224,7 @@ LUA_API void lua_replace (lua_State *L, - if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ - luaC_barrier(L, curr_func(L), L->top - 1); - } -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - } - -@@ -259,14 +263,14 @@ LUA_API int lua_iscfunction (lua_State * - - - LUA_API int lua_isnumber (lua_State *L, int idx) { -- TValue n; -+ TValue n = tvinit(); - const TValue *o = index2adr(L, idx); - return tonumber(o, &n); - } - - - LUA_API int lua_isinteger (lua_State *L, int idx) { -- TValue tmp; -+ TValue tmp = tvinit(); - lua_Integer dum; - const TValue *o = index2adr(L, idx); - return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum)); -@@ -319,7 +323,7 @@ LUA_API int lua_lessthan (lua_State *L, - - - LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { -- TValue n; -+ TValue n = tvinit(); - const TValue *o = index2adr(L, idx); - if (tonumber(o, &n)) { - #ifdef LNUM_COMPLEX -@@ -333,7 +337,7 @@ LUA_API lua_Number lua_tonumber (lua_Sta - - - LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { -- TValue n; -+ TValue n = tvinit(); - /* Lua 5.1 documented behaviour is to return nonzero for non-integer: - * "If the number is not an integer, it is truncated in some non-specified way." - * I would suggest to change this, to return 0 for anything that would -@@ -369,7 +373,7 @@ LUA_API lua_Integer lua_tointeger (lua_S - - #ifdef LNUM_COMPLEX - LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) { -- TValue tmp; -+ TValue tmp = tvinit(); - const TValue *o = index2adr(L, idx); - if (tonumber(o, &tmp)) - return nvalue_complex(o); -@@ -465,7 +469,7 @@ LUA_API const void *lua_topointer (lua_S - - LUA_API void lua_pushnil (lua_State *L) { - lua_lock(L); -- setnilvalue(L->top); -+ setnilvalue(L, L->top); - api_incr_top(L); - lua_unlock(L); - } -@@ -548,8 +552,10 @@ LUA_API void lua_pushcclosure (lua_State - cl = luaF_newCclosure(L, n, getcurrenv(L)); - cl->c.f = fn; - L->top -= n; -- while (n--) -+ while (n--) { - setobj2n(L, &cl->c.upvalue[n], L->top+n); -+ setnilvalue(L, L->top + n); -+ } - setclvalue(L, L->top, cl); - lua_assert(iswhite(obj2gco(cl))); - api_incr_top(L); -@@ -600,7 +606,7 @@ LUA_API void lua_gettable (lua_State *L, - - LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { - StkId t; -- TValue key; -+ TValue key = tvinit(); - lua_lock(L); - t = index2adr(L, idx); - api_checkvalidindex(L, t); -@@ -689,7 +695,7 @@ LUA_API void lua_getfenv (lua_State *L, - setobj2s(L, L->top, gt(thvalue(o))); - break; - default: -- setnilvalue(L->top); -+ setnilvalue(L, L->top); - break; - } - api_incr_top(L); -@@ -709,21 +715,21 @@ LUA_API void lua_settable (lua_State *L, - t = index2adr(L, idx); - api_checkvalidindex(L, t); - luaV_settable(L, t, L->top - 2, L->top - 1); -- L->top -= 2; /* pop index and value */ -+ setlvmtop(L, L->top - 2); /* pop index and value */ - lua_unlock(L); - } - - - LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - StkId t; -- TValue key; -+ TValue key = tvinit(); - lua_lock(L); - api_checknelems(L, 1); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_settable(L, t, &key, L->top - 1); -- L->top--; /* pop value */ -+ setlvmtop(L, L->top - 1); /* pop value */ - lua_unlock(L); - } - -@@ -736,7 +742,7 @@ LUA_API void lua_rawset (lua_State *L, i - api_check(L, ttistable(t)); - setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); - luaC_barriert(L, hvalue(t), L->top-1); -- L->top -= 2; -+ setlvmtop(L, L->top - 2); - lua_unlock(L); - } - -@@ -749,7 +755,7 @@ LUA_API void lua_rawseti (lua_State *L, - api_check(L, ttistable(o)); - setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1); - luaC_barriert(L, hvalue(o), L->top-1); -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - } - -@@ -785,7 +791,7 @@ LUA_API int lua_setmetatable (lua_State - break; - } - } -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - return 1; - } -@@ -814,7 +820,7 @@ LUA_API int lua_setfenv (lua_State *L, i - break; - } - if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - return res; - } -@@ -1040,8 +1046,9 @@ LUA_API int lua_next (lua_State *L, int - if (more) { - api_incr_top(L); - } -- else /* no more elements */ -- L->top -= 1; /* remove key */ -+ else { /* no more elements */ -+ setlvmtop(L, L->top - 1); /* remove key */ -+ } - lua_unlock(L); - return more; - } -@@ -1053,7 +1060,7 @@ LUA_API void lua_concat (lua_State *L, i - if (n >= 2) { - luaC_checkGC(L); - luaV_concat(L, n, cast_int(L->top - L->base) - 1); -- L->top -= (n-1); -+ setlvmtop(L, L->top - (n-1)); - } - else if (n == 0) { /* push empty string */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); -@@ -1139,6 +1146,7 @@ LUA_API const char *lua_setupvalue (lua_ - if (name) { - L->top--; - setobj(L, val, L->top); -+ setnilvalue(L, L->top); - luaC_barrier(L, clvalue(fi), L->top); - } - lua_unlock(L); -@@ -1160,7 +1168,7 @@ LUA_API const char *lua_setupvalue (lua_ - int lua_pushvalue_as_number (lua_State *L, int idx) - { - const TValue *o = index2adr(L, idx); -- TValue tmp; -+ TValue tmp = tvinit(); - lua_Integer i; - if (ttisnumber(o)) { - if ( (!ttisint(o)) && tt_integer_valued(o,&i)) { ---- a/src/lcode.c -+++ b/src/lcode.c -@@ -23,6 +23,7 @@ - #include "lparser.h" - #include "ltable.h" - #include "lnum.h" -+#include "lvm.h" - - - #define hasjumps(e) ((e)->t != (e)->f) -@@ -248,7 +249,7 @@ static int addk (FuncState *fs, TValue * - setivalue(idx, fs->nk); - luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, - MAXARG_Bx, "constant table overflow"); -- while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); -+ while (oldsize < f->sizek) setnilvalue(L, &f->k[oldsize++]); - setobj(L, &f->k[fs->nk], v); - luaC_barrier(L, f, v); - return fs->nk++; -@@ -257,21 +258,24 @@ static int addk (FuncState *fs, TValue * - - - int luaK_stringK (FuncState *fs, TString *s) { -- TValue o; -+ TValue o = tvinit(); - setsvalue(fs->L, &o, s); -+ luaV_unref(fs->L, &o); - return addk(fs, &o, &o); - } - - - int luaK_numberK (FuncState *fs, lua_Number r) { -- TValue o; -+ lua_State *L = fs->L; -+ TValue o = tvinit(); - setnvalue(&o, r); - return addk(fs, &o, &o); - } - - - int luaK_integerK (FuncState *fs, lua_Integer r) { -- TValue o; -+ lua_State *L = fs->L; -+ TValue o = tvinit(); - setivalue(&o, r); - return addk(fs, &o, &o); - } -@@ -279,22 +283,24 @@ int luaK_integerK (FuncState *fs, lua_In - - #ifdef LNUM_COMPLEX - static int luaK_imagK (FuncState *fs, lua_Number r) { -- TValue o; -+ lua_State *L = fs->L; -+ TValue o = tvinit(); - setnvalue_complex(&o, r*I); - return addk(fs, &o, &o); - } - #endif - - static int boolK (FuncState *fs, int b) { -- TValue o; -+ lua_State *L = fs->L; -+ TValue o = tvinit(); - setbvalue(&o, b); - return addk(fs, &o, &o); - } - - - static int nilK (FuncState *fs) { -- TValue k, v; -- setnilvalue(&v); -+ TValue k = tvinit(), v = tvinit(); -+ setnilvalue(fs->L, &v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->L, &k, fs->h); - return addk(fs, &k, &v); ---- a/src/ldebug.c -+++ b/src/ldebug.c -@@ -142,6 +142,7 @@ LUA_API const char *lua_setlocal (lua_St - if (name) - setobjs2s(L, ci->base + (n - 1), L->top - 1); - L->top--; /* pop value */ -+ setnilvalue(L, L->top); - lua_unlock(L); - return name; - } -@@ -176,7 +177,7 @@ static void info_tailcall (lua_Debug *ar - - static void collectvalidlines (lua_State *L, Closure *f) { - if (f == NULL || f->c.isC) { -- setnilvalue(L->top); -+ setnilvalue(L, L->top); - } - else { - Table *t = luaH_new(L, 0, 0); -@@ -248,7 +249,7 @@ LUA_API int lua_getinfo (lua_State *L, c - } - status = auxgetinfo(L, what, ar, f, ci); - if (strchr(what, 'f')) { -- if (f == NULL) setnilvalue(L->top); -+ if (f == NULL) setnilvalue(L, L->top); - else setclvalue(L, L->top, f); - incr_top(L); - } -@@ -586,7 +587,7 @@ void luaG_concaterror (lua_State *L, Stk - - - void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { -- TValue temp; -+ TValue temp = tvinit(); - if (luaV_tonumber(p1, &temp) == NULL) - p2 = p1; /* first operand is wrong */ - luaG_typeerror(L, p2, "perform arithmetic on"); ---- a/src/ldo.c -+++ b/src/ldo.c -@@ -211,7 +211,7 @@ static StkId adjust_varargs (lua_State * - Table *htab = NULL; - StkId base, fixed; - for (; actual < nfixargs; ++actual) -- setnilvalue(L->top++); -+ setnilvalue(L, L->top++); - #if defined(LUA_COMPAT_VARARG) - if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ - int nvar = actual - nfixargs; /* number of extra arguments */ -@@ -229,7 +229,7 @@ static StkId adjust_varargs (lua_State * - base = L->top; /* final position of first argument */ - for (i=0; itop++, fixed+i); -- setnilvalue(fixed+i); -+ setnilvalue(L, fixed+i); - } - /* add `arg' parameter */ - if (htab) { -@@ -294,7 +294,7 @@ int luaD_precall (lua_State *L, StkId fu - ci->tailcalls = 0; - ci->nresults = nresults; - for (st = L->top; st < ci->top; st++) -- setnilvalue(st); -+ setnilvalue(L, st); - L->top = ci->top; - if (L->hookmask & LUA_MASKCALL) { - L->savedpc++; /* hooks assume 'pc' is already incremented */ -@@ -354,8 +354,8 @@ int luaD_poscall (lua_State *L, StkId fi - for (i = wanted; i != 0 && firstResult < L->top; i--) - setobjs2s(L, res++, firstResult++); - while (i-- > 0) -- setnilvalue(res++); -- L->top = res; -+ setnilvalue(L, res++); -+ setlvmtop(L, res); - return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ - } - -@@ -463,8 +463,12 @@ int luaD_pcall (lua_State *L, Pfunc func - status = luaD_rawrunprotected(L, func, u); - if (status != 0) { /* an error occurred? */ - StkId oldtop = restorestack(L, old_top); -+ StkId curtop = L->top; -+ int i; - luaF_close(L, oldtop); /* close eventual pending closures */ - luaD_seterrorobj(L, status, oldtop); -+ for (i = (curtop - L->top); i-- > 0;) -+ setnilvalue(L, L->top + i); - L->nCcalls = oldnCcalls; - L->ci = restoreci(L, old_ci); - L->base = L->ci->base; ---- a/src/lfunc.c -+++ b/src/lfunc.c -@@ -17,7 +17,7 @@ - #include "lmem.h" - #include "lobject.h" - #include "lstate.h" -- -+#include "lvm.h" - - - Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { -@@ -45,7 +45,7 @@ UpVal *luaF_newupval (lua_State *L) { - UpVal *uv = luaM_new(L, UpVal); - luaC_link(L, obj2gco(uv), LUA_TUPVAL); - uv->v = &uv->u.value; -- setnilvalue(uv->v); -+ setnilvalue(L, uv->v); - return uv; - } - -@@ -67,8 +67,14 @@ UpVal *luaF_findupval (lua_State *L, Stk - uv = luaM_new(L, UpVal); /* not found: create a new one */ - uv->tt = LUA_TUPVAL; - uv->marked = luaC_white(g); -- uv->v = level; /* current value lives in the stack */ -+ uv->v = luaV_ref(level); /* current value lives in the stack */ - uv->next = *pp; /* chain it in the proper position */ -+ if (uv->next) { -+ uv->prev = uv->next->gch.prev; -+ uv->next->gch.prev = (GCObject *)uv; -+ } else { -+ uv->prev = NULL; -+ } - *pp = obj2gco(uv); - uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ - uv->u.l.next = g->uvhead.u.l.next; ---- a/src/lgc.c -+++ b/src/lgc.c -@@ -21,6 +21,7 @@ - #include "lstring.h" - #include "ltable.h" - #include "ltm.h" -+#include "lvm.h" - - - #define GCSTEPSIZE 1024u -@@ -265,7 +266,7 @@ static void traversestack (global_State - for (o = l->stack; o < l->top; o++) - markvalue(g, o); - for (; o <= lim; o++) -- setnilvalue(o); -+ setnilvalue(l, o); - checkstacksizes(l, lim); - } - -@@ -348,7 +349,7 @@ static int iscleared (const TValue *o, i - /* - ** clear collected entries from weaktables - */ --static void cleartable (GCObject *l) { -+static void cleartable (lua_State *L, GCObject *l) { - while (l) { - Table *h = gco2h(l); - int i = h->sizearray; -@@ -358,7 +359,7 @@ static void cleartable (GCObject *l) { - while (i--) { - TValue *o = &h->array[i]; - if (iscleared(o, 0)) /* value was collected? */ -- setnilvalue(o); /* remove value */ -+ setnilvalue(L, o); /* remove value */ - } - } - i = sizenode(h); -@@ -366,7 +367,7 @@ static void cleartable (GCObject *l) { - Node *n = gnode(h, i); - if (!ttisnil(gval(n)) && /* non-empty entry? */ - (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { -- setnilvalue(gval(n)); /* remove value ... */ -+ setnilvalue(L, gval(n)); /* remove value ... */ - removeentry(n); /* remove entry from table */ - } - } -@@ -375,7 +376,7 @@ static void cleartable (GCObject *l) { - } - - --static void freeobj (lua_State *L, GCObject *o) { -+void luaC_freeobj (lua_State *L, GCObject *o) { - switch (o->gch.tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; - case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; -@@ -418,10 +419,12 @@ static GCObject **sweeplist (lua_State * - } - else { /* must erase `curr' */ - lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); -+ if (curr->gch.next) -+ curr->gch.next->gch.prev = curr->gch.prev; - *p = curr->gch.next; - if (curr == g->rootgc) /* is the first element of the list? */ - g->rootgc = curr->gch.next; /* adjust first */ -- freeobj(L, curr); -+ luaC_freeobj(L, curr); - } - } - return p; -@@ -543,7 +546,7 @@ static void atomic (lua_State *L) { - udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ - marktmu(g); /* mark `preserved' userdata */ - udsize += propagateall(g); /* remark, to propagate `preserveness' */ -- cleartable(g->weak); /* remove collected objects from weak tables */ -+ cleartable(L, g->weak); /* remove collected objects from weak tables */ - /* flip current white */ - g->currentwhite = cast_byte(otherwhite(g)); - g->sweepstrgc = 0; -@@ -685,8 +688,11 @@ void luaC_barrierback (lua_State *L, Tab - - void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { - global_State *g = G(L); -+ o->gch.prev = (GCObject*)&g->rootgc; - o->gch.next = g->rootgc; - g->rootgc = o; -+ if (o->gch.next) -+ o->gch.next->gch.prev = o; - o->gch.marked = luaC_white(g); - o->gch.tt = tt; - } ---- a/src/lgc.h -+++ b/src/lgc.h -@@ -105,6 +105,6 @@ LUAI_FUNC void luaC_link (lua_State *L, - LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); - LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); - LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); -- -+LUAI_FUNC void luaC_freeobj (lua_State *L, GCObject *o); - - #endif ---- a/src/lmem.c -+++ b/src/lmem.c -@@ -6,6 +6,7 @@ - - - #include -+#include - - #define lmem_c - #define LUA_CORE -@@ -80,6 +81,8 @@ void *luaM_realloc_ (lua_State *L, void - if (block == NULL && nsize > 0) - luaD_throw(L, LUA_ERRMEM); - lua_assert((nsize == 0) == (block == NULL)); -+ if (nsize > osize) -+ memset((char *)block + osize, 0, nsize - osize); - g->totalbytes = (g->totalbytes - osize) + nsize; - return block; - } ---- a/src/lobject.h -+++ b/src/lobject.h -@@ -44,7 +44,7 @@ typedef union GCObject GCObject; - ** Common Header for all collectable objects (in macro form, to be - ** included in other objects) - */ --#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked -+#define CommonHeader GCObject *next; GCObject *prev; lu_byte tt; lu_byte marked - - - /* -@@ -83,6 +83,7 @@ typedef struct lua_TValue { - TValuefields; - } TValue; - -+#define tvinit() { .value.b = 0, .tt = 0 } - - /* Macros to test type */ - #define ttisnil(o) (ttype(o) == LUA_TNIL) -@@ -145,15 +146,15 @@ typedef struct lua_TValue { - - - /* Macros to set values */ --#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) -+#define setnilvalue(L, obj) (luaV_unref(L, (obj))->tt=LUA_TNIL) - - /* Must not have side effects, 'x' may be expression. - */ - #define setivalue(obj,x) \ -- { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; } -+ { TValue *i_o=luaV_unref(L, (obj)); i_o->value.i=(x); i_o->tt=LUA_TINT; } - - # define setnvalue(obj,x) \ -- { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; } -+ { TValue *i_o=luaV_unref(L, (obj)); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; } - - /* Note: Complex always has "inline", both are C99. - */ -@@ -170,45 +171,45 @@ typedef struct lua_TValue { - - - #define setpvalue(obj,x) \ -- { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } -+ { TValue *i_o=luaV_unref(L, (obj)); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } - - #define setbvalue(obj,x) \ -- { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } -+ { TValue *i_o=luaV_unref(L, (obj)); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } - - #define setsvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ -+ { TValue *i_o=(obj); TString *val=(x); luaS_ref(val); luaV_unref(L, obj); \ -+ i_o->value.gc=cast(GCObject *, (val)); i_o->tt=LUA_TSTRING; \ - checkliveness(G(L),i_o); } - - #define setuvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ - checkliveness(G(L),i_o); } - - #define setthvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ - checkliveness(G(L),i_o); } - - #define setclvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ - checkliveness(G(L),i_o); } - - #define sethvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ - checkliveness(G(L),i_o); } - - #define setptvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ - checkliveness(G(L),i_o); } - - #define setobj(L,obj1,obj2) \ -- { const TValue *o2=(obj2); TValue *o1=(obj1); \ -+ do { const TValue *o2=luaV_ref((TValue *)(obj2)); TValue *o1=luaV_unref(L, (obj1)); \ - o1->value = o2->value; o1->tt=o2->tt; \ -- checkliveness(G(L),o1); } -+ checkliveness(G(L),o1); } while(0) - - - /* -@@ -253,6 +254,7 @@ typedef union TString { - lu_byte reserved; - unsigned int hash; - size_t len; -+ int refcount; - } tsv; - } TString; - -@@ -409,6 +411,7 @@ typedef struct Table { - #define twoto(x) (1<<(x)) - #define sizenode(t) (twoto((t)->lsizenode)) - -+#include "lstring.h" - - #define luaO_nilobject (&luaO_nilobject_) - ---- a/src/lparser.c -+++ b/src/lparser.c -@@ -24,6 +24,7 @@ - #include "lstate.h" - #include "lstring.h" - #include "ltable.h" -+#include "lvm.h" - - - -@@ -146,7 +147,7 @@ static int registerlocalvar (LexState *l - luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, - LocVar, SHRT_MAX, "too many local variables"); - while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; -- f->locvars[fs->nlocvars].varname = varname; -+ f->locvars[fs->nlocvars].varname = luaS_ref(varname); - luaC_objbarrier(ls->L, f, varname); - return fs->nlocvars++; - } -@@ -194,7 +195,7 @@ static int indexupvalue (FuncState *fs, - luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, - TString *, MAX_INT, ""); - while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; -- f->upvalues[f->nups] = name; -+ f->upvalues[f->nups] = luaS_ref(name); - luaC_objbarrier(fs->L, f, name); - lua_assert(v->k == VLOCAL || v->k == VUPVAL); - fs->upvalues[f->nups].k = cast_byte(v->k); -@@ -341,7 +342,7 @@ static void open_func (LexState *ls, Fun - fs->nlocvars = 0; - fs->nactvar = 0; - fs->bl = NULL; -- f->source = ls->source; -+ f->source = luaS_ref(ls->source); - f->maxstacksize = 2; /* registers 0/1 are always valid */ - fs->h = luaH_new(L, 0, 0); - /* anchor table of constants and prototype (to avoid being collected) */ ---- a/src/lstate.c -+++ b/src/lstate.c -@@ -22,6 +22,7 @@ - #include "lstring.h" - #include "ltable.h" - #include "ltm.h" -+#include "lvm.h" - - - #define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) -@@ -52,7 +53,7 @@ static void stack_init (lua_State *L1, l - L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; - /* initialize first ci */ - L1->ci->func = L1->top; -- setnilvalue(L1->top++); /* `function' entry for this `ci' */ -+ setnilvalue(L1, L1->top++); /* `function' entry for this `ci' */ - L1->base = L1->ci->base = L1->top; - L1->ci->top = L1->top + LUA_MINSTACK; - } -@@ -98,7 +99,7 @@ static void preinit_state (lua_State *L, - L->base_ci = L->ci = NULL; - L->savedpc = NULL; - L->errfunc = 0; -- setnilvalue(gt(L)); -+ setnilvalue(L, gt(L)); - } - - -@@ -163,7 +164,7 @@ LUA_API lua_State *lua_newstate (lua_All - g->strt.size = 0; - g->strt.nuse = 0; - g->strt.hash = NULL; -- setnilvalue(registry(L)); -+ setnilvalue(L, registry(L)); - luaZ_initbuffer(L, &g->buff); - g->panic = NULL; - g->gcstate = GCSpause; ---- a/src/lstring.c -+++ b/src/lstring.c -@@ -37,6 +37,9 @@ void luaS_resize (lua_State *L, int news - int h1 = lmod(h, newsize); /* new position */ - lua_assert(cast_int(h%newsize) == lmod(h, newsize)); - p->gch.next = newhash[h1]; /* chain it */ -+ if (p->gch.next) -+ p->gch.next->gch.prev = p; -+ p->gch.prev = NULL; - newhash[h1] = p; - p = next; - } -@@ -59,11 +62,15 @@ static TString *newlstr (lua_State *L, c - ts->tsv.marked = luaC_white(G(L)); - ts->tsv.tt = LUA_TSTRING; - ts->tsv.reserved = 0; -+ ts->tsv.refcount = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ - tb = &G(L)->strt; - h = lmod(h, tb->size); - ts->tsv.next = tb->hash[h]; /* chain new entry */ -+ if (ts->tsv.next) -+ ts->tsv.next->gch.prev = (GCObject *)ts; -+ ts->tsv.prev = NULL; - tb->hash[h] = obj2gco(ts); - tb->nuse++; - if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) -@@ -109,3 +116,29 @@ Udata *luaS_newudata (lua_State *L, size - return u; - } - -+void luaS_unref(lua_State *L, TString *ts) { -+ if (!L || !ts) -+ return; -+ if (testbit(ts->tsv.marked, FIXEDBIT)) -+ return; -+ ts->tsv.refcount--; -+ if (ts->tsv.refcount < 0) { -+ fprintf(stderr, "REFCOUNT BUG, COUNT=%d, str=%s, len=%d\n", ts->tsv.refcount, (char *) (ts + 1), (int) ts->tsv.len); -+ } else if (ts->tsv.refcount) -+ return; -+ -+ if (ts->tsv.prev) { -+ ts->tsv.prev->gch.next = ts->tsv.next; -+ } else { -+ unsigned int idx = lmod(ts->tsv.hash, G(L)->strt.size); -+ lua_assert(G(L)->strt.hash[index] == (GCObject*)ts); -+ G(L)->strt.hash[idx] = ts->tsv.next; -+ } -+ -+ if (ts->tsv.next) -+ ts->tsv.next->gch.prev = ts->tsv.prev; -+ -+ luaC_freeobj(L, (GCObject *) ts); -+} -+ -+ ---- a/src/lstring.h -+++ b/src/lstring.h -@@ -7,7 +7,7 @@ - #ifndef lstring_h - #define lstring_h - -- -+#include - #include "lgc.h" - #include "lobject.h" - #include "lstate.h" -@@ -23,6 +23,12 @@ - - #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) - -+static inline TString *luaS_ref(TString *ts) { -+ ts->tsv.refcount++; -+ return ts; -+} -+ -+LUA_API void luaS_unref(lua_State *L, TString *ts); - LUAI_FUNC void luaS_resize (lua_State *L, int newsize); - LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); - LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l); ---- a/src/ltable.c -+++ b/src/ltable.c -@@ -34,6 +34,7 @@ - #include "lstate.h" - #include "ltable.h" - #include "lnum.h" -+#include "lvm.h" - - - /* -@@ -278,7 +279,7 @@ static void setarrayvector (lua_State *L - int i; - luaM_reallocvector(L, t->array, t->sizearray, size, TValue); - for (i=t->sizearray; iarray[i]); -+ setnilvalue(L, &t->array[i]); - t->sizearray = size; - } - -@@ -299,8 +300,8 @@ static void setnodevector (lua_State *L, - for (i=0; ilsizenode = cast_byte(lsize); -@@ -427,9 +428,11 @@ static TValue *newkey (lua_State *L, Tab - othern = gnext(othern); /* find previous */ - } - gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ -+ luaV_ref((TValue *) gkey(mp)); -+ luaV_ref(gval(mp)); - *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - gnext(mp) = NULL; /* now `mp' is free */ -- setnilvalue(gval(mp)); -+ setnilvalue(L, gval(mp)); - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ -@@ -438,6 +441,7 @@ static TValue *newkey (lua_State *L, Tab - mp = n; - } - } -+ luaV_ref((TValue *) key); - gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; - luaC_barriert(L, t, key); - lua_assert(ttisnil(gval(mp))); -@@ -530,7 +534,7 @@ TValue *luaH_setint (lua_State *L, Table - if (p != luaO_nilobject) - return cast(TValue *, p); - else { -- TValue k; -+ TValue k = tvinit(); - setivalue(&k, key); - return newkey(L, t, &k); - } -@@ -542,7 +546,7 @@ TValue *luaH_setstr (lua_State *L, Table - if (p != luaO_nilobject) - return cast(TValue *, p); - else { -- TValue k; -+ TValue k = tvinit(); - setsvalue(L, &k, key); - return newkey(L, t, &k); - } ---- a/src/luac.c -+++ b/src/luac.c -@@ -20,8 +20,9 @@ - #include "lmem.h" - #include "lobject.h" - #include "lopcodes.h" --#include "lstring.h" - #include "lundump.h" -+#include "lvm.h" -+#include "lstring.h" - - #define PROGNAME "luac" /* default program name */ - #define OUTPUT PROGNAME ".out" /* default output file */ ---- a/src/lundump.c -+++ b/src/lundump.c -@@ -19,6 +19,7 @@ - #include "lstring.h" - #include "lundump.h" - #include "lzio.h" -+#include "lvm.h" - - typedef struct { - lua_State* L; -@@ -133,7 +134,7 @@ static TString* LoadString(LoadState* S) - { - char* s=luaZ_openspace(S->L,S->b,size); - LoadBlock(S,s,size); -- return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ -+ return luaS_ref(luaS_newlstr(S->L,s,size-1)); /* remove trailing '\0' */ - } - } - -@@ -149,11 +150,12 @@ static Proto* LoadFunction(LoadState* S, - - static void LoadConstants(LoadState* S, Proto* f) - { -+ lua_State *L = S->L; - int i,n; - n=LoadInt(S); - f->k=luaM_newvector(S->L,n,TValue); - f->sizek=n; -- for (i=0; ik[i]); -+ for (i=0; ik[i]); - for (i=0; ik[i]; -@@ -161,7 +163,7 @@ static void LoadConstants(LoadState* S, - switch (t) - { - case LUA_TNIL: -- setnilvalue(o); -+ setnilvalue(L, o); - break; - case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)!=0); -@@ -229,6 +231,7 @@ static Proto* LoadFunction(LoadState* S, - LoadDebug(S,f); - IF (!luaG_checkcode(f), "bad code"); - S->L->top--; -+ setnilvalue(S->L, S->L->top); - S->L->nCcalls--; - return f; - } ---- a/src/lvm.c -+++ b/src/lvm.c -@@ -39,6 +39,7 @@ - * If 'obj' is a string, it is tried to be interpreted as a number. - */ - const TValue *luaV_tonumber ( const TValue *obj, TValue *n) { -+ lua_State *L = NULL; /* FIXME */ - lua_Number d; - lua_Integer i; - -@@ -384,6 +385,7 @@ void luaV_concat (lua_State *L, int tota - size_t l = tsvalue(top-i)->len; - memcpy(buffer+tl, svalue(top-i), l); - tl += l; -+ setnilvalue(L, top - i); - } - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); - } -@@ -420,7 +422,7 @@ void luaV_concat (lua_State *L, int tota - */ - static void Arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op) { -- TValue tempb, tempc; -+ TValue tempb = tvinit(), tempc = tvinit(); - const TValue *b, *c; - lua_Number nb,nc; - -@@ -663,7 +665,7 @@ void luaV_execute (lua_State *L, int nex - OPCODE_TARGET(LOADNIL) { - TValue *rb = RB(i); - do { -- setnilvalue(rb--); -+ setnilvalue(L, rb--); - } while (rb >= ra); - continue; - } -@@ -673,7 +675,7 @@ void luaV_execute (lua_State *L, int nex - continue; - } - OPCODE_TARGET(GETGLOBAL) { -- TValue g; -+ TValue g = tvinit(); - TValue *rb = KBx(i); - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(rb)); -@@ -685,7 +687,7 @@ void luaV_execute (lua_State *L, int nex - continue; - } - OPCODE_TARGET(SETGLOBAL) { -- TValue g; -+ TValue g = tvinit(); - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(KBx(i))); - Protect(luaV_settable(L, &g, KBx(i), ra)); -@@ -895,7 +897,7 @@ void luaV_execute (lua_State *L, int nex - if (--nexeccalls == 0) /* was previous function running `here'? */ - return; /* no: return */ - else { /* yes: continue its execution */ -- if (b) L->top = L->ci->top; -+ if (b) setlvmtop(L, L->ci->top); - lua_assert(isLua(L->ci)); - lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); - goto reentry; -@@ -986,6 +988,7 @@ void luaV_execute (lua_State *L, int nex - for (; n > 0; n--) { - TValue *val = ra+n; - setobj2t(L, luaH_setint(L, h, last--), val); -+ setnilvalue(L, val); - luaC_barriert(L, h, val); - } - continue; -@@ -1030,7 +1033,7 @@ void luaV_execute (lua_State *L, int nex - setobjs2s(L, ra + j, ci->base - n + j); - } - else { -- setnilvalue(ra + j); -+ setnilvalue(L, ra + j); - } - } - continue; ---- a/src/lvm.h -+++ b/src/lvm.h -@@ -11,6 +11,7 @@ - #include "ldo.h" - #include "lobject.h" - #include "ltm.h" -+#include "lstring.h" - - - #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) -@@ -19,6 +20,19 @@ - - #define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2)) - -+static inline TValue *luaV_ref(TValue *tv) -+{ -+ if (ttisstring(tv)) -+ luaS_ref(rawtsvalue(tv)); -+ return tv; -+} -+ -+static inline TValue *luaV_unref(lua_State *L, TValue *tv) -+{ -+ if (ttisstring(tv)) -+ luaS_unref(L, rawtsvalue(tv)); -+ return tv; -+} - - LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); - LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); ---- a/src/llex.c -+++ b/src/llex.c -@@ -23,6 +23,7 @@ - #include "ltable.h" - #include "lzio.h" - #include "lnum.h" -+#include "lvm.h" - - - -@@ -69,7 +70,7 @@ static void save (LexState *ls, int c) { - void luaX_init (lua_State *L) { - int i; - for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ -@@ -125,7 +126,7 @@ void luaX_syntaxerror (LexState *ls, con - - TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - lua_State *L = ls->L; -- TString *ts = luaS_newlstr(L, str, l); -+ TString *ts = luaS_ref(luaS_newlstr(L, str, l)); - TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ - if (ttisnil(o)) - setbvalue(o, 1); /* make sure `str' will not be collected */ -@@ -152,7 +153,7 @@ void luaX_setinput (lua_State *L, LexSta - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; -- ls->source = source; -+ ls->source = luaS_ref(source); - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ - next(ls); /* read first char */ - } ---- a/src/lstate.h -+++ b/src/lstate.h -@@ -144,6 +144,13 @@ union GCObject { - struct lua_State th; /* thread */ - }; - -+#define setlvmtop(L, val) do { \ -+ int __i; \ -+ for (__i = L->top - val; __i-- > 0;) \ -+ setnilvalue(L, val + __i); \ -+ L->top = val; \ -+} while (0) -+ - - /* macros to convert a GCObject into a specific value */ - #define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) From 1371c8b7125b04cabc1e368a835a4036ba979023 Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 05:36:14 +0000 Subject: [PATCH 22/45] mac80211: add missing config file for the rt2x00 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20623 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/mac80211/Config.in.rt2x00 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 package/mac80211/Config.in.rt2x00 diff --git a/package/mac80211/Config.in.rt2x00 b/package/mac80211/Config.in.rt2x00 new file mode 100644 index 000000000..04b927b14 --- /dev/null +++ b/package/mac80211/Config.in.rt2x00 @@ -0,0 +1,15 @@ +# rt2x00 configuration + +config PACKAGE_RT2X00_LIB_DEBUGFS + bool "Enable rt2x00 debugfs support" + depends PACKAGE_kmod-rt2x00-lib && PACKAGE_MAC80211_DEBUGFS + ---help--- + Enable creation of debugfs files for the rt2x00 drivers. + These debugfs files support both reading and writing of the + most important register types of the rt2x00 hardware. + +config PACKAGE_RT2X00_DEBUG + bool "Enavle rt2x00 debug output" + depends PACKAGE_kmod-rt2x00-lib + ---help--- + Enable debugging output for all rt2x00 modules From c03509e141ab899e8abae31ca8e550fa84281b52 Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 08:40:20 +0000 Subject: [PATCH 23/45] ramips: add wifi device for the RT2880 as well git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20624 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../files/arch/mips/ralink/rt288x/devices.c | 26 +++++++++++++++++++ .../files/arch/mips/ralink/rt288x/devices.h | 1 + 2 files changed, 27 insertions(+) diff --git a/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.c b/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.c index 64ce0a9e6..086d9a999 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.c @@ -96,3 +96,29 @@ void __init rt288x_register_flash(unsigned int id, platform_device_register(pdev); rt288x_flash_instance++; } + +static struct resource rt288x_wifi_resources[] = { + { + .start = RT2880_WMAC_BASE, + .end = RT2880_WMAC_BASE + 0x3FFFF, + .flags = IORESOURCE_MEM, + }, { + .start = RT288X_CPU_IRQ_WNIC, + .end = RT288X_CPU_IRQ_WNIC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device rt288x_wifi_device = { + .name = "rt2800_wmac", + .resource = rt288x_wifi_resources, + .num_resources = ARRAY_SIZE(rt288x_wifi_resources), + .dev = { + .platform_data = NULL, + } +}; + +void __init rt288x_register_wifi(void) +{ + platform_device_register(&rt288x_wifi_device); +} diff --git a/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.h b/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.h index 4585d8b56..78daf3ad0 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.h +++ b/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.h @@ -16,5 +16,6 @@ struct physmap_flash_data; extern void rt288x_register_flash(unsigned int id, struct physmap_flash_data *pdata) __init; +void rt288x_register_wifi(void) __init; #endif /* __ASM_MACH_RT288X_PLATFORM_H */ From b7a96a32ea297bade1cecc67bd30991fc03bf471 Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 08:40:23 +0000 Subject: [PATCH 24/45] ramips: register wifi device for the RT2880 based boards git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20625 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/ramips/files/arch/mips/ralink/rt288x/mach-rt-n15.c | 2 ++ .../ramips/files/arch/mips/ralink/rt288x/mach-wzr-agl300nh.c | 1 + 2 files changed, 3 insertions(+) diff --git a/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-rt-n15.c b/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-rt-n15.c index d6bebf494..1a869afac 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-rt-n15.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-rt-n15.c @@ -125,6 +125,8 @@ static void __init rt_n15_init(void) rt_n15_gpio_buttons); platform_device_register(&rt_n15_rtl8366s_device); + + rt288x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_RT_N15, "RT-N15", "Asus RT-N15", rt_n15_init); diff --git a/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-wzr-agl300nh.c b/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-wzr-agl300nh.c index d37af91ab..2e5f46744 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-wzr-agl300nh.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-wzr-agl300nh.c @@ -75,6 +75,7 @@ static void __init wzr_agl300nh_init(void) rt288x_gpio_init(RT2880_GPIO_MODE_UART0); rt288x_register_flash(0, &wzr_agl300nh_flash_data); + rt288x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_WZR_AGL300NH, "WZR-AGL300NH", From 01ec7932a5d57c9ae5be0a47540fea550378745a Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 08:40:26 +0000 Subject: [PATCH 25/45] mac80211: fix a typo in rt2x00 config Fix a simple typo Signed-off-by: Luis Correia git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20626 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/mac80211/Config.in.rt2x00 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/mac80211/Config.in.rt2x00 b/package/mac80211/Config.in.rt2x00 index 04b927b14..f9855145b 100644 --- a/package/mac80211/Config.in.rt2x00 +++ b/package/mac80211/Config.in.rt2x00 @@ -9,7 +9,7 @@ config PACKAGE_RT2X00_LIB_DEBUGFS most important register types of the rt2x00 hardware. config PACKAGE_RT2X00_DEBUG - bool "Enavle rt2x00 debug output" + bool "Enable rt2x00 debug output" depends PACKAGE_kmod-rt2x00-lib ---help--- Enable debugging output for all rt2x00 modules From 67ab18e38a1aad888ddf7070eba01d7364e429e9 Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 08:40:28 +0000 Subject: [PATCH 26/45] ramips: annotate device register function prototypes with __init git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20627 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h index 7e2144c16..b731f8683 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h @@ -15,8 +15,8 @@ struct physmap_flash_data; extern void rt305x_register_flash(unsigned int id, struct physmap_flash_data *pdata) __init; -extern void rt305x_register_ethernet(void); -extern void rt305x_register_wifi(void); +extern void rt305x_register_ethernet(void) __init; +extern void rt305x_register_wifi(void) __init; #endif /* __RT305X_DEVICES_H */ From ecfeb0b0550da676566e799c60b1ea8a7aee8280 Mon Sep 17 00:00:00 2001 From: ralph Date: Wed, 31 Mar 2010 09:45:09 +0000 Subject: [PATCH 27/45] [uboot-lantiq] cleanup configuration handling git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20628 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/uboot-lantiq/Config.in | 55 ++++++++++++++++++---------------- package/uboot-lantiq/Makefile | 34 +++++++++++---------- 2 files changed, 47 insertions(+), 42 deletions(-) diff --git a/package/uboot-lantiq/Config.in b/package/uboot-lantiq/Config.in index 7544e711d..e2c156d88 100644 --- a/package/uboot-lantiq/Config.in +++ b/package/uboot-lantiq/Config.in @@ -1,32 +1,35 @@ -config UBOOT_CONFIG - string "configuration file" - default "easy50712_DDR166M" - help - The configuration reflects the settings for a dedicated board hardware. - Select for Danube evaluation board easy50712_DDR166M . - Select for AR9 evaluation board easy50812_DDR166M . - -config UBOOT_DDR_CONFIG - string "DDR configuration file" - default "danube_ref_ddr166.conf" - depends on UBOOT_RAMBOOT - help - The DDR configuration file should reflect the DDR memory device configuration . - It will be used to create a RAM boot image - Select for Danube evalution board danube_ref_ddr166.conf . - Select for AR9 evalution board easy50812.conf . +config UBOOT_TARGET + string "target" + default "easy50712_DDR166M" + depends on PACKAGE_uboot-lantiq + help + The configuration reflects the settings for a dedicated board hardware. + Select for Danube evaluation board easy50712_DDR166M . + Select for AR9 evaluation board easy50812_DDR166M . config UBOOT_RAMBOOT - bool "Enable RAM boot image" - help - Using the UART boot mode of the ROM code this image could be loaded to the RAM. - Executing the image in the RAM the functionality of the uboot image can be - tested first without touching the original flash. - Note: Be carefull, by saving the environment the flash will be modified. - The OWRT flash layout differs from the layout provided by Lantiq / Infineon. + bool "Enable RAM boot image" + depends on PACKAGE_uboot-lantiq + help + Using the UART boot mode of the ROM code this image could be loaded to the RAM. + While executing the image in the RAM the functionality of the uboot image can be + tested first without touching the original flash. + Note: Be carefull, by saving the environment the flash will be modified. + The OWRT flash layout differs from the layout provided by Lantiq / Infineon. -config IFXMIPS_UBOOT_A800 +config UBOOT_RAMBOOT_DDR_CONFIG + string "DDR configuration file" + default "easy50712_DDR166M.conf" + depends on UBOOT_RAMBOOT + help + The DDR configuration file should reflect the DDR memory device configuration . + It will be used to create a RAM boot image + Select for Danube evalution board easy50712_DDR166M.conf . + Select for AR9 evalution board easy50812.conf . + + +config UBOOT_A800 bool "add ARV452 Switch bringup hack" - depends on PACKAGE_uboot-ifxmips + depends on PACKAGE_uboot-lantiq help Say Y, if you have a arv452 board (wav-281, A800, ..) diff --git a/package/uboot-lantiq/Makefile b/package/uboot-lantiq/Makefile index 985f3638a..fc7c65371 100644 --- a/package/uboot-lantiq/Makefile +++ b/package/uboot-lantiq/Makefile @@ -20,6 +20,10 @@ PKG_TARGETS:=bin include $(INCLUDE_DIR)/package.mk +ifeq ($(DUMP),) + STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep '^CONFIG_UBOOT_' $(TOPDIR)/.config | md5s) +endif + define Package/uboot-lantiq SECTION:=boot CATEGORY:=Boot Loaders @@ -35,8 +39,8 @@ define Build/Prepare find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf endef -UBOOT_CONFIG:=$(call qstrip,$(CONFIG_UBOOT_CONFIG)) -UBOOT_DDR_CONFIG:=$(call qstrip,$(CONFIG_UBOOT_DDR_CONFIG)) +UBOOT_TARGET:=$(call qstrip,$(CONFIG_UBOOT_TARGET)) +UBOOT_RAMBOOT_DDR_CONFIG:=$(call qstrip,$(CONFIG_UBOOT_RAMBOOT_DDR_CONFIG)) UBOOT_MAKE_OPTS:= \ CROSS_COMPILE=$(TARGET_CROSS) \ @@ -44,9 +48,7 @@ UBOOT_MAKE_OPTS:= \ V=1 define Package/uboot-lantiq/config - menu "configuration" - source "$(SOURCE)/Config.in" - endmenu + source "$(SOURCE)/Config.in" endef define Build/Configure/Target @@ -57,9 +59,9 @@ define Build/Configure/Target endef define Build/Configure - $(call Build/Configure/Target,$(UBOOT_CONFIG)) + $(call Build/Configure/Target,$(UBOOT_TARGET)) ifeq ($(CONFIG_UBOOT_RAMBOOT),y) - $(call Build/Configure/Target,$(UBOOT_CONFIG)_ramboot) + $(call Build/Configure/Target,$(UBOOT_TARGET)_ramboot) endif endef @@ -71,24 +73,24 @@ define Build/Compile/Target endef define Build/Compile - $(call Build/Compile/Target,$(UBOOT_CONFIG)) + $(call Build/Compile/Target,$(UBOOT_TARGET)) ifeq ($(CONFIG_UBOOT_RAMBOOT),y) - $(call Build/Compile/Target,$(UBOOT_CONFIG)_ramboot) + $(call Build/Compile/Target,$(UBOOT_TARGET)_ramboot) endif endef define Package/uboot-lantiq/install - mkdir -p $(1)/$(UBOOT_CONFIG) + mkdir -p $(1)/$(UBOOT_TARGET) dd \ - if=$(PKG_BUILD_DIR)/$(UBOOT_CONFIG)/u-boot.bin \ - of=$(1)/$(UBOOT_CONFIG)/u-boot.bin \ + if=$(PKG_BUILD_DIR)/$(UBOOT_TARGET)/u-boot.bin \ + of=$(1)/$(UBOOT_TARGET)/u-boot.bin \ bs=64k conv=sync ifeq ($(CONFIG_UBOOT_RAMBOOT),y) - if [ -e $(UBOOT_DDR_CONFIG) ]; then \ + if [ -e $(UBOOT_RAMBOOT_DDR_CONFIG) ]; then \ perl ./gct \ - $(UBOOT_DDR_CONFIG) \ - $(PKG_BUILD_DIR)/$(UBOOT_CONFIG)_ramboot/u-boot.srec \ - $(1)/$(UBOOT_CONFIG)/u-boot.asc; \ + $(UBOOT_RAMBOOT_DDR_CONFIG) \ + $(PKG_BUILD_DIR)/$(UBOOT_TARGET)_ramboot/u-boot.srec \ + $(1)/$(UBOOT_TARGET)/u-boot.asc; \ fi endif endef From 511b7edbde61bc2de24daf6f888ac822f5fbcf6b Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 09:58:26 +0000 Subject: [PATCH 28/45] mac80211: Enable rt2x00 debug if CONFIG_PACKAGE_RT2X00_DEBUG is selected When CONFIG_PACKAGE_RT2X00_DEBUG is selected we should compile rt2x00 with the CONFIG_RT2X00_DEBUG flag set to enable debug output. Signed-off-by: Helmut Schaa git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20629 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/mac80211/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index 8cec1b8ba..d7fde6b25 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -618,6 +618,7 @@ BUILDFLAGS:= \ $(if $(CONFIG_ATH_USER_REGD),-DATH_USER_REGD=1) \ $(if $(CONFIG_PACKAGE_ATH9K_USE_MINSTREL),-DATH9K_USE_MINSTREL) \ $(if $(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS),-DCONFIG_RT2X00_LIB_DEBUGFS) \ + $(if $(CONFIG_PACKAGE_RT2X00_DEBUG),-DCONFIG_RT2X00_DEBUG) \ $(if $(NEED_RT2X00_LIB_HT),-DCONFIG_RT2X00_LIB_HT) \ $(if $(NEED_RT2X00_LIB_CRYPTO),-DCONFIG_RT2X00_LIB_CRYPTO) \ $(if $(NEED_RT2X00_LIB_FIRMWARE),-DCONFIG_RT2X00_LIB_FIRMWARE) \ From 439805b1a9a5a4f984ea87d2c27282497d14f704 Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 09:58:29 +0000 Subject: [PATCH 29/45] select LZMA compressed initramfs by default for ramips git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20630 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- Config.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Config.in b/Config.in index b04c65a71..2ff2862a2 100644 --- a/Config.in +++ b/Config.in @@ -25,6 +25,7 @@ menu "Target Images" depends TARGET_ROOTFS_INITRAMFS depends !LINUX_2_6_25 default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_ar71xx + default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_ramips default TARGET_INITRAMFS_COMPRESSION_NONE help Select ramdisk compression. From 517dcf8d8bed0b91c5b44c20d8b616912cbf5b4c Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 09:58:31 +0000 Subject: [PATCH 30/45] hostapd: enable CONFIG_IEEE80211N for the rt2800 driver as well git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20631 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/hostapd/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/hostapd/Makefile b/package/hostapd/Makefile index f4142f76d..38d91875e 100644 --- a/package/hostapd/Makefile +++ b/package/hostapd/Makefile @@ -54,7 +54,7 @@ DRIVER_MAKEOPTS= \ CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-mac80211) \ CONFIG_DRIVER_MADWIFI=$(CONFIG_PACKAGE_kmod-madwifi) \ CONFIG_DRIVER_HOSTAP=$(CONFIG_PACKAGE_kmod-hostap) \ - CONFIG_IEEE80211N=$(CONFIG_PACKAGE_kmod-ath9k) \ + CONFIG_IEEE80211N=$(if ($(CONFIG_PACKAGE_kmod-ath9k)$(CONFIG_PACKAGE_kmod-rt2800-lib)),y) \ CONFIG_IEEE80211W=$(CONFIG_PACKAGE_kmod-ath9k) ifneq ($(LOCAL_TYPE),hostapd) From e75dc44dcad2caa4cc88b0ad46ba9e51816f4558 Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 09:58:33 +0000 Subject: [PATCH 31/45] ramips: add wpad-mini to the default packages git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20632 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/ramips/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/Makefile b/target/linux/ramips/Makefile index 8eac4f6ef..23eb5280d 100644 --- a/target/linux/ramips/Makefile +++ b/target/linux/ramips/Makefile @@ -16,7 +16,7 @@ FEATURES:=squashfs broken LINUX_VERSION:=2.6.32.10 include $(INCLUDE_DIR)/target.mk -DEFAULT_PACKAGES+=kmod-leds-gpio +DEFAULT_PACKAGES+=kmod-leds-gpio wpad-mini define Target/Description Build firmware images for Ralink RT288x/RT305x based boards. From 5efdbb7a7b8fc8978ff1c05713dc00553d3327fc Mon Sep 17 00:00:00 2001 From: blogic Date: Wed, 31 Mar 2010 11:09:06 +0000 Subject: [PATCH 32/45] [ifxmips] uboot only builds with gcc 3.4.6 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20635 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/uboot-ifxmips/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/uboot-ifxmips/Makefile b/package/uboot-ifxmips/Makefile index 932c17f41..6b78c3d0a 100644 --- a/package/uboot-ifxmips/Makefile +++ b/package/uboot-ifxmips/Makefile @@ -23,7 +23,7 @@ include $(INCLUDE_DIR)/package.mk define Package/uboot-ifxmips SECTION:=boot CATEGORY:=Boot Loaders - DEPENDS:=@TARGET_ifxmips + DEPENDS:=@TARGET_ifxmips @BROKEN TITLE:=U-Boot for Infineon MIPS boards URL:=http://www.denx.de/wiki/U-Boot endef From c3d9a7dba18bfaeaeb683d51bce2a20845b7fbcb Mon Sep 17 00:00:00 2001 From: blogic Date: Wed, 31 Mar 2010 11:12:10 +0000 Subject: [PATCH 33/45] [ifxmips] fix licensing issues of ifxmips dsl driver git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20636 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/ifxmips-dsl-api/Config.in | 7 +++++++ package/ifxmips-dsl-api/Makefile | 19 ++++++++++++++++++- package/ifxmips-dsl-control/Makefile | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/package/ifxmips-dsl-api/Config.in b/package/ifxmips-dsl-api/Config.in index f27181e31..56177d168 100644 --- a/package/ifxmips-dsl-api/Config.in +++ b/package/ifxmips-dsl-api/Config.in @@ -17,6 +17,13 @@ config IFXMIPS_ANNEX_B endchoice +config IFXMIPS_DSL_FIRMWARE + bool "ifxmips-dsl firmware extractor" + default y + depends on PACKAGE_kmod-ifxmips-dsl-api + help + Say Y, if you need ifxmips-dsl to auto extract the firmware for you from the a800 firmware image + config IFXMIPS_DSL_DEBUG bool "ifxmips-dsl debugging" depends on PACKAGE_kmod-ifxmips-dsl-api diff --git a/package/ifxmips-dsl-api/Makefile b/package/ifxmips-dsl-api/Makefile index 3fc31eda4..b1952b5ed 100644 --- a/package/ifxmips-dsl-api/Makefile +++ b/package/ifxmips-dsl-api/Makefile @@ -34,7 +34,7 @@ define KernelPackage/ifxmips-dsl-api TITLE:=DSL CPE API driver URL:=http://www.infineon.com/ MAINTAINER:=Infineon Technologies AG / Lantiq / blogic@openwrt.org - DEPENDS:=@TARGET_ifxmips + DEPENDS:=@TARGET_ifxmips @BROKEN FILES:=$(PKG_BUILD_DIR)/src/mei/ifxmips_mei.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/src/drv_dsl_cpe_api.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/src/mei/ifxmips_atm.$(LINUX_KMOD_SUFFIX) @@ -57,6 +57,17 @@ define KernelPackage/ifxmips-dsl-api/config source "$(SOURCE)/Config.in" endef +ifeq ($(CONFIG_IFXMIPS_DSL_FIRMWARE),y) +FW_FILE:=arcor_A800_452CPW_FW_1.02.206(20081201).bin +define Download/firmware + URL:=http://www.arcor.de/hilfe/files/pdf/ + FILE=$(FW_FILE) + MD5SUM:=19d9af4e369287a0f0abaed415cdac10 +endef +$(eval $(call Download,firmware)) + +else + define Download/annex-a FILE:=$(FW_BASE_NAME)_a-$(FW_A_VER).tar.gz URL:=http://mirror2.openwrt.org/sources/ @@ -70,6 +81,7 @@ define Download/annex-b MD5SUM:=$(FW_B_MD5) endef $(eval $(call Download,annex-b)) +endif IFX_DSL_MAX_DEVICE=1 IFX_DSL_LINES_PER_DEVICE=1 @@ -145,7 +157,12 @@ endef define KernelPackage/ifxmips-dsl-api/install $(INSTALL_DIR) $(1)/lib/firmware/ +ifeq ($(CONFIG_IFXMIPS_DSL_FIRMWARE),y) + $(PLATFORM_DIR)/extract.sh $(DL_DIR) '$(FW_FILE)' + $(CP) $(DL_DIR)/dsl_$(if $(CONFIG_IFXMIPS_ANNEX_A),a,b).bin $(1)/lib/firmware/ModemHWE.bin +else $(CP) $(PKG_BUILD_DIR)/$(FW_BASE_NAME)_$(if $(CONFIG_IFXMIPS_ANNEX_A),a_$(FW_A_FILE_VER),b_$(FW_B_FILE_VER)).bin $(1)/lib/firmware/ModemHWE.bin +endif endef $(eval $(call KernelPackage,ifxmips-dsl-api)) diff --git a/package/ifxmips-dsl-control/Makefile b/package/ifxmips-dsl-control/Makefile index 035deada1..bd35d2f9c 100644 --- a/package/ifxmips-dsl-control/Makefile +++ b/package/ifxmips-dsl-control/Makefile @@ -24,7 +24,7 @@ define Package/ifxmips-dsl-control TITLE:=DSL CPE control application URL:=http://www.infineon.com/ MAINTAINER:=Infineon Technologies AG / Lantiq / blogic@openwrt.org - DEPENDS:=+kmod-ifxmips-dsl-api +libpthread + DEPENDS:=+kmod-ifxmips-dsl-api +libpthread @BROKEN endef define Package/ifxmips-dsl-control/description From 664dbf6de87a76c290a08d3b9eb71c49085ccf6c Mon Sep 17 00:00:00 2001 From: blogic Date: Wed, 31 Mar 2010 11:12:33 +0000 Subject: [PATCH 34/45] [ifxmips] adds voip support git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20637 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/ifx-tapi/Config.in | 71 +++ package/ifx-tapi/Makefile | 70 +++ .../ifx-tapi/patches/001-portability.patch | 26 + package/ifx-tapi/patches/100-ifxmips.patch | 108 ++++ package/ifx-tapidemo/Config.in | 36 ++ package/ifx-tapidemo/Makefile | 70 +++ package/ifx-tapidemo/files/bringup_tapidemo | 89 ++++ .../ifx-tapidemo/patches/100-ifxmips.patch | 78 +++ .../patches/110-no_echo_cancelation.patch | 12 + package/ifx-vmmc/Config.in | 49 ++ package/ifx-vmmc/Makefile | 151 ++++++ package/ifx-vmmc/files/vmmc.init | 25 + .../ifx-vmmc/patches/001-portability.patch | 26 + package/ifx-vmmc/patches/100-ifxmips.patch | 491 ++++++++++++++++++ package/ifxos/Makefile | 2 +- 15 files changed, 1303 insertions(+), 1 deletion(-) create mode 100644 package/ifx-tapi/Config.in create mode 100644 package/ifx-tapi/Makefile create mode 100644 package/ifx-tapi/patches/001-portability.patch create mode 100644 package/ifx-tapi/patches/100-ifxmips.patch create mode 100644 package/ifx-tapidemo/Config.in create mode 100644 package/ifx-tapidemo/Makefile create mode 100644 package/ifx-tapidemo/files/bringup_tapidemo create mode 100644 package/ifx-tapidemo/patches/100-ifxmips.patch create mode 100644 package/ifx-tapidemo/patches/110-no_echo_cancelation.patch create mode 100644 package/ifx-vmmc/Config.in create mode 100644 package/ifx-vmmc/Makefile create mode 100644 package/ifx-vmmc/files/vmmc.init create mode 100644 package/ifx-vmmc/patches/001-portability.patch create mode 100644 package/ifx-vmmc/patches/100-ifxmips.patch diff --git a/package/ifx-tapi/Config.in b/package/ifx-tapi/Config.in new file mode 100644 index 000000000..56defb3dd --- /dev/null +++ b/package/ifx-tapi/Config.in @@ -0,0 +1,71 @@ +config VOICE_CPE_TAPI_FAX + bool "fax relay and modem support" + default n + help + Option to enable fax/modem support in TAPI. + Note: Newer platforms as AR9 and VR9 support a T.38 fax relay stack + in FW while older platforms like Danube or VINETIC-CPE require a + separate SW stack executed as an application. + +config VOICE_CPE_TAPI_CID + bool "CID support" + default y + help + Option to enable Caller ID support. + +config VOICE_CPE_TAPI_LT_GR909 + bool "Linetesting GR-909 support" + default y + help + Option to enable linetesting GR-909. + +config VOICE_CPE_TAPI_DECT + bool "DECT encoding for COSIC modem" + default n + help + Option to enable DECT encoding for COSIC modem. + +config VOICE_CPE_TAPI_KPI + bool "KPI (Kernel Packet Interface)" + default y + help + Option to enable the generic kernel level packet interface + which allows accelerated packet transfer for various purposes. + The most important example is the QOS option, which allows + to redirect RTP packets directly into the IP stack. + Other options relying on KPI are DECT and HDLC. + +config VOICE_CPE_TAPI_QOS + bool "QOS for accelerated RTP packet handling" + default y + help + Option to enable an accelerated RTP packet transfer inside + the LINUX kernel space. This option requires the KPI2UDP + packet, which actually provides the OS specific hooks in + the IP stack. + +config VOICE_CPE_TAPI_STATISTICS + bool "TAPI statistics via /proc fs" + default y + help + Option to enable /proc fs statistics for packet counts etc. + +config VOICE_CPE_TAPI_METERING + bool "Metering (TTX) support" + default n + help + Option to enable metering (TTX) support. + +config VOICE_CPE_TAPI_HDLC + bool "PCM HDLC support, evaluation" + default n + help + Option to enable PCM HDLC framing inside the firmware, e.g. for + ISDN D-Channel access. + +config VOICE_CPE_TAPI_TRACES + bool "enable driver traces" + default y + help + enable driver traces with different trace levels to be + configured dynamically from the application or during insmod diff --git a/package/ifx-tapi/Makefile b/package/ifx-tapi/Makefile new file mode 100644 index 000000000..fe91ad015 --- /dev/null +++ b/package/ifx-tapi/Makefile @@ -0,0 +1,70 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# 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:=drv_tapi +PKG_VERSION:=3.11.0 +PKG_RELEASE:=1 + +PKG_SOURCE:=drv_tapi-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_MD5SUM:=1ffee83ce69f55915468c309d8ae2138 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ifx-tapi + SUBMENU:=Voice over IP + TITLE:=Lantiq TAPI subsystem + URL:=http://www.lantiq.com/ + MAINTAINER:=Lantiq + DEPENDS:=+kmod-ifxos @BROKEN + FILES:=$(PKG_BUILD_DIR)/src/drv_tapi.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,20,drv_tapi) +endef + +define KernelPackage/ifx-tapi/description + Voice Subsystem Telephony API High Level Driver +endef + +define KernelPackage/ifx-tapi/config + if PACKAGE_kmod-ifx-tapi + source "$(SOURCE)/Config.in" + endif +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \ + $(call autoconf_bool,CONFIG_IFX_DRV_TAPI_EVENT_LOGGER,el-debug) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_FAX,fax t38) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_CID,cid) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_DECT,dect) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_KPI,kpi) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_QOS,qos) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LT_GR909,lt) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_STATISTICS,statistics) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_METERING,metering) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_HDLC,hdlc) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_TRACES,trace) + +define Build/Configure + (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake) + $(call Build/Configure/Default) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/drv_tapi + $(CP) --dereference $(PKG_BUILD_DIR)/include/* $(1)/usr/include/drv_tapi + (cd $(1)/usr/include/drv_tapi && ln -s . include && ln -s ../ifxos/ifx_types.h .) +endef + +$(eval $(call KernelPackage,ifx-tapi)) diff --git a/package/ifx-tapi/patches/001-portability.patch b/package/ifx-tapi/patches/001-portability.patch new file mode 100644 index 000000000..807a64b12 --- /dev/null +++ b/package/ifx-tapi/patches/001-portability.patch @@ -0,0 +1,26 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -149,7 +149,7 @@ if KERNEL_2_6 + drv_tapi_OBJS = "$(subst .c,.o, $(drv_tapi_SOURCES))" + + drv_tapi.ko: $(drv_tapi_SOURCES) $(EXTRA_DIST) +- @echo -e "Making Linux 2.6.x kernel object" ++ @echo "Making Linux 2.6.x kernel object" + @for f in $(drv_tapi_SOURCES) ; do \ + if test ! -e $(PWD)/$$f; then \ + echo " LN $$f" ; \ +@@ -157,10 +157,10 @@ drv_tapi.ko: $(drv_tapi_SOURCES) $(EXTRA + ln -s @abs_srcdir@/$$f $(PWD)/$$f; \ + fi; \ + done; +- @echo -e "# drv_tapi: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild +- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild +- @echo -e "$(subst .ko,,$@)-y := $(drv_tapi_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild ++ @echo "# drv_tapi: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild ++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild ++ @echo "$(subst .ko,,$@)-y := $(drv_tapi_OBJS)" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: diff --git a/package/ifx-tapi/patches/100-ifxmips.patch b/package/ifx-tapi/patches/100-ifxmips.patch new file mode 100644 index 000000000..bce831c08 --- /dev/null +++ b/package/ifx-tapi/patches/100-ifxmips.patch @@ -0,0 +1,108 @@ +--- a/src/drv_tapi_linux.c ++++ b/src/drv_tapi_linux.c +@@ -544,7 +544,7 @@ static ssize_t ifx_tapi_write (struct fi + IFX_uint8_t *pData; + IFX_size_t buf_size; + #endif /* TAPI_PACKET */ +- IFX_ssize_t size = 0; ++ ssize_t size = 0; + + #ifdef TAPI_PACKET + if (pTapiDev->bInitialized == IFX_FALSE) +@@ -3600,7 +3600,11 @@ IFX_void_t TAPI_OS_ThreadKill(IFXOS_Thre + flag and released after the down() call. */ + lock_kernel(); + mb(); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + kill_proc(pThrCntrl->tid, SIGKILL, 1); ++#else ++ kill_pid(find_vpid(pThrCntrl->tid), SIGKILL, 1); ++#endif + /* release the big kernel lock */ + unlock_kernel(); + wait_for_completion (&pThrCntrl->thrCompletion); +--- a/src/drv_tapi_osmap.h ++++ b/src/drv_tapi_osmap.h +@@ -17,39 +17,6 @@ + */ + + #include "ifx_types.h" /* ifx type definitions */ +- +-#ifndef HAVE_IFX_ULONG_T +- #warning please update your ifx_types.h, using local definition of IFX_ulong_t +- /* unsigned long type - valid for 32bit systems only */ +- typedef unsigned long IFX_ulong_t; +- #define HAVE_IFX_ULONG_T +-#endif /* HAVE_IFX_ULONG_T */ +- +-#ifndef HAVE_IFX_LONG_T +- #warning please update your ifx_types.h, using local definition of IFX_long_t +- /* long type - valid for 32bit systems only */ +- typedef long IFX_long_t; +- #define HAVE_IFX_LONG_T +-#endif /* HAVE_IFX_LONG_T */ +- +-#ifndef HAVE_IFX_INTPTR_T +- #warning please update your ifx_types.h, using local definition of IFX_intptr_t +- typedef IFX_long_t IFX_intptr_t; +- #define HAVE_IFX_INTPTR_T +-#endif /* HAVE_IFX_INTPTR_T */ +- +-#ifndef HAVE_IFX_SIZE_T +- #warning please update your ifx_types.h, using local definition of IFX_size_t +- typedef IFX_ulong_t IFX_size_t; +- #define HAVE_IFX_SIZE_T +-#endif /* HAVE_IFX_SIZE_T */ +- +-#ifndef HAVE_IFX_SSIZE_T +- #warning please update your ifx_types.h, using local definition of IFX_ssize_t +- typedef IFX_long_t IFX_ssize_t; +- #define HAVE_IFX_SSIZE_T +-#endif /* HAVE_IFX_SSIZE_T */ +- + #include "ifxos_interrupt.h" + #include "ifxos_memory_alloc.h" + #include "ifxos_copy_user_space.h" +--- a/include/drv_tapi_ll_interface.h ++++ b/include/drv_tapi_ll_interface.h +@@ -40,13 +40,6 @@ + #include "ifxos_select.h" + #endif /* TAPI_PACKET */ + +-#ifndef HAVE_IFX_ULONG_T +- #warning please update your ifx_types.h, using local definition of IFX_ulong_t +- /* unsigned long type - valid for 32bit systems only */ +- typedef unsigned long IFX_ulong_t; +- #define HAVE_IFX_ULONG_T +-#endif /* HAVE_IFX_ULONG_T */ +- + /* ============================= */ + /* Local Macros Definitions */ + /* ============================= */ +--- a/src/lib/lib_bufferpool/lib_bufferpool.c ++++ b/src/lib/lib_bufferpool/lib_bufferpool.c +@@ -80,24 +80,6 @@ + #include + #endif /* LINUX */ + +- +-/* ============================= */ +-/* Extra type definitions */ +-/* ============================= */ +-#ifndef HAVE_IFX_ULONG_T +- #warning please update your ifx_types.h, using local definition of IFX_ulong_t +- /* unsigned long type - valid for 32bit systems only */ +- typedef unsigned long IFX_ulong_t; +- #define HAVE_IFX_ULONG_T +-#endif /* HAVE_IFX_ULONG_T */ +- +-#ifndef HAVE_IFX_UINTPTR_T +- #warning please update your ifx_types.h, using local definition of IFX_uintptr_t +- typedef IFX_ulong_t IFX_uintptr_t; +- #define HAVE_IFX_UINTPTR_T +-#endif /* HAVE_IFX_UINTPTR_T */ +- +- + /* ============================= */ + /* Local Macros & Definitions */ + /* ============================= */ diff --git a/package/ifx-tapidemo/Config.in b/package/ifx-tapidemo/Config.in new file mode 100644 index 000000000..32594ba9c --- /dev/null +++ b/package/ifx-tapidemo/Config.in @@ -0,0 +1,36 @@ +choice + prompt "board selection" + default VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3 if TARGET_ifxmips_platform_danube + default VOICE_CPE_TAPIDEMO_BOARD_EASY508xx if TARGET_ifxmips_platform_ar9 + default VOICE_CPE_TAPIDEMO_BOARD_EASY80910 if TARGET_ifxmips_platform_vr9 + default VOICE_CPE_TAPIDEMO_BOARD_EASY50812 + help + Select the target platform. + + config VOICE_CPE_TAPIDEMO_BOARD_EASY50712 + bool "Danube reference board" + + config VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3 + bool "Danube reference board V3" + + config VOICE_CPE_TAPIDEMO_BOARD_EASY508xx + bool "AR9/GR9 reference board" + + config VOICE_CPE_TAPIDEMO_BOARD_EASY80910 + bool "VR9 reference board" +endchoice + +config VOICE_CPE_TAPIDEMO_QOS + bool "enable QOS support" + default n + help + Option to enable the KPI2UDP RTP packet acceleration path + (highly recommended for VoIP). + +config VOICE_CPE_TAPIDEMO_FAX_T.38_FW + bool "enable T.38 fax relay" + depends on (TARGET_ifxmips_platform_ar9 || TARGET_ifxmips_platform_vr9) + default n + help + enable T.38 fax relay demo. + diff --git a/package/ifx-tapidemo/Makefile b/package/ifx-tapidemo/Makefile new file mode 100644 index 000000000..217d4641a --- /dev/null +++ b/package/ifx-tapidemo/Makefile @@ -0,0 +1,70 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id: $ + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=tapidemo +PKG_VERSION:=5.0.1.27 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_MD5SUM:=a38a7bf3242aad607f50f57b988bc87c + +include $(INCLUDE_DIR)/package.mk + +define Package/ifx-tapidemo + SECTION:=utils + CATEGORY:=Utilities + TITLE:=TAPIdemo application for Lantiq boards + URL:=http://www.lantiq.com/ + MAINTAINER:=Lantiq + DEPENDS:=+kmod-ifx-tapi +kmod-ifx-vmmc @BROKEN +endef + +define Package/ifx-tapidemo/description + Voice Access mini-PBX Demo Application +endef + +define Package/ifx-tapidemo/config + if PACKAGE_ifx-tapidemo + source "$(SOURCE)/Config.in" + endif +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --with-drvincl="$(STAGING_DIR)/usr/include" \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_QOS,qos) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPIDEMO_FAX_T,fax-t38) \ + --enable-trace \ + --enable-fs + +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY50712),y) + CONFIGURE_ARGS += --enable-boardname=EASY50712 +endif +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3),y) + CONFIGURE_ARGS += --enable-boardname=EASY50712_V3 +endif +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY508xx),y) + CONFIGURE_ARGS += --enable-boardname=EASY508XX +endif +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY80910),y) + CONFIGURE_ARGS += --enable-boardname=EASY508XX +endif + +define Package/ifx-tapidemo/install + $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/tapidemo $(1)/usr/sbin + $(INSTALL_BIN) ./files/bringup_tapidemo $(1)/etc/init.d/tapidemo +endef + +$(eval $(call BuildPackage,ifx-tapidemo)) diff --git a/package/ifx-tapidemo/files/bringup_tapidemo b/package/ifx-tapidemo/files/bringup_tapidemo new file mode 100644 index 000000000..e3abd5639 --- /dev/null +++ b/package/ifx-tapidemo/files/bringup_tapidemo @@ -0,0 +1,89 @@ +#!/bin/sh /etc/rc.common +# (C) 2008 openwrt.org + +START=96 + +[ ! -f /dev/vmmc10 ] && { + mknod /dev/vmmc10 c 122 10 + mknod /dev/vmmc11 c 122 11 + mknod /dev/vmmc12 c 122 12 + mknod /dev/vmmc13 c 122 13 + mknod /dev/vmmc14 c 122 14 + mknod /dev/vmmc15 c 122 15 + mknod /dev/vmmc16 c 122 16 + mknod /dev/vmmc17 c 122 17 + mknod /dev/vmmc18 c 122 18 +} + +TD_EXTRA_FLAGS_FXO= +TD_EXTRA_FLAGS_KPI2UDP= +TD_DOWNLOAD_PATH=/opt/lantiq/downloads/ +DEV_NODE_TERIDIAN=ter10 + + # Show help +help() +{ + echo "Usage:" + echo " - $0 WAN-IF-NAME - start TAPIDEMO without FXO support" + echo " - $0 WAN-IF-NAME fxo - start TAPIDEMO with FXO support." + echo " - $0 stop - stop TAPIDEMO" +} + +# Check if device node for Teridian exists +checkFxoSupport() +{ + if [ ! -e /dev/$DEV_NODE_TERIDIAN ];then + echo "FXO support is disabled. Can not find required driver's device node." + else + TD_EXTRA_FLAGS_FXO="-x" + fi +} + +# Check if module drv_kpi2udp is loaded +checkKpi2UdpSupport() +{ + tmp=`cat /proc/modules | grep 'drv_kpi2udp '` + if [ "$tmp" != "" ]; then + TD_EXTRA_FLAGS_KPI2UDP="-q" + fi +} + +start() +{ + TD_WANIF=$1 + + TD_WANIF_IP=`ifconfig $TD_WANIF | grep 'inet addr:' | cut -f2 -d: | cut -f1 -d' '` + if [ "$TD_WANIF_IP" = "" ]; then + echo "Error, getting IP address for network device $TD_WANIF failed." + exit 1 + fi + + if [ "$2" = "" ];then + # FXO support is disabled. + continue + elif [ "$2" = "fxo" ];then + checkFxoSupport + else + echo "Error, unknown second parameter." + help + exit 1 + fi + + checkKpi2UdpSupport + + if [ -r /etc/rc.conf ]; then + . /etc/rc.conf + fi + + TD_DEBUG_LEVEL=$tapiDebugLevel + if [ "$TD_DEBUG_LEVEL" = "" ]; then + TD_DEBUG_LEVEL=3 + fi + + /usr/sbin/tapidemo -d $TD_DEBUG_LEVEL $TD_EXTRA_FLAGS_FXO $TD_EXTRA_FLAGS_KPI2UDP -i $TD_WANIF_IP -l $TD_DOWNLOAD_PATH & +} + +stop() +{ + killall tapidemo > /dev/null 2> /dev/null +} diff --git a/package/ifx-tapidemo/patches/100-ifxmips.patch b/package/ifx-tapidemo/patches/100-ifxmips.patch new file mode 100644 index 000000000..43fa988ef --- /dev/null +++ b/package/ifx-tapidemo/patches/100-ifxmips.patch @@ -0,0 +1,78 @@ +--- a/src/board_easy50712.c Mon Mar 15 14:47:53 2010 +0300 ++++ b/src/board_easy50712.c Tue Mar 16 17:25:55 2010 +0300 +@@ -40,7 +40,9 @@ + #endif /* DUSLIC_FXO */ + #endif /* EASY50712_V3 */ + +-#include "asm/ifx/ifx_gpio.h" ++#ifdef FXO ++# include "asm/ifx/ifx_gpio.h" ++#endif + + /* ============================= */ + /* Defines */ +@@ -896,6 +898,7 @@ + /* Global function definition */ + /* ============================= */ + ++#ifdef FXO + /** + Set direction of GPIO pin to out which is used for set/clear reset. + +@@ -944,7 +947,7 @@ + return IFX_SUCCESS; + } + break; +- ++ + case GPIO_DUSLIC_EASY50510: + { + TRACE(TAPIDEMO, DBG_LEVEL_LOW, +@@ -982,8 +985,9 @@ + + return IFX_SUCCESS; + }; ++#endif + +- ++#ifdef FXO + /* + Set/Clear reset of device by using GPIO port. + +@@ -1086,7 +1090,9 @@ + /* usleep(100000); karol - workaround, */ + return ret; + } ++#endif + ++#ifdef EASY50510 + /** + Set PCM master mode. + +@@ -1178,15 +1184,16 @@ + + return ret; + } ++#endif + + /** + Register board. + + \param pBoard - pointer to board +- ++ + \return IFX_SUCCESS if successful, otherwise IFX_ERROR. + +- \remarks ++ \remarks + */ + IFX_return_t BOARD_Easy50712_Register(BOARD_t* pBoard) + { +@@ -1204,7 +1211,3 @@ + pBoard->RemoveBoard = BOARD_Easy50712_RemoveBoard; + return IFX_SUCCESS; + } +- +- +- +- diff --git a/package/ifx-tapidemo/patches/110-no_echo_cancelation.patch b/package/ifx-tapidemo/patches/110-no_echo_cancelation.patch new file mode 100644 index 000000000..d424d4847 --- /dev/null +++ b/package/ifx-tapidemo/patches/110-no_echo_cancelation.patch @@ -0,0 +1,12 @@ +Index: tapidemo-5.0.1.27/src/device_vmmc.c +=================================================================== +--- tapidemo-5.0.1.27.orig/src/device_vmmc.c 2009-11-09 15:40:31.000000000 +0100 ++++ tapidemo-5.0.1.27/src/device_vmmc.c 2010-03-30 21:32:51.000000000 +0200 +@@ -240,7 +240,6 @@ + TRACE(TAPIDEMO, DBG_LEVEL_HIGH, + ("Error, BBD file %s is not found.\n(File: %s, line: %d)\n", + pCpuDevice->pszBBD_CRAM_File, __FILE__, __LINE__)); +- return IFX_ERROR; + } + + #endif /* USE_FILESYSTEM */ diff --git a/package/ifx-vmmc/Config.in b/package/ifx-vmmc/Config.in new file mode 100644 index 000000000..bd3c032d3 --- /dev/null +++ b/package/ifx-vmmc/Config.in @@ -0,0 +1,49 @@ +choice + prompt "device selection" + default VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract + help + Select the target device. + + config VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract + bool "Danube, Twinpass, Vinax - extract binaries" + + config VOICE_CPE_VMMC_WITH_DEVICE_DANUBE + bool "Danube, Twinpass, Vinax" + + config VOICE_CPE_VMMC_WITH_DEVICE_AR9 + bool "AR9 family" + + config VOICE_CPE_VMMC_WITH_DEVICE_VR9 + bool "VR9 family" + +endchoice + +config VOICE_CPE_VMMC_PMC + depends on (VOICE_CPE_VMMC_WITH_DEVICE_AR9 || VOICE_CPE_VMMC_WITH_DEVICE_VR9) + bool "Power Management Control support" + default n + help + Option to enable Power Management Control on AR9, VR9. Not supported for Danube. + +config VOICE_CPE_VMMC_DISABLE_DECT_NIBBLE_SWAP + bool "Disable DECT nibble swap" + default n + help + Option to disable DECT nibble swap for COSIC modem (for backward compatibility only). + +config VOICE_CPE_VMMC_EVENT_LOGGER + depends on BROKEN + bool "Event logger support" + default n + help + Option to enable details traces between drv_vmmc and the voice FW + - for debugging only + - requires package ifx-evtlog + +config VOICE_CPE_VMMC_MPS_HISTORY_SIZE + int "MPS history buffer in words (0<=size<=512)" + default "128" + help + MPS history buffer (default=128 words, maximum=512 words, 0=disable) + To opimize the memory footprint in RAM, you might want to set the + buffer size to 0. diff --git a/package/ifx-vmmc/Makefile b/package/ifx-vmmc/Makefile new file mode 100644 index 000000000..c1b9b00cb --- /dev/null +++ b/package/ifx-vmmc/Makefile @@ -0,0 +1,151 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# 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:=drv_vmmc +PKG_VERSION:=1.7.0 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_MD5SUM:=3f1b44e79408a3320aa9f8b21a260fd0 +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ifx-vmmc + SUBMENU:=Voice over IP + TITLE:=TAPI LL driver for Voice Macro + URL:=http://www.lantiq.com/ + MAINTAINER:=Lantiq + DEPENDS:=+kmod-ifx-tapi @BROKEN + FILES:=$(PKG_BUILD_DIR)/src/drv_vmmc.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,25,drv_vmmc) +endef + +define KernelPackage/ifx-vmmc/description + Voice Subsystem Low Level Driver for Danube, AR9, VR9 device families +endef + +define KernelPackage/ifx-vmmc/config + if PACKAGE_kmod-ifx-vmmc + source "$(SOURCE)/Config.in" + endif +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --enable-tapiincl="$(STAGING_DIR)/usr/include/drv_tapi" \ + --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \ + $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_EVENT_LOGGER,el-debug) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_PMC,pmc) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_DISABLE_DECT_NIBBLE_SWAP,dect-nibble-swap) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_FAX,fax t38) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_CID,cid) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_DECT,dect) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_KPI,kpi) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LT_GR909,lt calibration) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_HDLC,hdlc) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_TRACES,trace) + +ifneq ($(CONFIG_VOICE_CPE_VMMC_MPS_HISTORY_SIZE),128) + CONFIGURE_ARGS += --enable-history-buf=$(CONFIG_VOICE_CPE_VMMC_MPS_HISTORY_SIZE) +endif + +#defaults +FW_URL:=http://localhost/ +FW_TARGET:=ifx_firmware.bin +FW_FILE:=fw_voip_ifx.tar.gz +COEF_TARGET:=ifx_bbd_fxs.bin +COEF_FILE:=coef_voip_ifx.tar.gz + +FW_DIR:=opt/lantiq/downloads +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) + CONFIGURE_ARGS += --with-device=DANUBE + FW_TARGET:=danube_firmware.bin + FW_URL:=http://www.arcor.de/hilfe/files/pdf/ + FW_FILE=arcor_A800_452CPW_FW_1.02.206(20081201).bin + FW_MD5SUM:=19d9af4e369287a0f0abaed415cdac10 + COEF_TARGET:=danube_bbd_fxs.bin + COEF_FILE:=arcor_A800_452CPW_FW_1.02.206(20081201).bin + COEF_MD5SUM:=19d9af4e369287a0f0abaed415cdac10 +endif + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE),y) + CONFIGURE_ARGS += --with-device=DANUBE + FW_TARGET:=danube_firmware.bin + FW_FILE=fw_voip_danube-12.1.0.1.0.tar.gz + FW_MD5SUM:=51868b88dee9dbc65d3dbba355ded91c + COEF_TARGET:=danube_bbd_fxs.bin + COEF_FILE:=coef_voip_danube-0.9.0.tar.gz + COEF_MD5SUM:=c8ac6592b304b03829a8123560e15710 +endif + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_AR9),y) + CONFIGURE_ARGS += --with-device=AR9 + # TODO: add fw/coef +endif + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_VR9),y) + CONFIGURE_ARGS += --with-device=VR9 + # TODO: add fw/coef +endif + +define Download/firmware + FILE:=$(FW_FILE) + URL:=$(FW_URL) + MD5SUM:=$(FW_MD5SUM) +endef +$(eval $(call Download,firmware)) + +define Download/coef + FILE:=$(COEF_FILE) + URL:=$(FW_URL) + MD5SUM:=$(COEF_MD5SUM) +endef +$(eval $(call Download,coef)) + +define Build/Configure + rm -rf \ + $(PKG_BUILD_DIR)/coef \ + $(PKG_BUILD_DIR)/firmware + mkdir -p \ + $(PKG_BUILD_DIR)/coef \ + $(PKG_BUILD_DIR)/firmware +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) + $(PLATFORM_DIR)/extract.sh $(DL_DIR) '$(FW_FILE)' + $(CP) $(DL_DIR)/voip.bin $(PKG_BUILD_DIR)/firmware/$(FW_TARGET) + #$(CP) $(DL_DIR)/voip_bbd.bin $(PKG_BUILD_DIR)/firmware/$(COEF_TARGET) +else + $(TAR) -C $(PKG_BUILD_DIR)/firmware -xvzf $(DL_DIR)/$(FW_FILE) + $(TAR) -C $(PKG_BUILD_DIR)/coef -xvzf $(DL_DIR)/$(COEF_FILE) +endif + (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake) + $(call Build/Configure/Default) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + mkdir -p $(1)/usr/include/drv_vmmc + $(CP) -v --dereference $(PKG_BUILD_DIR)/include/* $(1)/usr/include/drv_vmmc + (cd $(1)/usr/include/drv_vmmc && ln -snf . include) +endef + +define KernelPackage/ifx-vmmc/install + $(INSTALL_DIR) $(1)/etc/init.d $(1)/$(FW_DIR) + $(INSTALL_BIN) ./files/vmmc.init $(1)/etc/init.d/vmmc + $(CP) $(PKG_BUILD_DIR)/firmware/*.bin $(1)/$(FW_DIR)/$(FW_TARGET) +ifneq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) + $(CP) $(PKG_BUILD_DIR)/coef/$(COEF_TARGET) $(1)/$(FW_DIR)/$(COEF_TARGET) +endif +endef + +$(eval $(call KernelPackage,ifx-vmmc)) diff --git a/package/ifx-vmmc/files/vmmc.init b/package/ifx-vmmc/files/vmmc.init new file mode 100644 index 000000000..bae7badaf --- /dev/null +++ b/package/ifx-vmmc/files/vmmc.init @@ -0,0 +1,25 @@ +#!/bin/sh /etc/rc.common +# +# Activate Voice CPE TAPI subsystem LL driver for VMMC + +START=31 + +start() { + # TODO: clean up this mess + [ `cat /proc/cpuinfo | grep system | cut -f 3 -d ' '` = "Twinpass-VE" ] && { + [ ! -e /dev/danube-port ] && mknod /dev/danube-port c 254 0 + return; + } + [ `cat /proc/cpuinfo | grep system | cut -f 3 -d ' '` != "Danube" ] && { + [ ! -e /dev/amazon_s-port ] && mknod /dev/amazon_s-port c 240 1 + echo "INFO configuring HW scheduling 33/66" + echo "t0 0x0" > /proc/mips/mtsched + echo "t1 0x1" > /proc/mips/mtsched + echo "v0 0x0" > /proc/mips/mtsched + } + [ `cat /proc/cpuinfo | grep system | cut -f 3 -d ' '` = "Danube" ] && { + [ ! -e /dev/danube-port ] && mknod /dev/danube-port c 240 1 + # switch life-line relais + echo 1 > /sys/class/leds/fxs_relay/brightness + } +} diff --git a/package/ifx-vmmc/patches/001-portability.patch b/package/ifx-vmmc/patches/001-portability.patch new file mode 100644 index 000000000..fb8ab68ed --- /dev/null +++ b/package/ifx-vmmc/patches/001-portability.patch @@ -0,0 +1,26 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -227,7 +227,7 @@ drv_vmmc_CFLAGS += -fno-common + drv_vmmc_OBJS = "$(subst .c,.o, $(drv_vmmc_SOURCES) $(nodist_drv_vmmc_SOURCES))" + + drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA_DIST) +- @echo -e "Making Linux 2.6.x kernel object" ++ @echo "Making Linux 2.6.x kernel object" + @for f in $(drv_vmmc_SOURCES) $(nodist_drv_vmmc_SOURCES) ; do \ + if test ! -e $(PWD)/$$f; then \ + echo " LN $$f" ; \ +@@ -235,10 +235,10 @@ drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA + ln -s @abs_srcdir@/$$f $(PWD)/$$f; \ + fi; \ + done; +- @echo -e "# drv_vmmc: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild +- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild +- @echo -e "$(subst .ko,,$@)-y := $(drv_vmmc_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild ++ @echo "# drv_vmmc: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild ++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild ++ @echo "$(subst .ko,,$@)-y := $(drv_vmmc_OBJS)" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: diff --git a/package/ifx-vmmc/patches/100-ifxmips.patch b/package/ifx-vmmc/patches/100-ifxmips.patch new file mode 100644 index 000000000..6a4cc8d59 --- /dev/null +++ b/package/ifx-vmmc/patches/100-ifxmips.patch @@ -0,0 +1,491 @@ +--- a/src/drv_vmmc_access.h ++++ b/src/drv_vmmc_access.h +@@ -24,6 +24,10 @@ + #include "drv_mps_vmmc.h" + #endif + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# define IFX_MPS IFXMIPS_MPS_BASE_ADDR ++#endif ++ + /* ============================= */ + /* Global Defines */ + /* ============================= */ +--- a/src/drv_vmmc_bbd.c ++++ b/src/drv_vmmc_bbd.c +@@ -939,7 +939,11 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + IFX_uint8_t padBytes = 0; + #endif + IFX_uint16_t cram_offset, cram_crc, +- pCmd [MAX_CMD_WORD] = {0}; ++ pCmd [MAX_CMD_WORD] ++#if defined (__GNUC__) || defined (__GNUG__) ++ __attribute__ ((aligned(4))) ++#endif ++ = {0}; + + /* read offset */ + cpb2w (&cram_offset, &bbd_cram->pData[0], sizeof (IFX_uint16_t)); +--- a/src/drv_vmmc_danube.h ++++ b/src/drv_vmmc_danube.h +@@ -15,12 +15,59 @@ + */ + + #if defined SYSTEM_DANUBE +-#include ++# if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++ ++# define IFX_GPIO_PIN_NUMBER_PER_PORT 16 ++# define IFX_GPIO_PIN_ID(port, pin) ((port) \ ++ * IFX_GPIO_PIN_NUMBER_PER_PORT \ ++ + (pin)) ++# define IFX_GPIO_PIN_ID_TO_PORT(pin_id) (pin_id >> 4) ++# define IFX_GPIO_PIN_ID_TO_PIN(pin_id) (pin_id & 0x0F) ++ ++# define IFX_GPIO_MODULE_TAPI_VMMC 0 /* not used */ ++ ++# define ifx_gpio_pin_reserve(a,b) 0 /* obsolete */ ++ ++# define ifx_gpio_open_drain_set(a,b) ifxmips_port_set_open_drain( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_altsel0_set(a,b) ifxmips_port_set_altsel0( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_altsel1_set(a,b) ifxmips_port_set_altsel1( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_altsel0_clear(a,b) ifxmips_port_clear_altsel0( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_altsel1_clear(a,b) ifxmips_port_clear_altsel1( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_dir_in_set(a,b) ifxmips_port_set_dir_in( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_dir_out_set(a,b) ifxmips_port_set_dir_out( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_pin_free(a,b) ifxmips_port_free_pin( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++# else ++# include ++# endif + #else + #error no system selected + #endif + +-#define VMMC_TAPI_GPIO_MODULE_ID IFX_GPIO_MODULE_TAPI_VMMC ++#define VMMC_TAPI_GPIO_MODULE_ID IFX_GPIO_MODULE_TAPI_VMMC + /** + + */ +--- a/src/drv_vmmc_init.c ++++ b/src/drv_vmmc_init.c +@@ -48,6 +48,14 @@ + #include "drv_vmmc_pmc.h" + #endif /* PMC_SUPPORTED */ + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR ++# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR ++# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR ++# define IFX_MPS_CVC1SR IFXMIPS_MPS_CVC1SR ++# define IFX_MPS_CVC2SR IFXMIPS_MPS_CVC2SR ++# define IFX_MPS_CVC3SR IFXMIPS_MPS_CVC3SR ++#endif + + /* ============================= */ + /* Local Macros & Definitions */ +--- a/src/drv_vmmc_init_cap.c ++++ b/src/drv_vmmc_init_cap.c +@@ -22,6 +22,11 @@ + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_device.h" + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# define IFX_MPS_CHIPID_VERSION_GET IFXMIPS_MPS_CHIPID_VERSION_GET ++# define IFX_MPS_CHIPID IFXMIPS_MPS_CHIPID ++#endif ++ + /* ============================= */ + /* Configuration defintions */ + /* ============================= */ +--- a/src/mps/drv_mps_vmmc_common.c ++++ b/src/mps/drv_mps_vmmc_common.c +@@ -35,8 +35,35 @@ + #include "ifxos_interrupt.h" + #include "ifxos_time.h" + +-#include +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++# include ++ ++# define ifx_gptu_timer_request ifxmips_request_timer ++# define ifx_gptu_timer_start ifxmips_start_timer ++# define ifx_gptu_countvalue_get ifxmips_get_count_value ++# define ifx_gptu_timer_free ifxmips_free_timer ++ ++# define IFX_MPS_SRAM IFXMIPS_MPS_SRAM ++# define IFX_MPS_AD0ENR IFXMIPS_MPS_AD0ENR ++# define IFX_MPS_AD1ENR IFXMIPS_MPS_AD1ENR ++# define IFX_MPS_VC0ENR IFXMIPS_MPS_VC0ENR ++# define IFX_MPS_SAD0SR IFXMIPS_MPS_SAD0SR ++# define IFX_MPS_RAD0SR IFXMIPS_MPS_RAD0SR ++# define IFX_MPS_RAD1SR IFXMIPS_MPS_RAD1SR ++# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR ++# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR ++# define IFX_MPS_RVC0SR IFXMIPS_MPS_RVC0SR ++# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR ++ ++# define INT_NUM_IM4_IRL14 (INT_NUM_IM4_IRL0 + 14) ++ ++# define bsp_mask_and_ack_irq ifxmips_mask_and_ack_irq ++#else ++# include ++# include ++#endif + + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_dbg.h" +@@ -193,7 +220,8 @@ IFX_boolean_t ifx_mps_ext_bufman () + */ + IFX_void_t *ifx_mps_fastbuf_malloc (IFX_size_t size, IFX_int32_t priority) + { +- IFX_uint32_t ptr, flags; ++ unsigned long flags; ++ IFX_uint32_t ptr; + IFX_int32_t index = fastbuf_index; + + if (fastbuf_initialized == 0) +@@ -219,11 +247,11 @@ IFX_void_t *ifx_mps_fastbuf_malloc (IFX_ + if ((volatile IFX_uint32_t) fastbuf_pool[index] & FASTBUF_USED) + continue; + ptr = fastbuf_pool[index]; +- (volatile IFX_uint32_t) fastbuf_pool[index] |= FASTBUF_USED; ++ fastbuf_pool[index] = (volatile IFX_uint32_t) fastbuf_pool[index] | FASTBUF_USED; + if ((priority == FASTBUF_FW_OWNED) || (priority == FASTBUF_CMD_OWNED) || + (priority == FASTBUF_EVENT_OWNED) || + (priority == FASTBUF_WRITE_OWNED)) +- (volatile IFX_uint32_t) fastbuf_pool[index] |= priority; ++ fastbuf_pool[index] = (volatile IFX_uint32_t) fastbuf_pool[index] | priority; + fastbuf_index = index; + IFXOS_UNLOCKINT (flags); + return (IFX_void_t *) ptr; +@@ -247,7 +275,7 @@ IFX_void_t *ifx_mps_fastbuf_malloc (IFX_ + */ + IFX_void_t ifx_mps_fastbuf_free (const IFX_void_t * ptr) + { +- IFX_uint32_t flags; ++ unsigned long flags; + IFX_int32_t index = fastbuf_index; + + IFXOS_LOCKINT (flags); +@@ -261,8 +289,9 @@ IFX_void_t ifx_mps_fastbuf_free (const I + FASTBUF_EVENT_OWNED | FASTBUF_WRITE_OWNED)) + == ((IFX_uint32_t) ptr | FASTBUF_USED)) + { +- (volatile IFX_uint32_t) fastbuf_pool[index] &= ~FASTBUF_USED; +- (volatile IFX_uint32_t) fastbuf_pool[index] &= ++ fastbuf_pool[index] = (volatile IFX_uint32_t) fastbuf_pool[index] & ~FASTBUF_USED; ++ ++ fastbuf_pool[index] = (volatile IFX_uint32_t) fastbuf_pool[index] & + ~(FASTBUF_FW_OWNED | FASTBUF_CMD_OWNED | FASTBUF_EVENT_OWNED | + FASTBUF_WRITE_OWNED); + IFXOS_UNLOCKINT (flags); +@@ -444,7 +473,7 @@ static mps_buffer_state_e ifx_mps_bufman + */ + static IFX_int32_t ifx_mps_bufman_inc_level (IFX_uint32_t value) + { +- IFX_uint32_t flags; ++ unsigned long flags; + + if (mps_buffer.buf_level + value > MPS_BUFFER_MAX_LEVEL) + { +@@ -471,7 +500,7 @@ static IFX_int32_t ifx_mps_bufman_inc_le + */ + static IFX_int32_t ifx_mps_bufman_dec_level (IFX_uint32_t value) + { +- IFX_uint32_t flags; ++ unsigned long flags; + + if (mps_buffer.buf_level < value) + { +@@ -932,7 +961,7 @@ IFX_int32_t ifx_mps_common_open (mps_com + mps_mbx_dev * pMBDev, IFX_int32_t bcommand, + IFX_boolean_t from_kernel) + { +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + +@@ -1048,7 +1077,7 @@ IFX_int32_t ifx_mps_common_close (mps_mb + IFX_void_t ifx_mps_release_structures (mps_comm_dev * pDev) + { + IFX_int32_t count; +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + IFXOS_BlockFree (pFW_img_data); +@@ -1544,7 +1573,7 @@ IFX_int32_t ifx_mps_mbx_read_message (mp + IFX_uint32_t * bytes) + { + IFX_int32_t i, ret; +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + +@@ -1751,7 +1780,7 @@ IFX_int32_t ifx_mps_mbx_write_message (m + { + mps_fifo *mbx; + IFX_uint32_t i; +- IFX_uint32_t flags; ++ unsigned long flags; + IFX_int32_t retval = -EAGAIN; + IFX_int32_t retries = 0; + IFX_uint32_t word = 0; +@@ -2138,6 +2167,7 @@ IFX_int32_t ifx_mps_mbx_write_cmd (mps_m + TRACE (MPS, DBG_LEVEL_HIGH, + ("%s(): Invalid device ID %d !\n", __FUNCTION__, pMBDev->devID)); + } ++ + return retval; + } + +@@ -2161,7 +2191,7 @@ IFX_void_t ifx_mps_mbx_data_upstream (IF + mps_mbx_dev *mbx_dev; + MbxMsg_s msg; + IFX_uint32_t bytes_read = 0; +- IFX_uint32_t flags; ++ unsigned long flags; + IFX_int32_t ret; + + /* set pointer to data upstream mailbox, no matter if 0,1,2 or 3 because +@@ -2252,7 +2282,7 @@ IFX_void_t ifx_mps_mbx_data_upstream (IF + { + ifx_mps_bufman_dec_level (1); + if ((ifx_mps_bufman_get_level () <= mps_buffer.buf_threshold) && +- (atomic_read (&pMPSDev->provide_buffer->object.count) == 0)) ++ ((volatile unsigned int)pMPSDev->provide_buffer->object.count == 0)) + { + IFXOS_LockRelease (pMPSDev->provide_buffer); + } +@@ -2295,7 +2325,7 @@ IFX_void_t ifx_mps_mbx_data_upstream (IF + #endif /* CONFIG_PROC_FS */ + ifx_mps_bufman_dec_level (1); + if ((ifx_mps_bufman_get_level () <= mps_buffer.buf_threshold) && +- (atomic_read (&pMPSDev->provide_buffer->object.count) == 0)) ++ ((volatile unsigned int)pMPSDev->provide_buffer->object.count == 0)) + { + IFXOS_LockRelease (pMPSDev->provide_buffer); + } +@@ -2325,7 +2355,7 @@ IFX_void_t ifx_mps_mbx_data_upstream (IF + IFX_void_t ifx_mps_mbx_cmd_upstream (IFX_ulong_t dummy) + { + mps_fifo *mbx; +- IFX_uint32_t flags; ++ unsigned long flags; + + /* set pointer to upstream command mailbox */ + mbx = &(pMPSDev->cmd_upstrm_fifo); +@@ -2373,7 +2403,7 @@ IFX_void_t ifx_mps_mbx_event_upstream (I + mps_event_msg msg; + IFX_int32_t length = 0; + IFX_int32_t read_length = 0; +- IFX_uint32_t flags; ++ unsigned long flags; + + /* set pointer to upstream event mailbox */ + mbx = &(pMPSDev->event_upstrm_fifo); +@@ -2616,7 +2646,7 @@ IFX_void_t ifx_mps_disable_mailbox_int ( + */ + IFX_void_t ifx_mps_dd_mbx_int_enable (IFX_void_t) + { +- IFX_uint32_t flags; ++ unsigned long flags; + MPS_Ad0Reg_u Ad0Reg; + + IFXOS_LOCKINT (flags); +@@ -2642,7 +2672,7 @@ IFX_void_t ifx_mps_dd_mbx_int_enable (IF + */ + IFX_void_t ifx_mps_dd_mbx_int_disable (IFX_void_t) + { +- IFX_uint32_t flags; ++ unsigned long flags; + MPS_Ad0Reg_u Ad0Reg; + + IFXOS_LOCKINT (flags); +@@ -2769,6 +2799,7 @@ irqreturn_t ifx_mps_ad0_irq (IFX_int32_t + } + } + ++ + if (MPS_Ad0StatusReg.fld.du_mbx) + { + #ifdef CONFIG_PROC_FS +@@ -3062,7 +3093,8 @@ IFX_int32_t ifx_mps_get_fw_version (IFX_ + */ + IFX_return_t ifx_mps_init_gpt () + { +- IFX_uint32_t flags, timer_flags, timer, loops = 0; ++ unsigned long flags; ++ IFX_uint32_t timer_flags, timer, loops = 0; + IFX_ulong_t count; + #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) + timer = TIMER1A; +--- a/src/mps/drv_mps_vmmc_danube.c ++++ b/src/mps/drv_mps_vmmc_danube.c +@@ -32,9 +32,22 @@ + #include "ifxos_select.h" + #include "ifxos_interrupt.h" + +-#include +-#include +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++# include ++# include ++ ++# define IFX_RCU_RST_REQ IFXMIPS_RCU_RST ++# define IFX_RCU_RST_REQ_CPU1 IFXMIPS_RCU_RST_CPU1 ++ ++# define ifx_get_cp1_base prom_get_cp1_base ++# define ifx_get_cp1_size prom_get_cp1_size ++#else ++# include ++# include ++# include ++#endif + + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_dbg.h" +@@ -119,6 +132,15 @@ IFX_int32_t ifx_mps_download_firmware (m + } + + /* check if FW image fits in available memory space */ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++ if (mem > ifx_get_cp1_size()<<20) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("[%s %s %d]: error, firmware memory exceeds reserved space (%i > %i)!\n", ++ __FILE__, __func__, __LINE__, mem, ifx_get_cp1_size()<<20)); ++ return IFX_ERROR; ++ } ++#else + if (mem > ifx_get_cp1_size()) + { + TRACE (MPS, DBG_LEVEL_HIGH, +@@ -126,6 +148,7 @@ IFX_int32_t ifx_mps_download_firmware (m + __FILE__, __func__, __LINE__, mem, ifx_get_cp1_size())); + return IFX_ERROR; + } ++#endif + + /* reset the driver */ + ifx_mps_reset (); +@@ -337,7 +360,7 @@ IFX_void_t ifx_mps_release (IFX_void_t) + */ + IFX_void_t ifx_mps_wdog_expiry() + { +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + /* recalculate and compare the firmware checksum */ +--- a/src/mps/drv_mps_vmmc_device.h ++++ b/src/mps/drv_mps_vmmc_device.h +@@ -16,8 +16,15 @@ + declarations. + *******************************************************************************/ + +-#include +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++# include ++# include ++#else ++# include ++# include ++#endif + + /* ============================= */ + /* MPS Common defines */ +--- a/src/mps/drv_mps_vmmc_linux.c ++++ b/src/mps/drv_mps_vmmc_linux.c +@@ -40,10 +40,26 @@ + #include + #endif /* */ + +- +-#include +-#include +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++ ++# define IFX_MPS_AD0ENR IFXMIPS_MPS_AD0ENR ++# define IFX_MPS_AD1ENR IFXMIPS_MPS_AD1ENR ++# define IFX_MPS_RAD0SR IFXMIPS_MPS_RAD0SR ++# define IFX_MPS_RAD1SR IFXMIPS_MPS_RAD1SR ++# define IFX_MPS_VC0ENR IFXMIPS_MPS_VC0ENR ++# define IFX_MPS_RVC0SR IFXMIPS_MPS_RVC0SR ++ ++# define INT_NUM_IM4_IRL14 (INT_NUM_IM4_IRL0 + 14) ++# define INT_NUM_IM4_IRL18 (INT_NUM_IM4_IRL0 + 18) ++# define INT_NUM_IM4_IRL19 (INT_NUM_IM4_IRL0 + 19) ++# define IFX_ICU_IM4_IER IFXMIPS_ICU_IM4_IER ++#else ++# include ++# include ++# include ++#endif + + /* lib_ifxos headers */ + #include "ifx_types.h" +@@ -914,7 +930,7 @@ IFX_int32_t ifx_mps_ioctl (struct inode + #endif /* MPS_FIFO_BLOCKING_WRITE */ + case FIO_MPS_GET_STATUS: + { +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + +@@ -949,7 +965,7 @@ IFX_int32_t ifx_mps_ioctl (struct inode + #if CONFIG_MPS_HISTORY_SIZE > 0 + case FIO_MPS_GET_CMD_HISTORY: + { +- IFX_uint32_t flags; ++ unsigned long flags; + + if (from_kernel) + { +@@ -1637,6 +1653,7 @@ IFX_int32_t ifx_mps_get_status_proc (IFX + sprintf (buf + len, " minLv: \t %8d\n", + ifx_mps_dev.voice_mb[i].upstrm_fifo->min_space); + } ++ + return len; + } + diff --git a/package/ifxos/Makefile b/package/ifxos/Makefile index de4da7de8..2a84eb53e 100644 --- a/package/ifxos/Makefile +++ b/package/ifxos/Makefile @@ -23,7 +23,7 @@ define KernelPackage/ifxos TITLE:=Lantiq OS abstraction library URL:=http://www.lantiq.com/ MAINTAINER:=Lantiq - DEPENDS:=@TARGET_ifxmips + DEPENDS:=@TARGET_ifxmips @BROKEN FILES:=$(PKG_BUILD_DIR)/src/drv_ifxos.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,10,drv_ifxos) endef From 9e41f39fb684dea6a2c81446e16dd96dcf572ad8 Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 31 Mar 2010 15:34:51 +0000 Subject: [PATCH 35/45] hostapd: fix build error caused by r20631 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20638 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/hostapd/Makefile | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/package/hostapd/Makefile b/package/hostapd/Makefile index 38d91875e..0ccba9ad9 100644 --- a/package/hostapd/Makefile +++ b/package/hostapd/Makefile @@ -25,6 +25,7 @@ PKG_BUILD_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \ CONFIG_WPA_SUPPLICANT_NO_TIMESTAMP_CHECK \ CONFIG_PACKAGE_kmod-ath9k \ + CONFIG_PACKAGE_kmod-rt2800-lib \ CONFIG_PACKAGE_kmod-mac80211 \ CONFIG_PACKAGE_kmod-madwifi \ CONFIG_PACKAGE_hostapd \ @@ -50,11 +51,19 @@ PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSI include $(INCLUDE_DIR)/package.mk +ifneq ($(CONFIG_PACKAGE_kmod-rt2800-lib),) + HOSTAPD_IEEE80211N:=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-ath9k),) + HOSTAPD_IEEE80211N:=y +endif + DRIVER_MAKEOPTS= \ CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-mac80211) \ CONFIG_DRIVER_MADWIFI=$(CONFIG_PACKAGE_kmod-madwifi) \ CONFIG_DRIVER_HOSTAP=$(CONFIG_PACKAGE_kmod-hostap) \ - CONFIG_IEEE80211N=$(if ($(CONFIG_PACKAGE_kmod-ath9k)$(CONFIG_PACKAGE_kmod-rt2800-lib)),y) \ + CONFIG_IEEE80211N=$(HOSTAPD_IEEE80211N) \ CONFIG_IEEE80211W=$(CONFIG_PACKAGE_kmod-ath9k) ifneq ($(LOCAL_TYPE),hostapd) From 5332ca5feaadbbb230d06be83d84e9f992877653 Mon Sep 17 00:00:00 2001 From: blogic Date: Wed, 31 Mar 2010 17:24:43 +0000 Subject: [PATCH 36/45] [ifxmips] update os abstraction layer git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20639 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/ifxos/Makefile | 6 ++--- package/ifxos/patches/100-portability.patch | 27 +++++---------------- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/package/ifxos/Makefile b/package/ifxos/Makefile index 2a84eb53e..5b453aed6 100644 --- a/package/ifxos/Makefile +++ b/package/ifxos/Makefile @@ -10,16 +10,16 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=lib_ifxos -PKG_VERSION:=1.5.10 +PKG_VERSION:=1.5.12 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_RELEASE:=1 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources -PKG_MD5SUM:=3602797b0f531f37546c6beb748d50cf +#PKG_MD5SUM:=3602797b0f531f37546c6beb748d50cf include $(INCLUDE_DIR)/package.mk define KernelPackage/ifxos - SUBMENU:=Lantiq + SUBMENU:=Other modules TITLE:=Lantiq OS abstraction library URL:=http://www.lantiq.com/ MAINTAINER:=Lantiq diff --git a/package/ifxos/patches/100-portability.patch b/package/ifxos/patches/100-portability.patch index 92b0ea01c..51d6bbd16 100644 --- a/package/ifxos/patches/100-portability.patch +++ b/package/ifxos/patches/100-portability.patch @@ -1,23 +1,8 @@ ---- a/configure.in -+++ b/configure.in -@@ -149,12 +149,12 @@ AC_ARG_ENABLE(targetincl, - echo Set the target image include path $enableval - AC_SUBST([TARGET_INCL_PATH],[$enableval]) - else -- echo -e Set the default target image include path $DEFAULT_TARGET_INCL_PATH -+ echo Set the default target image include path $DEFAULT_TARGET_INCL_PATH - AC_SUBST([TARGET_INCL_PATH],[$DEFAULT_TARGET_INCL_PATH]) - fi - ], - [ -- echo -e Set the default target image include path $DEFAULT_TARGET_INCL_PATH -+ echo Set the default target image include path $DEFAULT_TARGET_INCL_PATH - AC_SUBST([TARGET_INCL_PATH],[$DEFAULT_TARGET_INCL_PATH]) - ] - ) ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -610,7 +610,7 @@ if KERNEL_2_6 +Index: lib_ifxos-1.5.12/src/Makefile.am +=================================================================== +--- lib_ifxos-1.5.12.orig/src/Makefile.am 2010-01-08 18:12:15.000000000 +0100 ++++ lib_ifxos-1.5.12/src/Makefile.am 2010-03-31 18:56:12.000000000 +0200 +@@ -639,7 +639,7 @@ drv_ifxos_OBJS = "$(subst .c,.o,$(filter %.c,$(drv_ifxos_SOURCES)))" drv_ifxos.ko: $(drv_ifxos_SOURCES) @@ -26,7 +11,7 @@ if test ! -e common/ifxos_debug.c ; then \ echo "copy source files (as links only!)"; \ for f in $(filter %.c,$(drv_ifxos_SOURCES)); do \ -@@ -618,10 +618,10 @@ drv_ifxos.ko: $(drv_ifxos_SOURCES) +@@ -647,10 +647,10 @@ cp -s $(addprefix @abs_srcdir@/,$$f) $(PWD)/`dirname $$f`/ ; \ done \ fi From 1a2ce2ca8b9d570c639b260fb0da55fb48472146 Mon Sep 17 00:00:00 2001 From: blogic Date: Wed, 31 Mar 2010 21:11:39 +0000 Subject: [PATCH 37/45] [ifxmips] adds proper md5sum to ifxos git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20640 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/ifxos/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/ifxos/Makefile b/package/ifxos/Makefile index 5b453aed6..e0fac2303 100644 --- a/package/ifxos/Makefile +++ b/package/ifxos/Makefile @@ -14,7 +14,7 @@ PKG_VERSION:=1.5.12 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_RELEASE:=1 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources -#PKG_MD5SUM:=3602797b0f531f37546c6beb748d50cf +PKG_MD5SUM:=ba775356bdd5e1b73b3e11a152710ed6 include $(INCLUDE_DIR)/package.mk From 11abdf5e7d5ced0b23f0662e98677235909e4ec1 Mon Sep 17 00:00:00 2001 From: blogic Date: Wed, 31 Mar 2010 21:12:02 +0000 Subject: [PATCH 38/45] [ifxmips] improve extract code git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20641 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/ifxmips/extract.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/target/linux/ifxmips/extract.sh b/target/linux/ifxmips/extract.sh index 4024969d1..7b1c1da0b 100755 --- a/target/linux/ifxmips/extract.sh +++ b/target/linux/ifxmips/extract.sh @@ -11,10 +11,16 @@ echo "Please only do so if it is legal in your country" exit 1 } -[ ! -f ${DIR}bbd.crypt ] && { - dd if=${FILE} of=${DIR}bbd.crypt bs=1 skip=104 count=1472302 +[ -f ${DIR}/ifxmips_fw_decode.tar.bz2 -a ! -f ${DIR}voip_coef.bin ] && { + [ ! -f ${DIR}decode_ifx_fw ] && { + tar xjf ${DIR}ifxmips_fw_decode.tar.bz2 ifxmips_fw_decode/decode.c -O > ${DIR}decode.c + gcc -o ${DIR}decode_ifx_fw ${DIR}decode.c + } + [ ! -f ${DIR}voip_coef.lzma ] && { + ${DIR}decode_ifx_fw $FILE ${DIR}voip_coef.lzma + } + lzma d ${DIR}voip_coef.lzma ${DIR}voip_coef.bin } - [ ! -f ${DIR}dsl_a.bin ] && { dd if=${FILE} of=${DIR}dsl1.lzma bs=1 skip=2168832 count=150724 lzma d ${DIR}dsl2.lzma ${DIR}dsl_a.bin From 38b25a187b7c5a833e6d8e5ba215f25043d2d3ab Mon Sep 17 00:00:00 2001 From: blogic Date: Wed, 31 Mar 2010 21:12:20 +0000 Subject: [PATCH 39/45] [ifxmips] load firmware to /lib/firmware git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20642 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/ifx-tapidemo/files/bringup_tapidemo | 2 +- package/ifx-vmmc/Makefile | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/package/ifx-tapidemo/files/bringup_tapidemo b/package/ifx-tapidemo/files/bringup_tapidemo index e3abd5639..6eb13d25f 100644 --- a/package/ifx-tapidemo/files/bringup_tapidemo +++ b/package/ifx-tapidemo/files/bringup_tapidemo @@ -17,7 +17,7 @@ START=96 TD_EXTRA_FLAGS_FXO= TD_EXTRA_FLAGS_KPI2UDP= -TD_DOWNLOAD_PATH=/opt/lantiq/downloads/ +TD_DOWNLOAD_PATH=/lib/firmware/ DEV_NODE_TERIDIAN=ter10 # Show help diff --git a/package/ifx-vmmc/Makefile b/package/ifx-vmmc/Makefile index c1b9b00cb..945d5ba7e 100644 --- a/package/ifx-vmmc/Makefile +++ b/package/ifx-vmmc/Makefile @@ -67,7 +67,7 @@ FW_FILE:=fw_voip_ifx.tar.gz COEF_TARGET:=ifx_bbd_fxs.bin COEF_FILE:=coef_voip_ifx.tar.gz -FW_DIR:=opt/lantiq/downloads +FW_DIR:=lib/firmware ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) CONFIGURE_ARGS += --with-device=DANUBE FW_TARGET:=danube_firmware.bin @@ -99,6 +99,15 @@ ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_VR9),y) # TODO: add fw/coef endif +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) +define Download/decode + FILE:=ifxmips_fw_decode.tar.bz2 + URL:=http://downloads.openwrt.org/sources/ + MD5SUM:=1197ff6cace6a7c86492a468f5fbfe07 +endef +$(eval $(call Download,decode)) +endif + define Download/firmware FILE:=$(FW_FILE) URL:=$(FW_URL) @@ -123,7 +132,7 @@ define Build/Configure ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) $(PLATFORM_DIR)/extract.sh $(DL_DIR) '$(FW_FILE)' $(CP) $(DL_DIR)/voip.bin $(PKG_BUILD_DIR)/firmware/$(FW_TARGET) - #$(CP) $(DL_DIR)/voip_bbd.bin $(PKG_BUILD_DIR)/firmware/$(COEF_TARGET) + $(CP) $(DL_DIR)/voip_coef.bin $(PKG_BUILD_DIR)/coef/$(COEF_TARGET) else $(TAR) -C $(PKG_BUILD_DIR)/firmware -xvzf $(DL_DIR)/$(FW_FILE) $(TAR) -C $(PKG_BUILD_DIR)/coef -xvzf $(DL_DIR)/$(COEF_FILE) @@ -142,10 +151,8 @@ endef define KernelPackage/ifx-vmmc/install $(INSTALL_DIR) $(1)/etc/init.d $(1)/$(FW_DIR) $(INSTALL_BIN) ./files/vmmc.init $(1)/etc/init.d/vmmc - $(CP) $(PKG_BUILD_DIR)/firmware/*.bin $(1)/$(FW_DIR)/$(FW_TARGET) -ifneq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) + $(CP) $(PKG_BUILD_DIR)/firmware/$(FW_TARGET) $(1)/$(FW_DIR)/$(FW_TARGET) $(CP) $(PKG_BUILD_DIR)/coef/$(COEF_TARGET) $(1)/$(FW_DIR)/$(COEF_TARGET) -endif endef $(eval $(call KernelPackage,ifx-vmmc)) From 23f27ea50bbe2cbdd0c260c7c6b78229a83d7996 Mon Sep 17 00:00:00 2001 From: kaloz Date: Thu, 1 Apr 2010 12:05:27 +0000 Subject: [PATCH 40/45] [x86]: add a subtarget and drivers for the Intel Tolapai SoC git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20648 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/ep80579-drivers/Makefile | 80 + .../patches/001-igbe_update.patch | 11755 ++++++++++++++++ .../patches/002-cflags_cleanup.patch | 22 + .../patches/003-new_irqf_constants.patch | 53 + .../patches/100-iegbe_netdev_ops.patch | 56 + .../101-iegbe_fix_napi_interface.patch | 41 + .../102-iegbe_nuke_polling_netdev.patch | 103 + .../103-iegbe_convert_unicast_addr_list.patch | 60 + ...gbe_group_address_list_and_its_count.patch | 20 + .../patches/105-iegbe_new_dma_masks.patch | 20 + .../patches/106-iegbe_new_irqf_constant.patch | 12 + .../patches/150-ocracoke_island.patch | 747 + .../patches/200-can_fix_ioctl_numbers.patch | 11 + .../patches/210-can_include_linux_fs_h.patch | 11 + .../patches/220-can_fix_irq_request.patch | 23 + ...can_remove_driver_data_direct_access.patch | 41 + .../patches/300-wdt_compile_fix.patch | 59 + .../400-edma_fix_irq_request_warning.patch | 22 + .../500-1588_fix_irq_request_warning.patch | 22 + .../patches/600-2.6.27_includes.patch | 22 + .../patches/601-2.6.32_includes.patch | 33 + .../patches/700-iegbe_kcompat_2.6.30.patch | 31 + .../patches/701-iegbe_poll_dev.patch | 11 + target/linux/generic-2.6/config-2.6.32 | 1 + target/linux/x86/Makefile | 2 +- target/linux/x86/ep80579/config-default | 12 + target/linux/x86/ep80579/target.mk | 9 + 27 files changed, 13278 insertions(+), 1 deletion(-) create mode 100644 package/ep80579-drivers/Makefile create mode 100644 package/ep80579-drivers/patches/001-igbe_update.patch create mode 100644 package/ep80579-drivers/patches/002-cflags_cleanup.patch create mode 100644 package/ep80579-drivers/patches/003-new_irqf_constants.patch create mode 100644 package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch create mode 100644 package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch create mode 100644 package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch create mode 100644 package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch create mode 100644 package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch create mode 100644 package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch create mode 100644 package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch create mode 100644 package/ep80579-drivers/patches/150-ocracoke_island.patch create mode 100644 package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch create mode 100644 package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch create mode 100644 package/ep80579-drivers/patches/220-can_fix_irq_request.patch create mode 100644 package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch create mode 100644 package/ep80579-drivers/patches/300-wdt_compile_fix.patch create mode 100644 package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch create mode 100644 package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch create mode 100644 package/ep80579-drivers/patches/600-2.6.27_includes.patch create mode 100644 package/ep80579-drivers/patches/601-2.6.32_includes.patch create mode 100644 package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch create mode 100644 package/ep80579-drivers/patches/701-iegbe_poll_dev.patch create mode 100644 target/linux/x86/ep80579/config-default create mode 100644 target/linux/x86/ep80579/target.mk diff --git a/package/ep80579-drivers/Makefile b/package/ep80579-drivers/Makefile new file mode 100644 index 000000000..fac0fbbad --- /dev/null +++ b/package/ep80579-drivers/Makefile @@ -0,0 +1,80 @@ +# +# Copyright (C) 2010 OpenWrt.org +# +# 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:=ep80579-drivers +PKG_VERSION:=1.0.34 +PKG_RELEASE:=1 + +PKG_SOURCE:=Embedded.L.1.0.34.ADI.R100.tar.gz +PKG_SOURCE_URL:=ftp://ftp.adiengineering.com/Archive/OcracokeIsland/Drivers/Linux/1.0.34/ +PKG_MD5SUM:=61df9778f8c1f919257d2f48a0bcb000 + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ep80579-drivers/Default + DEPENDS:=@TARGET_x86 +endef + +define KernelPackage/ep80579-eth +$(call KernelPackage/ep80579-drivers/Default) + SUBMENU:=Network Devices + TITLE:=Intel EP80579 ethernet driver + FILES:= \ + $(PKG_BUILD_DIR)/Embedded/build/gcu.$(LINUX_KMOD_SUFFIX) \ + $(PKG_BUILD_DIR)/Embedded/build/iegbe.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,40,gcu iegbe) +endef + +define KernelPackage/ep80579-misc +$(call KernelPackage/ep80579-drivers/Default) + SUBMENU:=Other modules + TITLE:=Misc. Intel EP80579 drivers (DMA,, gpio) + FILES:= \ + $(PKG_BUILD_DIR)/Embedded/build/dma.$(LINUX_KMOD_SUFFIX) \ + $(PKG_BUILD_DIR)/Embedded/build/gpio.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,40,gpio dma) +endef + +define KernelPackage/ep80579-can +$(call KernelPackage/ep80579-drivers/Default) + SUBMENU:=Other modules + TITLE:=Intel EP80579 CAN driver + FILES:= \ + $(PKG_BUILD_DIR)/Embedded/build/timesync.$(LINUX_KMOD_SUFFIX) \ + $(PKG_BUILD_DIR)/Embedded/build/can.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,40,timesync can) +endef + +define Build/Prepare + rm -rf $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR) + tar xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR)/ + $(Build/Patch) +endef + +define Build/Compile + (cd $(PKG_BUILD_DIR)/Embedded; \ + $(MAKE) KERNEL_SOURCE_ROOT=$(LINUX_DIR) \ + KSRC=$(LINUX_DIR) \ + KOBJ=$(LINUX_DIR) \ + ENV_DIR=$(PKG_BUILD_DIR)/Embedded \ + all \ + ) +endef + +define KernelPackage/ep80579-eth/install +endef + +$(eval $(call KernelPackage,ep80579-can)) +$(eval $(call KernelPackage,ep80579-eth)) +$(eval $(call KernelPackage,ep80579-misc)) + diff --git a/package/ep80579-drivers/patches/001-igbe_update.patch b/package/ep80579-drivers/patches/001-igbe_update.patch new file mode 100644 index 000000000..67560b8de --- /dev/null +++ b/package/ep80579-drivers/patches/001-igbe_update.patch @@ -0,0 +1,11755 @@ +--- a/Embedded/src/GbE/gcu.h ++++ b/Embedded/src/GbE/gcu.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/gcu_if.c ++++ b/Embedded/src/GbE/gcu_if.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -330,10 +330,17 @@ gcu_write_verify(uint32_t phy_num, uint3 + */ + void gcu_iegbe_resume(struct pci_dev *pdev) + { ++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ) ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct gcu_adapter *adapter = netdev_priv(netdev); ++#endif ++ + GCU_DBG("%s\n", __func__); + + pci_restore_state(pdev); +- pci_enable_device(pdev); ++ if(!pci_enable_device(pdev)) ++ GCU_DBG("pci_enable_device failed!\n",); + + return; + } +@@ -348,6 +355,12 @@ EXPORT_SYMBOL(gcu_iegbe_resume); + */ + int gcu_iegbe_suspend(struct pci_dev *pdev, uint32_t state) + { ++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ) ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct gcu_adapter *adapter = netdev_priv(netdev); ++#endif ++ + GCU_DBG("%s\n", __func__); + + pci_save_state(pdev); +--- a/Embedded/src/GbE/gcu_if.h ++++ b/Embedded/src/GbE/gcu_if.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/gcu_main.c ++++ b/Embedded/src/GbE/gcu_main.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -94,6 +94,7 @@ static struct pci_driver gcu_driver = { + + static struct gcu_adapter *global_adapter = 0; + static spinlock_t global_adapter_spinlock = SPIN_LOCK_UNLOCKED; ++static unsigned long g_intflags = 0; + + MODULE_AUTHOR("Intel(R) Corporation"); + MODULE_DESCRIPTION("Global Configuration Unit Driver"); +@@ -124,7 +125,7 @@ gcu_init_module(void) + + printk(KERN_INFO "%s\n", gcu_copyright); + +- ret = pci_module_init(&gcu_driver); ++ ret = pci_register_driver(&gcu_driver); + if(ret >= 0) { + register_reboot_notifier(&gcu_notifier_reboot); + } +@@ -199,8 +200,6 @@ gcu_probe(struct pci_dev *pdev, + return -ENOMEM; + } + +- SET_MODULE_OWNER(adapter); +- + pci_set_drvdata(pdev, adapter); + + adapter->pdev = pdev; +@@ -238,7 +237,6 @@ gcu_probe(struct pci_dev *pdev, + return 0; + } + +- + /** + * gcu_probe_err - gcu_probe error handler + * @err: gcu_err_type +@@ -295,7 +293,7 @@ gcu_notify_reboot(struct notifier_block + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: +- while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { ++ while((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { + if(pci_dev_driver(pdev) == &gcu_driver){ + gcu_suspend(pdev, 0x3); + } +@@ -318,6 +316,11 @@ static int + gcu_suspend(struct pci_dev *pdev, uint32_t state) + { + /*struct gcu_adapter *adapter = pci_get_drvdata(pdev); */ ++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ) ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct gcu_adapter *adapter = netdev_priv(netdev); ++#endif + + GCU_DBG("%s\n", __func__); + +@@ -338,7 +341,6 @@ gcu_suspend(struct pci_dev *pdev, uint32 + return state; + } + +- + /** + * alloc_gcu_adapter + * +@@ -412,7 +414,7 @@ gcu_get_adapter(void) + return NULL; + } + +- spin_lock(&global_adapter_spinlock); ++ spin_lock_irqsave(&global_adapter_spinlock, g_intflags); + + return global_adapter; + } +@@ -437,7 +439,7 @@ gcu_release_adapter(const struct gcu_ada + *adapter = 0; + } + +- spin_unlock(&global_adapter_spinlock); ++ spin_unlock_irqrestore(&global_adapter_spinlock, g_intflags); + + return; + } +--- a/Embedded/src/GbE/gcu_reg.h ++++ b/Embedded/src/GbE/gcu_reg.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/iegbe.7 ++++ b/Embedded/src/GbE/iegbe.7 +@@ -1,7 +1,7 @@ + + .\" GPL LICENSE SUMMARY + .\" +-.\" Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++.\" Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + .\" + .\" This program is free software; you can redistribute it and/or modify + .\" it under the terms of version 2 of the GNU General Public License as +@@ -21,7 +21,7 @@ + .\" Contact Information: + .\" Intel Corporation + .\" +-.\" version: Embedded.L.1.0.34 ++.\" version: Embedded.Release.Patch.L.1.0.7-5 + + .\" LICENSE + .\" +--- a/Embedded/src/GbE/iegbe_ethtool.c ++++ b/Embedded/src/GbE/iegbe_ethtool.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -132,22 +132,6 @@ static const struct iegbe_stats iegbe_gs + { "cpp_master", E1000_STAT(icr_cpp_master) }, + { "stat", E1000_STAT(icr_stat) }, + #endif +-#ifdef IEGBE_GBE_WORKAROUND +- { "txqec", E1000_STAT(stats.txqec) }, +- { "tx_next_to_clean", E1000_STAT(stats.tx_next_to_clean) }, +- { "tx_next_to_use", E1000_STAT(stats.tx_next_to_use) }, +- { "num_tx_queues", E1000_STAT(stats.num_tx_queues) }, +- +- { "num_rx_buf_alloc", E1000_STAT(stats.num_rx_buf_alloc) }, +- { "rx_next_to_clean", E1000_STAT(stats.rx_next_to_clean) }, +- { "rx_next_to_use", E1000_STAT(stats.rx_next_to_use) }, +- { "cc_gt_num_rx", E1000_STAT(stats.cc_gt_num_rx) }, +- { "tx_hnet", E1000_STAT(stats.tx_hnet) }, +- { "tx_hnentu", E1000_STAT(stats.tx_hnentu) }, +- { "RUC", E1000_STAT(stats.ruc) }, +- { "RFC", E1000_STAT(stats.rfc) }, +- +-#endif + }; + #define E1000_STATS_LEN \ + sizeof(iegbe_gstrings_stats) / sizeof(struct iegbe_stats) +@@ -158,7 +142,7 @@ static const char iegbe_gstrings_test[][ + "Interrupt test (offline)", "Loopback test (offline)", + "Link test (on/offline)" + }; +-#define E1000_TEST_LEN (sizeof(iegbe_gstrings_test) / (ETH_GSTRING_LEN)) ++#define E1000_TEST_LEN (sizeof(iegbe_gstrings_test) / ETH_GSTRING_LEN) + #endif /* ETHTOOL_TEST */ + + #define E1000_REGS_LEN 0x20 +@@ -176,9 +160,7 @@ iegbe_get_settings(struct net_device *ne + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | +-#ifndef IEGBE_10_100_ONLY + SUPPORTED_1000baseT_Full| +-#endif + SUPPORTED_Autoneg | + SUPPORTED_TP); + +@@ -259,21 +241,13 @@ iegbe_set_settings(struct net_device *ne + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | +-#ifndef IEGBE_10_100_ONLY + ADVERTISED_1000baseT_Full| +-#endif +- + ADVERTISED_Autoneg | + ADVERTISED_TP; + ecmd->advertising = hw->autoneg_advertised; + } +- } else { +- uint16_t duplex; +- +- // ethtool uses DUPLEX_FULL/DUPLEX_HALF +- // the driver needs FULL_DUPLEX/HALF_DUPLEX +- duplex = (ecmd->duplex == DUPLEX_FULL) ? FULL_DUPLEX : HALF_DUPLEX; +- if(iegbe_set_spd_dplx(adapter, ecmd->speed + duplex)) ++ } else ++ if(iegbe_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)){ + return -EINVAL; + } + /* reset the link */ +@@ -728,8 +702,8 @@ iegbe_set_ringparam(struct net_device *n + struct iegbe_rx_ring *rxdr, *rx_old, *rx_new; + int i, err, tx_ring_size, rx_ring_size; + +- tx_ring_size = sizeof(struct iegbe_tx_ring) * adapter->num_queues; +- rx_ring_size = sizeof(struct iegbe_rx_ring) * adapter->num_queues; ++ tx_ring_size = sizeof(struct iegbe_tx_ring) * adapter->num_tx_queues; ++ rx_ring_size = sizeof(struct iegbe_rx_ring) * adapter->num_rx_queues; + + if (netif_running(adapter->netdev)){ + iegbe_down(adapter); +@@ -768,10 +742,10 @@ iegbe_set_ringparam(struct net_device *n + E1000_MAX_TXD : E1000_MAX_82544_TXD)); + E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); + +- for (i = 0; i < adapter->num_queues; i++) { +- txdr[i].count = txdr->count; +- rxdr[i].count = rxdr->count; +- } ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ txdr[i].count = txdr->count; ++ for (i = 0; i < adapter->num_rx_queues; i++) ++ rxdr[i].count = rxdr->count; + + if(netif_running(adapter->netdev)) { + /* Try to get new resources before deleting old */ +@@ -950,8 +924,7 @@ iegbe_eeprom_test(struct iegbe_adapter * + + static irqreturn_t + iegbe_test_intr(int irq, +- void *data, +- struct pt_regs *regs) ++ void *data) + { + struct net_device *netdev = (struct net_device *) data; + struct iegbe_adapter *adapter = netdev_priv(netdev); +@@ -973,7 +946,7 @@ iegbe_intr_test(struct iegbe_adapter *ad + /* Hook up test interrupt handler just for this test */ + if(!request_irq(irq, &iegbe_test_intr, 0, netdev->name, netdev)) { + shared_int = FALSE; +- } else if(request_irq(irq, &iegbe_test_intr, SA_SHIRQ, ++ } else if(request_irq(irq, &iegbe_test_intr, IRQF_SHARED, + netdev->name, netdev)){ + *data = 1; + return -1; +@@ -1393,7 +1366,7 @@ iegbe_set_phy_loopback(struct iegbe_adap + * attempt this 10 times. + */ + while(iegbe_nonintegrated_phy_loopback(adapter) && +- count++ < 0xa) { }; ++ count++ < 0xa); + if(count < 0xb) { + return 0; + } +--- a/Embedded/src/GbE/iegbe.h ++++ b/Embedded/src/GbE/iegbe.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -21,7 +21,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -127,9 +127,12 @@ struct iegbe_adapter; + #define E1000_MIN_RXD 80 + #define E1000_MAX_82544_RXD 4096 + ++#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 + /* Supported Rx Buffer Sizes */ + #define E1000_RXBUFFER_128 128 /* Used for packet split */ + #define E1000_RXBUFFER_256 256 /* Used for packet split */ ++#define E1000_RXBUFFER_512 512 ++#define E1000_RXBUFFER_1024 1024 + #define E1000_RXBUFFER_2048 2048 + #define E1000_RXBUFFER_4096 4096 + #define E1000_RXBUFFER_8192 8192 +@@ -164,11 +167,9 @@ struct iegbe_adapter; + #define E1000_MASTER_SLAVE iegbe_ms_hw_default + #endif + +-#ifdef NETIF_F_HW_VLAN_TX +-#define E1000_MNG_VLAN_NONE -1 +-#endif ++#define E1000_MNG_VLAN_NONE (-1) + /* Number of packet split data buffers (not including the header buffer) */ +-#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1 ++#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) + + /* only works for sizes that are powers of 2 */ + #define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) +@@ -206,6 +207,7 @@ struct iegbe_tx_ring { + spinlock_t tx_lock; + uint16_t tdh; + uint16_t tdt; ++ boolean_t last_tx_tso; + uint64_t pkt; + }; + +@@ -228,6 +230,9 @@ struct iegbe_rx_ring { + struct iegbe_ps_page *ps_page; + struct iegbe_ps_page_dma *ps_page_dma; + ++ /* cpu for rx queue */ ++ int cpu; ++ + uint16_t rdh; + uint16_t rdt; + uint64_t pkt; +@@ -252,10 +257,8 @@ struct iegbe_adapter { + struct timer_list tx_fifo_stall_timer; + struct timer_list watchdog_timer; + struct timer_list phy_info_timer; +-#ifdef NETIF_F_HW_VLAN_TX + struct vlan_group *vlgrp; + uint16_t mng_vlan_id; +-#endif + uint32_t bd_number; + uint32_t rx_buffer_len; + uint32_t part_num; +@@ -265,8 +268,18 @@ struct iegbe_adapter { + uint16_t link_speed; + uint16_t link_duplex; + spinlock_t stats_lock; +- atomic_t irq_sem; +- struct work_struct tx_timeout_task; ++ spinlock_t tx_queue_lock; ++ unsigned int total_tx_bytes; ++ unsigned int total_tx_packets; ++ unsigned int total_rx_bytes; ++ unsigned int total_rx_packets; ++ /* Interrupt Throttle Rate */ ++ uint32_t itr; ++ uint32_t itr_setting; ++ uint16_t tx_itr; ++ uint16_t rx_itr; ++ ++ struct work_struct reset_task; + uint8_t fc_autoneg; + + #ifdef ETHTOOL_PHYS_ID +@@ -276,9 +289,8 @@ struct iegbe_adapter { + + /* TX */ + struct iegbe_tx_ring *tx_ring; /* One per active queue */ +-#ifdef CONFIG_E1000_MQ +- struct iegbe_tx_ring **cpu_tx_ring; /* per-cpu */ +-#endif ++ unsigned int restart_queue; ++ unsigned long tx_queue_len; + uint32_t txd_cmd; + uint32_t tx_int_delay; + uint32_t tx_abs_int_delay; +@@ -286,46 +298,33 @@ struct iegbe_adapter { + uint64_t gotcl_old; + uint64_t tpt_old; + uint64_t colc_old; ++ uint32_t tx_timeout_count; + uint32_t tx_fifo_head; + uint32_t tx_head_addr; + uint32_t tx_fifo_size; ++ uint8_t tx_timeout_factor; + atomic_t tx_fifo_stall; + boolean_t pcix_82544; + boolean_t detect_tx_hung; + + /* RX */ +-#ifdef CONFIG_E1000_NAPI +- boolean_t (*clean_rx) (struct iegbe_adapter *adapter, ++ bool (*clean_rx)(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do); +-#else +- boolean_t (*clean_rx) (struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif +- +-#ifdef IEGBE_GBE_WORKAROUND + void (*alloc_rx_buf) (struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring, +- int cleaned_count); +-#else +- void (*alloc_rx_buf) (struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif +- ++ struct iegbe_rx_ring *rx_ring, ++ int cleaned_count); + struct iegbe_rx_ring *rx_ring; /* One per active queue */ +-#ifdef CONFIG_E1000_NAPI ++ struct napi_struct napi; + struct net_device *polling_netdev; /* One per active queue */ +-#endif +-#ifdef CONFIG_E1000_MQ +- struct net_device **cpu_netdev; /* per-cpu */ +- struct call_async_data_struct rx_sched_call_data; +- int cpu_for_queue[4]; +-#endif +- int num_queues; ++ ++ int num_tx_queues; ++ int num_rx_queues; + + uint64_t hw_csum_err; + uint64_t hw_csum_good; + uint64_t rx_hdr_split; ++ uint32_t alloc_rx_buff_failed; + uint32_t rx_int_delay; + uint32_t rx_abs_int_delay; + boolean_t rx_csum; +@@ -334,8 +333,6 @@ struct iegbe_adapter { + uint64_t gorcl_old; + uint16_t rx_ps_bsize0; + +- /* Interrupt Throttle Rate */ +- uint32_t itr; + + /* OS defined structs */ + struct net_device *netdev; +@@ -378,7 +375,21 @@ struct iegbe_adapter { + #ifdef CONFIG_PCI_MSI + boolean_t have_msi; + #endif +-#define IEGBE_INTD_DISABLE 0x0400 ++ /* to not mess up cache alignment, always add to the bottom */ ++ boolean_t tso_force; ++ boolean_t smart_power_down; /* phy smart power down */ ++ boolean_t quad_port_a; ++ unsigned long flags; ++ uint32_t eeprom_wol; ++ int bars; ++ int need_ioport; + }; ++ ++enum iegbe_state_t { ++ __E1000_TESTING, ++ __E1000_RESETTING, ++ __E1000_DOWN ++}; ++#define IEGBE_INTD_DISABLE 0x0400 + #endif /* _IEGBE_H_ */ + +--- a/Embedded/src/GbE/iegbe_hw.c ++++ b/Embedded/src/GbE/iegbe_hw.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -2115,7 +2115,7 @@ iegbe_config_mac_to_phy(struct iegbe_hw + + ret_val = iegbe_oem_set_trans_gasket(hw); + if(ret_val){ +- return ret_val; ++ return ret_val; + } + ret_val = iegbe_oem_phy_is_full_duplex( + hw, (int *) &is_FullDuplex); +@@ -2164,7 +2164,7 @@ iegbe_config_mac_to_phy(struct iegbe_hw + } + /* Write the configured values back to the Device Control Reg. */ + E1000_WRITE_REG(hw, CTRL, ctrl); +- return E1000_SUCCESS; ++ return ret_val; + } + + /***************************************************************************** +@@ -2684,7 +2684,7 @@ iegbe_check_for_link(struct iegbe_hw *hw + + if(hw->autoneg_failed == 0) { + hw->autoneg_failed = 1; +- return 0; ++ return E1000_SUCCESS; + } + DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); + +@@ -5875,7 +5875,7 @@ iegbe_get_cable_length(struct iegbe_hw * + max_agc = cur_agc; + } + } +- ++ + /* This is to fix a Klockwork defect, that the array index might + * be out of bounds. 113 is table size */ + if (cur_agc < 0x71){ +--- a/Embedded/src/GbE/iegbe_hw.h ++++ b/Embedded/src/GbE/iegbe_hw.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -299,7 +299,7 @@ void iegbe_set_media_type(struct iegbe_h + /* Link Configuration */ + int32_t iegbe_setup_link(struct iegbe_hw *hw); + int32_t iegbe_phy_setup_autoneg(struct iegbe_hw *hw); +-void iegbe_config_collision_dist(struct iegbe_hw *hw); ++void iegbe_config_collision_dist(struct iegbe_hw *hw); + int32_t iegbe_config_fc_after_link_up(struct iegbe_hw *hw); + int32_t iegbe_check_for_link(struct iegbe_hw *hw); + int32_t iegbe_get_speed_and_duplex(struct iegbe_hw *hw, uint16_t * speed, uint16_t * duplex); +@@ -588,14 +588,6 @@ uint8_t iegbe_arc_subsystem_valid(struct + * o LSC = Link Status Change + */ + +-#ifdef IEGBE_GBE_WORKAROUND +-#define IMS_ENABLE_MASK ( \ +- E1000_IMS_RXT0 | \ +- E1000_IMS_TXQE | \ +- E1000_IMS_RXDMT0 | \ +- E1000_IMS_RXSEQ | \ +- E1000_IMS_LSC) +-#else + #define IMS_ENABLE_MASK ( \ + E1000_IMS_RXT0 | \ + E1000_IMS_TXDW | \ +@@ -606,8 +598,7 @@ uint8_t iegbe_arc_subsystem_valid(struct + E1000_ICR_PB | \ + E1000_ICR_CPP_TARGET | \ + E1000_ICR_CPP_MASTER | \ +- E1000_IMS_LSC) +-#endif ++ E1000_ICR_LSC) + + /* Number of high/low register pairs in the RAR. The RAR (Receive Address + * Registers) holds the directed and multicast addresses that we monitor. We +@@ -923,10 +914,15 @@ struct iegbe_ffvt_entry { + #define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ + #define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ + #define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ +-// Register conflict, does not exist for ICP_xxxx hardware +-// #define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ + #define E1000_CTRL_AUX 0x000E0 /* Aux Control -RW */ ++#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ + #define E1000_RCTL 0x00100 /* RX Control - RW */ ++#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */ ++#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */ ++#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */ ++#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */ ++#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */ ++#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */ + #define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ + #define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ + #define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ +@@ -1282,8 +1278,6 @@ struct iegbe_ffvt_entry { + #define E1000_82542_FFMT E1000_FFMT + #define E1000_82542_FFVT E1000_FFVT + #define E1000_82542_HOST_IF E1000_HOST_IF +-// Register conflict with ICP_xxxx hardware, no IAM +-// #define E1000_82542_IAM E1000_IAM + #define E1000_82542_EEMNGCTL E1000_EEMNGCTL + #define E1000_82542_PSRCTL E1000_PSRCTL + #define E1000_82542_RAID E1000_RAID +@@ -1329,6 +1323,7 @@ struct iegbe_hw_stats { + uint64_t algnerrc; + uint64_t symerrs; + uint64_t rxerrc; ++ uint64_t txerrc; + uint64_t mpc; + uint64_t scc; + uint64_t ecol; +@@ -1363,6 +1358,7 @@ struct iegbe_hw_stats { + uint64_t ruc; + uint64_t rfc; + uint64_t roc; ++ uint64_t rlerrc; + uint64_t rjc; + uint64_t mgprc; + uint64_t mgpdc; +@@ -1392,19 +1388,6 @@ struct iegbe_hw_stats { + uint64_t ictxqmtc; + uint64_t icrxdmtc; + uint64_t icrxoc; +-#ifdef IEGBE_GBE_WORKAROUND +- u64 txqec; +- u64 tx_next_to_clean; +- u64 tx_next_to_use; +- u64 cc_gt_num_rx; +- u64 tx_hnet; +- u64 tx_hnentu; +- u64 num_tx_queues; +- +- u64 num_rx_buf_alloc; +- u64 rx_next_to_clean; +- u64 rx_next_to_use; +-#endif + }; + + /* Structure containing variables used by the shared code (iegbe_hw.c) */ +@@ -1484,6 +1467,7 @@ struct iegbe_hw { + boolean_t ifs_params_forced; + boolean_t in_ifs_mode; + boolean_t mng_reg_access_disabled; ++ boolean_t rx_needs_kicking; + boolean_t icp_xxxx_is_link_up; + }; + +@@ -2358,17 +2342,23 @@ struct iegbe_host_command_info { + #define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF + #define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00 + #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000 ++#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 ++#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 + + /* PBA constants */ ++#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */ + #define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */ + #define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ ++#define E1000_PBA_20K 0x0014 + #define E1000_PBA_22K 0x0016 + #define E1000_PBA_24K 0x0018 + #define E1000_PBA_30K 0x001E + #define E1000_PBA_32K 0x0020 ++#define E1000_PBA_34K 0x0022 + #define E1000_PBA_38K 0x0026 + #define E1000_PBA_40K 0x0028 + #define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ ++#define E1000_PBS_16K E1000_PBA_16K + + /* Flow Control Constants */ + #define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 +@@ -2899,7 +2889,7 @@ struct iegbe_host_command_info { + #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID + #define M88E1011_I_REV_4 0x04 + #define M88E1111_I_PHY_ID 0x01410CC2 +-#define M88E1141_E_PHY_ID 0x01410CD4 ++#define M88E1141_E_PHY_ID 0x01410CD0 + #define L1LXT971A_PHY_ID 0x001378E0 + + /* Miscellaneous PHY bit definitions. */ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -42,103 +42,15 @@ GPL LICENSE SUMMARY + + #include "iegbe.h" + #include "gcu_if.h" +- +-/* Change Log +- * 6.0.58 4/20/05 +- * o iegbe_set_spd_dplx tests for compatible speed/duplex specification +- * for fiber adapters +- * 6.0.57 4/19/05 +- * o Added code to fix register test failure for devices >= 82571 +- * +- * 6.0.52 3/15/05 +- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent +- * calls, one from mii_ioctl and other from within update_stats while +- * processing MIIREG ioctl. +- * +- * 6.1.2 4/13/05 +- * o Fixed ethtool diagnostics +- * o Enabled flow control to take default eeprom settings +- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent +- * calls, one from mii_ioctl and other from within update_stats while processing +- * MIIREG ioctl. +- * 6.0.55 3/23/05 +- * o Support for MODULE_VERSION +- * o Fix APM setting for 82544 based adapters +- * 6.0.54 3/26/05 +- * o Added a timer to expire packets that were deferred for cleanup +- * 6.0.52 3/15/05 +- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent +- * calls, one from mii_ioctl and other from within update_stats while +- * processing MIIREG ioctl. +- * 6.0.47 3/2/05 +- * o Added enhanced functionality to the loopback diags to wrap the +- * descriptor rings +- * o Added manageability vlan filtering workaround. +- * +- * 6.0.44+ 2/15/05 +- * o Added code to handle raw packet based DHCP packets +- * o Added code to fix the errata 10 buffer overflow issue +- * o Sync up with WR01-05 +- * o applied Anton's patch to resolve tx hang in hardware +- * o iegbe timeouts with early writeback patch +- * o Removed Queensport IDs +- * o fixed driver panic if MAC receives a bad large packets when packet +- * split is enabled +- * o Applied Andrew Mortons patch - iegbe stops working after resume +- * 5.2.29 12/24/03 +- * o Bug fix: Endianess issue causing ethtool diags to fail on ppc. +- * o Bug fix: Use pdev->irq instead of netdev->irq for MSI support. +- * o Report driver message on user override of InterruptThrottleRate module +- * parameter. +- * o Bug fix: Change I/O address storage from uint32_t to unsigned long. +- * o Feature: Added ethtool RINGPARAM support. +- * o Feature: Added netpoll support. +- * o Bug fix: Race between Tx queue and Tx clean fixed with a spin lock. +- * o Bug fix: Allow 1000/Full setting for autoneg param for fiber connections. +- * Jon D Mason [jonmason@us.ibm.com]. +- * +- * 5.2.22 10/15/03 +- * o Bug fix: SERDES devices might be connected to a back-plane switch that +- * doesn't support auto-neg, so add the capability to force 1000/Full. +- * Also, since forcing 1000/Full, sample RxSynchronize bit to detect link +- * state. +- * o Bug fix: Flow control settings for hi/lo watermark didn't consider +- * changes in the RX FIFO size, which could occur with Jumbo Frames or with +- * the reduced FIFO in 82547. +- * o Bug fix: Better propagation of error codes. +- * [Janice Girouard (janiceg -a-t- us.ibm.com)] +- * o Bug fix: hang under heavy Tx stress when running out of Tx descriptors; +- * wasn't clearing context descriptor when backing out of send because of +- * no-resource condition. +- * o Bug fix: check netif_running in dev->poll so we don't have to hang in +- * dev->close until all polls are finished. [Rober Olsson +- * (robert.olsson@data.slu.se)]. +- * o Revert TxDescriptor ring size back to 256 since change to 1024 wasn't +- * accepted into the kernel. +- * +- * 5.2.16 8/8/03 +- */ +- +-#ifdef IEGBE_GBE_WORKAROUND +-#define IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS 1 +-#endif ++#include ++#include + + char iegbe_driver_name[] = "iegbe"; + char iegbe_driver_string[] = "Gigabit Ethernet Controller Driver"; +-#ifndef CONFIG_E1000_NAPI +-#define DRIVERNAPI +-#else +-#define DRIVERNAPI "-NAPI" +-#endif +-#define DRV_VERSION "0.8.0"DRIVERNAPI ++#define DRV_VERSION "1.0.0-K28-NAPI" + char iegbe_driver_version[] = DRV_VERSION; +-char iegbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; ++char iegbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation."; + +-#define E1000_FIFO_HDR 0x10 +-#define E1000_82547_PAD_LEN 0x3E0 +-#define MINIMUM_DHCP_PACKET_SIZE 282 +-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) +-#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 + + /* iegbe_pci_tbl - PCI Device ID Table + * +@@ -148,95 +60,48 @@ char iegbe_copyright[] = "Copyright (c) + * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} + */ + static struct pci_device_id iegbe_pci_tbl[] = { +-/* INTEL_E1000_ETHERNET_DEVICE(0x1000), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1001), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1004), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1008), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1009), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100C), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100D), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100F), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1010), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1011), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1012), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1013), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1014), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1015), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1016), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1017), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1018), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1019), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x101A), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x101D), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x101E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1026), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1027), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1028), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x105E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x105F), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1060), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1075), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1076), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1077), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1078), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1079), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107A), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107B), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107C), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107D), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107F), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x108A), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x108B), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x108C), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x109A), */ +- INTEL_E1000_ETHERNET_DEVICE(0x5040), +- INTEL_E1000_ETHERNET_DEVICE(0x5041), +- INTEL_E1000_ETHERNET_DEVICE(0x5042), +- INTEL_E1000_ETHERNET_DEVICE(0x5043), +- INTEL_E1000_ETHERNET_DEVICE(0x5044), +- INTEL_E1000_ETHERNET_DEVICE(0x5045), +- INTEL_E1000_ETHERNET_DEVICE(0x5046), +- INTEL_E1000_ETHERNET_DEVICE(0x5047), +- INTEL_E1000_ETHERNET_DEVICE(0x5048), +- INTEL_E1000_ETHERNET_DEVICE(0x5049), +- INTEL_E1000_ETHERNET_DEVICE(0x504A), +- INTEL_E1000_ETHERNET_DEVICE(0x504B), +- /* required last entry */ ++ INTEL_E1000_ETHERNET_DEVICE(0x5040), ++ INTEL_E1000_ETHERNET_DEVICE(0x5041), ++ INTEL_E1000_ETHERNET_DEVICE(0x5042), ++ INTEL_E1000_ETHERNET_DEVICE(0x5043), ++ INTEL_E1000_ETHERNET_DEVICE(0x5044), ++ INTEL_E1000_ETHERNET_DEVICE(0x5045), ++ INTEL_E1000_ETHERNET_DEVICE(0x5046), ++ INTEL_E1000_ETHERNET_DEVICE(0x5047), ++ INTEL_E1000_ETHERNET_DEVICE(0x5048), ++ INTEL_E1000_ETHERNET_DEVICE(0x5049), ++ INTEL_E1000_ETHERNET_DEVICE(0x504A), ++ INTEL_E1000_ETHERNET_DEVICE(0x504B), ++ /* required last entry */ + {0,} + }; + + MODULE_DEVICE_TABLE(pci, iegbe_pci_tbl); + +-DEFINE_SPINLOCK(print_lock); + + int iegbe_up(struct iegbe_adapter *adapter); + void iegbe_down(struct iegbe_adapter *adapter); ++void iegbe_reinit_locked(struct iegbe_adapter *adapter); + void iegbe_reset(struct iegbe_adapter *adapter); + int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, uint16_t spddplx); + int iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter); + int iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter); + void iegbe_free_all_tx_resources(struct iegbe_adapter *adapter); + void iegbe_free_all_rx_resources(struct iegbe_adapter *adapter); +-int iegbe_setup_tx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *txdr); +-int iegbe_setup_rx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rxdr); +-void iegbe_free_tx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring); +-void iegbe_free_rx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring); + void iegbe_update_stats(struct iegbe_adapter *adapter); +- + static int iegbe_init_module(void); + static void iegbe_exit_module(void); + static int iegbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent); + static void __devexit iegbe_remove(struct pci_dev *pdev); + static int iegbe_alloc_queues(struct iegbe_adapter *adapter); +-#ifdef CONFIG_E1000_MQ +-static void iegbe_setup_queue_mapping(struct iegbe_adapter *adapter); +-#endif + static int iegbe_sw_init(struct iegbe_adapter *adapter); + static int iegbe_open(struct net_device *netdev); + static int iegbe_close(struct net_device *netdev); +@@ -249,7 +114,8 @@ static void iegbe_clean_tx_ring(struct i + struct iegbe_tx_ring *tx_ring); + static void iegbe_clean_rx_ring(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring); +-static void iegbe_set_multi(struct net_device *netdev); ++ ++static void iegbe_set_rx_mode(struct net_device *netdev); + static void iegbe_update_phy_info(unsigned long data); + static void iegbe_watchdog(unsigned long data); + static void iegbe_82547_tx_fifo_stall(unsigned long data); +@@ -257,66 +123,46 @@ static int iegbe_xmit_frame(struct sk_bu + static struct net_device_stats * iegbe_get_stats(struct net_device *netdev); + static int iegbe_change_mtu(struct net_device *netdev, int new_mtu); + static int iegbe_set_mac(struct net_device *netdev, void *p); +-static irqreturn_t iegbe_intr(int irq, void *data, struct pt_regs *regs); ++static irqreturn_t iegbe_intr(int irq, void *data); + +-void iegbe_tasklet(unsigned long); ++static irqreturn_t iegbe_intr_msi(int irq, void *data); + +-#ifndef IEGBE_GBE_WORKAROUND +-static boolean_t iegbe_clean_tx_irq(struct iegbe_adapter *adapter, ++static bool iegbe_clean_tx_irq(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring); +-#endif +- +-#ifdef CONFIG_E1000_NAPI +-static int iegbe_clean(struct net_device *poll_dev, int *budget); +-static boolean_t iegbe_clean_rx_irq(struct iegbe_adapter *adapter, ++static int iegbe_clean(struct napi_struct *napi, int budget); ++static bool iegbe_clean_rx_irq(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do); +-static boolean_t iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, ++static bool iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do); +-#else +-static boolean_t iegbe_clean_rx_irq(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-static boolean_t iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif + +-#ifdef IEGBE_GBE_WORKAROUND ++ + static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count); + static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count); +-#else +-static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif ++ + + static int iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); +-#ifdef SIOCGMIIPHY + static int iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, +- int cmd); +-#endif ++ int cmd); + void set_ethtool_ops(struct net_device *netdev); + extern int ethtool_ioctl(struct ifreq *ifr); + static void iegbe_enter_82542_rst(struct iegbe_adapter *adapter); + static void iegbe_leave_82542_rst(struct iegbe_adapter *adapter); + static void iegbe_tx_timeout(struct net_device *dev); +-static void iegbe_tx_timeout_task(struct net_device *dev); ++static void iegbe_reset_task(struct work_struct *work); + static void iegbe_smartspeed(struct iegbe_adapter *adapter); + static inline int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, +- struct sk_buff *skb); ++ struct sk_buff *skb); + +-#ifdef NETIF_F_HW_VLAN_TX +-static void iegbe_vlan_rx_register(struct net_device *netdev, +- struct vlan_group *grp); ++static void iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); + static void iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); + static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); + static void iegbe_restore_vlan(struct iegbe_adapter *adapter); +-#endif + + static int iegbe_notify_reboot(struct notifier_block *, + unsigned long event, +@@ -331,15 +177,17 @@ static int iegbe_resume(struct pci_dev * + static void iegbe_netpoll (struct net_device *netdev); + #endif + +-#ifdef CONFIG_E1000_MQ +-/* for multiple Rx queues */ ++#define COPYBREAK_DEFAULT 256 ++static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT; ++module_param(copybreak, uint, 0644); ++MODULE_PARM_DESC(copybreak, ++ "Maximum size of packet that is copied to a new buffer on receive"); + void iegbe_rx_schedule(void *data); +-#endif + + struct notifier_block iegbe_notifier_reboot = { +- .notifier_call = iegbe_notify_reboot, +- .next = NULL, +- .priority = 0 ++ .notifier_call = iegbe_notify_reboot, ++ .next = NULL, ++ .priority = 0 + }; + + /* Exported from other modules */ +@@ -347,14 +195,14 @@ struct notifier_block iegbe_notifier_reb + extern void iegbe_check_options(struct iegbe_adapter *adapter); + + static struct pci_driver iegbe_driver = { +- .name = iegbe_driver_name, +- .id_table = iegbe_pci_tbl, +- .probe = iegbe_probe, +- .remove = __devexit_p(iegbe_remove), +- /* Power Managment Hooks */ ++ .name = iegbe_driver_name, ++ .id_table = iegbe_pci_tbl, ++ .probe = iegbe_probe, ++ .remove = __devexit_p(iegbe_remove), ++ /* Power Managment Hooks */ + #ifdef CONFIG_PM +- .suspend = iegbe_suspend, +- .resume = iegbe_resume ++ .suspend = iegbe_suspend, ++ .resume = iegbe_resume + #endif + }; + +@@ -364,46 +212,17 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); + + static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE; +-module_param(debug, int, 0); ++module_param(debug, int, 0x0); + MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +-static uint8_t gcu_suspend = 0; +-static uint8_t gcu_resume = 0; ++static uint8_t gcu_suspend = 0x0; ++static uint8_t gcu_resume = 0x0; + struct pci_dev *gcu = NULL; + +-unsigned long tasklet_data; +-DECLARE_TASKLET(iegbe_reset_tasklet, iegbe_tasklet, (unsigned long) &tasklet_data); + + /** + * iegbe_iegbe_tasklet -* + **/ +-void iegbe_tasklet(unsigned long data) +-{ +- char* err_msg = "TEST"; +- uint32_t *icr = (uint32_t*) data; +- uint32_t gbe = *icr & 0x000000FF; +- if( *icr & E1000_ICR_RX_DESC_FIFO_PAR) { /* 21 */ +- err_msg = "DMA Transmit Descriptor 2-bit ECC Error!"; +- } +- if( *icr & E1000_ICR_TX_DESC_FIFO_PAR) { /* 20 */ +- err_msg = "DMA Receive Descriptor 2-bit ECC Error!"; +- } +- if( *icr & E1000_ICR_PB) { /* 23 */ +- err_msg = "DMA Packet Buffer 2-bit ECC Error!"; +- } +- if( *icr & E1000_ICR_CPP_TARGET) { /* 27 */ +- err_msg = "Statistic Register ECC Error!"; +- } +- if( *icr & E1000_ICR_CPP_MASTER) { +- err_msg = "CPP Error!"; +- } +- spin_lock(&print_lock); +- printk("IEGBE%d: System Reset due to: %s\n", gbe, err_msg); +- dump_stack(); +- spin_unlock(&print_lock); +- panic(err_msg); +- return; +-} + /** + * iegbe_init_module - Driver Registration Routine + * +@@ -411,21 +230,24 @@ void iegbe_tasklet(unsigned long data) + * loaded. All it does is register with the PCI subsystem. + **/ + +-static int __init +-iegbe_init_module(void) ++static int __init iegbe_init_module(void) + { +- int ret; ++ int ret; + + printk(KERN_INFO "%s - version %s\n", +- iegbe_driver_string, iegbe_driver_version); ++ iegbe_driver_string, iegbe_driver_version); + +- printk(KERN_INFO "%s\n", iegbe_copyright); ++ printk(KERN_INFO "%s\n", iegbe_copyright); + +- ret = pci_module_init(&iegbe_driver); +- if(ret >= 0) { +- register_reboot_notifier(&iegbe_notifier_reboot); +- } +- return ret; ++ ret = pci_register_driver(&iegbe_driver); ++ if (copybreak != COPYBREAK_DEFAULT) { ++ if (copybreak == 0) ++ printk(KERN_INFO "iegbe: copybreak disabled\n"); ++ else ++ printk(KERN_INFO "iegbe: copybreak enabled for " ++ "packets <= %u bytes\n", copybreak); ++ } ++ return ret; + } + + module_init(iegbe_init_module); +@@ -437,29 +259,51 @@ module_init(iegbe_init_module); + * from memory. + **/ + +-static void __exit +-iegbe_exit_module(void) ++static void __exit iegbe_exit_module(void) + { +- +- unregister_reboot_notifier(&iegbe_notifier_reboot); +- pci_unregister_driver(&iegbe_driver); ++ pci_unregister_driver(&iegbe_driver); + } + + module_exit(iegbe_exit_module); + ++static int iegbe_request_irq(struct iegbe_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ irq_handler_t handler = iegbe_intr; ++ int irq_flags = IRQF_SHARED; ++ int err; ++ adapter->have_msi = !pci_enable_msi(adapter->pdev); ++ if (adapter->have_msi) { ++ handler = iegbe_intr_msi; ++ irq_flags = 0; ++ } ++ err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, ++ netdev); ++ if (err) { ++ if (adapter->have_msi) ++ pci_disable_msi(adapter->pdev); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate interrupt Error: %d\n", err); ++ } ++ return err; ++} ++static void iegbe_free_irq(struct iegbe_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ free_irq(adapter->pdev->irq, netdev); ++ if (adapter->have_msi) ++ pci_disable_msi(adapter->pdev); ++} + /** + * iegbe_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ + +-static inline void +-iegbe_irq_disable(struct iegbe_adapter *adapter) ++static void iegbe_irq_disable(struct iegbe_adapter *adapter) + { +- +- atomic_inc(&adapter->irq_sem); +- E1000_WRITE_REG(&adapter->hw, IMC, ~0); +- E1000_WRITE_FLUSH(&adapter->hw); +- synchronize_irq(adapter->pdev->irq); ++ E1000_WRITE_REG(&adapter->hw, IMC, ~0); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ synchronize_irq(adapter->pdev->irq); + } + + /** +@@ -470,244 +314,414 @@ iegbe_irq_disable(struct iegbe_adapter * + static inline void + iegbe_irq_enable(struct iegbe_adapter *adapter) + { +- +- if(likely(atomic_dec_and_test(&adapter->irq_sem))) { +- E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); +- E1000_WRITE_FLUSH(&adapter->hw); +- } ++ E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); ++ E1000_WRITE_FLUSH(&adapter->hw); + } +-#ifdef NETIF_F_HW_VLAN_TX +-void +-iegbe_update_mng_vlan(struct iegbe_adapter *adapter) +-{ +- struct net_device *netdev = adapter->netdev; +- uint16_t vid = adapter->hw.mng_cookie.vlan_id; +- uint16_t old_vid = adapter->mng_vlan_id; + +- if(adapter->vlgrp) { +- if(!adapter->vlgrp->vlan_devices[vid]) { +- if(adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { +- iegbe_vlan_rx_add_vid(netdev, vid); +- adapter->mng_vlan_id = vid; +- } else { +- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- } +- if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) && +- (vid != old_vid) && +- !adapter->vlgrp->vlan_devices[old_vid]) { +- iegbe_vlan_rx_kill_vid(netdev, old_vid); +- } +- } +-} ++static void iegbe_update_mng_vlan(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ u16 vid = hw->mng_cookie.vlan_id; ++ u16 old_vid = adapter->mng_vlan_id; ++ if (adapter->vlgrp) { ++ if (!vlan_group_get_device(adapter->vlgrp, vid)) { ++ if (hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { ++ iegbe_vlan_rx_add_vid(netdev, vid); ++ adapter->mng_vlan_id = vid; ++ } else ++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; ++ ++ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && ++ (vid != old_vid) && ++ !vlan_group_get_device(adapter->vlgrp, old_vid)) ++ iegbe_vlan_rx_kill_vid(netdev, old_vid); ++ } else ++ adapter->mng_vlan_id = vid; ++ } + } +-#endif + +-int +-iegbe_up(struct iegbe_adapter *adapter) ++/** ++ * iegbe_configure - configure the hardware for RX and TX ++ * @adapter = private board structure ++ **/ ++static void iegbe_configure(struct iegbe_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +- int i, err; +- uint16_t pci_cmd; +- +- /* hardware has been reset, we need to reload some things */ +- +- /* Reset the PHY if it was previously powered down */ +- if(adapter->hw.media_type == iegbe_media_type_copper +- || (adapter->hw.media_type == iegbe_media_type_oem +- && iegbe_oem_phy_is_copper(&adapter->hw))) { +- uint16_t mii_reg; +- iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); +- if(mii_reg & MII_CR_POWER_DOWN){ +- iegbe_phy_reset(&adapter->hw); +- } +- } ++ int i; + +- iegbe_set_multi(netdev); ++ iegbe_set_rx_mode(netdev); + +-#ifdef NETIF_F_HW_VLAN_TX + iegbe_restore_vlan(adapter); +-#endif + + iegbe_configure_tx(adapter); + iegbe_setup_rctl(adapter); + iegbe_configure_rx(adapter); ++ /* call E1000_DESC_UNUSED which always leaves ++ * at least 1 descriptor unused to make sure ++ * next_to_use != next_to_clean */ ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ struct iegbe_rx_ring *ring = &adapter->rx_ring[i]; ++ adapter->alloc_rx_buf(adapter, ring, ++ E1000_DESC_UNUSED(ring)); ++ } + +-#ifdef IEGBE_GBE_WORKAROUND +- for (i = 0; i < adapter->num_queues; i++) +- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i], +- IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS + 1); +-#else +- for (i = 0; i < adapter->num_queues; i++) +- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]); +-#endif ++ adapter->tx_queue_len = netdev->tx_queue_len; ++} + +-#ifdef CONFIG_PCI_MSI +- if(adapter->hw.mac_type > iegbe_82547_rev_2 +- || adapter->hw.mac_type == iegbe_icp_xxxx) { +- adapter->have_msi = TRUE; +- if((err = pci_enable_msi(adapter->pdev))) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate MSI interrupt Error: %d\n", err); +- adapter->have_msi = FALSE; +- } +- } +- pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); +- pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd | IEGBE_INTD_DISABLE); ++int iegbe_up(struct iegbe_adapter *adapter) ++{ ++ /* hardware has been reset, we need to reload some things */ ++ iegbe_configure(adapter); + +-#endif +- if((err = request_irq(adapter->pdev->irq, &iegbe_intr, +- SA_SHIRQ | SA_SAMPLE_RANDOM, +- netdev->name, netdev))) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate interrupt Error: %d\n", err); +- return err; +- } ++ clear_bit(__E1000_DOWN, &adapter->flags); + +- mod_timer(&adapter->watchdog_timer, jiffies); ++ napi_enable(&adapter->napi); + +-#ifdef CONFIG_E1000_NAPI +- netif_poll_enable(netdev); +-#endif + iegbe_irq_enable(adapter); + ++ adapter->hw.get_link_status = 0x1; + return 0; + } + +-void +-iegbe_down(struct iegbe_adapter *adapter) +-{ +- struct net_device *netdev = adapter->netdev; +- +- iegbe_irq_disable(adapter); +-#ifdef CONFIG_E1000_MQ +- while (atomic_read(&adapter->rx_sched_call_data.count) != 0) { }; +-#endif +- free_irq(adapter->pdev->irq, netdev); +-#ifdef CONFIG_PCI_MSI +- if((adapter->hw.mac_type > iegbe_82547_rev_2 +- || adapter->hw.mac_type == iegbe_icp_xxxx) +- && adapter->have_msi == TRUE) { +- pci_disable_msi(adapter->pdev); +- } +-#endif +- del_timer_sync(&adapter->tx_fifo_stall_timer); +- del_timer_sync(&adapter->watchdog_timer); +- del_timer_sync(&adapter->phy_info_timer); ++/** ++ * iegbe_power_up_phy - restore link in case the phy was powered down ++ * @adapter: address of board private structure ++ * ++ * The phy may be powered down to save power and turn off link when the ++ * driver is unloaded and wake on lan is not enabled (among others) ++ * *** this routine MUST be followed by a call to iegbe_reset *** ++ * ++ **/ + +-#ifdef CONFIG_E1000_NAPI +- netif_poll_disable(netdev); +-#endif +- adapter->link_speed = 0; +- adapter->link_duplex = 0; +- netif_carrier_off(netdev); +- netif_stop_queue(netdev); ++void iegbe_power_up_phy(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ u16 mii_reg = 0; + +- iegbe_reset(adapter); +- iegbe_clean_all_tx_rings(adapter); +- iegbe_clean_all_rx_rings(adapter); ++ /* Just clear the power down bit to wake the phy back up */ ++ if (hw->media_type == iegbe_media_type_copper) { ++ /* according to the manual, the phy will retain its ++ * settings across a power-down/up cycle */ ++ iegbe_read_phy_reg(hw, PHY_CTRL, &mii_reg); ++ mii_reg &= ~MII_CR_POWER_DOWN; ++ iegbe_write_phy_reg(hw, PHY_CTRL, mii_reg); ++ } ++} + +- /* If WoL is not enabled and management mode is not IAMT +- * or if WoL is not enabled and OEM PHY is copper based, +- * power down the PHY so no link is implied when interface is down */ +- if(!adapter->wol +- && ((adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.media_type == iegbe_media_type_copper +- && !iegbe_check_mng_mode(&adapter->hw) +- && !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) +- || (adapter->hw.media_type == iegbe_media_type_oem +- && iegbe_oem_phy_is_copper(&adapter->hw)))){ ++static void iegbe_power_down_phy(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; + +- uint16_t mii_reg; +- iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); ++ /* Power down the PHY so no link is implied when interface is down * ++ * The PHY cannot be powered down if any of the following is true * ++ * (a) WoL is enabled ++ * (b) AMT is active ++ * (c) SoL/IDER session is active */ ++ if (!adapter->wol && hw->mac_type >= iegbe_82540 && ++ hw->media_type == iegbe_media_type_copper) { ++ u16 mii_reg = 0; ++ ++ switch (hw->mac_type) { ++ case iegbe_82540: ++ case iegbe_82545: ++ case iegbe_82545_rev_3: ++ case iegbe_82546: ++ case iegbe_82546_rev_3: ++ case iegbe_82541: ++ case iegbe_82541_rev_2: ++ case iegbe_82547: ++ case iegbe_82547_rev_2: ++ if (E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) ++ goto out; ++ break; ++ case iegbe_82571: ++ case iegbe_82572: ++ case iegbe_82573: ++ if (iegbe_check_mng_mode(hw) || ++ iegbe_check_phy_reset_block(hw)) ++ goto out; ++ break; ++ default: ++ goto out; ++ } ++ iegbe_read_phy_reg(hw, PHY_CTRL, &mii_reg); + mii_reg |= MII_CR_POWER_DOWN; +- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg); ++ iegbe_write_phy_reg(hw, PHY_CTRL, mii_reg); + mdelay(1); + } ++out: ++ return; + } + +-void +-iegbe_reset(struct iegbe_adapter *adapter) ++void iegbe_down(struct iegbe_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- uint32_t pba, manc; +- uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF; +- uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF; ++ struct net_device *netdev = adapter->netdev; + ++ /* signal that we're down so the interrupt handler does not ++ * reschedule our watchdog timer */ ++ set_bit(__E1000_DOWN, &adapter->flags); + +- /* Repartition Pba for greater than 9k mtu +- * To take effect CTRL.RST is required. +- */ ++ napi_disable(&adapter->napi); + +- switch (adapter->hw.mac_type) { +- case iegbe_82547: +- case iegbe_82547_rev_2: +- pba = E1000_PBA_30K; +- break; +- case iegbe_82571: +- case iegbe_82572: +- pba = E1000_PBA_38K; +- break; +- case iegbe_82573: +- pba = E1000_PBA_12K; ++ iegbe_irq_disable(adapter); ++ ++ del_timer_sync(&adapter->tx_fifo_stall_timer); ++ del_timer_sync(&adapter->watchdog_timer); ++ del_timer_sync(&adapter->phy_info_timer); ++ ++ netdev->tx_queue_len = adapter->tx_queue_len; ++ adapter->link_speed = 0; ++ adapter->link_duplex = 0; ++ netif_carrier_off(netdev); ++ netif_stop_queue(netdev); ++ ++ iegbe_reset(adapter); ++ iegbe_clean_all_tx_rings(adapter); ++ iegbe_clean_all_rx_rings(adapter); ++} ++void iegbe_reinit_locked(struct iegbe_adapter *adapter) ++{ ++ WARN_ON(in_interrupt()); ++ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) ++ msleep(1); ++ iegbe_down(adapter); ++ iegbe_up(adapter); ++ clear_bit(__E1000_RESETTING, &adapter->flags); ++} ++ ++void iegbe_reset(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 pba = 0, tx_space, min_tx_space, min_rx_space; ++ u16 fc_high_water_mark = E1000_FC_HIGH_DIFF; ++ bool legacy_pba_adjust = false; ++ ++ /* Repartition Pba for greater than 9k mtu ++ * To take effect CTRL.RST is required. ++ */ ++ ++ switch (hw->mac_type) { ++ case iegbe_82542_rev2_0: ++ case iegbe_82542_rev2_1: ++ case iegbe_82543: ++ case iegbe_82544: ++ case iegbe_82540: ++ case iegbe_82541: ++ case iegbe_82541_rev_2: ++ case iegbe_icp_xxxx: ++ legacy_pba_adjust = true; ++ pba = E1000_PBA_48K; + break; +- default: ++ case iegbe_82545: ++ case iegbe_82545_rev_3: ++ case iegbe_82546: ++ case iegbe_82546_rev_3: + pba = E1000_PBA_48K; + break; +- } ++ case iegbe_82547: ++ case iegbe_82573: ++ case iegbe_82547_rev_2: ++ legacy_pba_adjust = true; ++ pba = E1000_PBA_30K; ++ break; ++ case iegbe_82571: ++ case iegbe_82572: ++ case iegbe_undefined: ++ case iegbe_num_macs: ++ break; ++ } ++ ++ if (legacy_pba_adjust) { ++ if (adapter->netdev->mtu > E1000_RXBUFFER_8192) ++ pba -= 8; /* allocate more FIFO for Tx */ ++ /* send an XOFF when there is enough space in the ++ * Rx FIFO to hold one extra full size Rx packet ++ */ + +- if((adapter->hw.mac_type != iegbe_82573) && +- (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) { +- pba -= 0x8; /* allocate more FIFO for Tx */ +- /* send an XOFF when there is enough space in the +- * Rx FIFO to hold one extra full size Rx packet +- */ +- fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE + +- ETHERNET_FCS_SIZE + 0x1; +- fc_low_water_mark = fc_high_water_mark + 0x8; +- } + ++ if (hw->mac_type == iegbe_82547) { ++ adapter->tx_fifo_head = 0; ++ adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; ++ adapter->tx_fifo_size = ++ (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; ++ atomic_set(&adapter->tx_fifo_stall, 0); ++ } ++ } else if (hw->max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) { ++ E1000_WRITE_REG(&adapter->hw, PBA, pba); ++ ++ /* To maintain wire speed transmits, the Tx FIFO should be ++ * large enough to accomodate two full transmit packets, ++ * rounded up to the next 1KB and expressed in KB. Likewise, ++ * the Rx FIFO should be large enough to accomodate at least ++ * one full receive packet and is similarly rounded up and ++ * expressed in KB. */ ++ pba = E1000_READ_REG(&adapter->hw, PBA); ++ /* upper 16 bits has Tx packet buffer allocation size in KB */ ++ tx_space = pba >> 16; ++ /* lower 16 bits has Rx packet buffer allocation size in KB */ ++ pba &= 0xffff; ++ /* don't include ethernet FCS because hardware appends/strips */ ++ min_rx_space = adapter->netdev->mtu + ENET_HEADER_SIZE + ++ VLAN_TAG_SIZE; ++ min_tx_space = min_rx_space; ++ min_tx_space *= 2; ++ min_tx_space = ALIGN(min_tx_space, 1024); ++ min_tx_space >>= 10; ++ min_rx_space = ALIGN(min_rx_space, 1024); ++ min_rx_space >>= 10; ++ ++ /* If current Tx allocation is less than the min Tx FIFO size, ++ * and the min Tx FIFO size is less than the current Rx FIFO ++ * allocation, take space away from current Rx allocation */ ++ if (tx_space < min_tx_space && ++ ((min_tx_space - tx_space) < pba)) { ++ pba = pba - (min_tx_space - tx_space); ++ ++ /* PCI/PCIx hardware has PBA alignment constraints */ ++ switch (hw->mac_type) { ++ case iegbe_82545 ... iegbe_82546_rev_3: ++ pba &= ~(E1000_PBA_8K - 1); ++ break; ++ default: ++ break; ++ } + +- if(adapter->hw.mac_type == iegbe_82547) { +- adapter->tx_fifo_head = 0; +- adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; +- adapter->tx_fifo_size = +- (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; +- atomic_set(&adapter->tx_fifo_stall, 0); ++ /* if short on rx space, rx wins and must trump tx ++ * adjustment or use Early Receive if available */ ++ if (pba < min_rx_space) { ++ switch (hw->mac_type) { ++ case iegbe_82573: ++ /* ERT enabled in iegbe_configure_rx */ ++ break; ++ default: ++ pba = min_rx_space; ++ break; ++ } ++ } ++ } + } + + E1000_WRITE_REG(&adapter->hw, PBA, pba); + + /* flow control settings */ +- adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) - +- fc_high_water_mark; +- adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) - +- fc_low_water_mark; +- adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; +- adapter->hw.fc_send_xon = 1; +- adapter->hw.fc = adapter->hw.original_fc; ++ /* Set the FC high water mark to 90% of the FIFO size. ++ * Required to clear last 3 LSB */ ++ fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8; ++ /* We can't use 90% on small FIFOs because the remainder ++ * would be less than 1 full frame. In this case, we size ++ * it to allow at least a full frame above the high water ++ * mark. */ ++ if (pba < E1000_PBA_16K) ++ fc_high_water_mark = (pba * 1024) - 1600; ++ ++ hw->fc_high_water = fc_high_water_mark; ++ hw->fc_low_water = fc_high_water_mark - 8; ++ hw->fc_pause_time = E1000_FC_PAUSE_TIME; ++ hw->fc_send_xon = 1; ++ hw->fc = hw->original_fc; + + /* Allow time for pending master requests to run */ +- iegbe_reset_hw(&adapter->hw); +- if(adapter->hw.mac_type >= iegbe_82544){ ++ iegbe_reset_hw(hw); ++ if (hw->mac_type >= iegbe_82544) + E1000_WRITE_REG(&adapter->hw, WUC, 0); +- } +- if(iegbe_init_hw(&adapter->hw)) { ++ ++ if (iegbe_init_hw(hw)) + DPRINTK(PROBE, ERR, "Hardware Error\n"); +- } +-#ifdef NETIF_F_HW_VLAN_TX + iegbe_update_mng_vlan(adapter); +-#endif ++ ++ /* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */ ++ if (hw->mac_type >= iegbe_82544 && ++ hw->mac_type <= iegbe_82547_rev_2 && ++ hw->autoneg == 1 && ++ hw->autoneg_advertised == ADVERTISE_1000_FULL) { ++ u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ /* clear phy power management bit if we are in gig only mode, ++ * which if enabled will attempt negotiation to 100Mb, which ++ * can cause a loss of link at power off or driver unload */ ++ ctrl &= ~E1000_CTRL_SWDPIN3; ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ } ++ + /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ + E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE); + +- iegbe_reset_adaptive(&adapter->hw); +- iegbe_phy_get_info(&adapter->hw, &adapter->phy_info); +- if(adapter->en_mng_pt) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST); +- E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ iegbe_reset_adaptive(hw); ++ iegbe_phy_get_info(hw, &adapter->phy_info); ++ ++ if (!adapter->smart_power_down && ++ (hw->mac_type == iegbe_82571 || ++ hw->mac_type == iegbe_82572)) { ++ u16 phy_data = 0; ++ /* speed up time to link by disabling smart power down, ignore ++ * the return value of this function because there is nothing ++ * different we would do if it failed */ ++ iegbe_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ &phy_data); ++ phy_data &= ~IGP02E1000_PM_SPD; ++ iegbe_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ phy_data); ++ } ++ ++} ++ ++/** ++ * Dump the eeprom for users having checksum issues ++ **/ ++static void iegbe_dump_eeprom(struct iegbe_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ struct ethtool_eeprom eeprom; ++ const struct ethtool_ops *ops = netdev->ethtool_ops; ++ u8 *data; ++ int i; ++ u16 csum_old, csum_new = 0; ++ ++ eeprom.len = ops->get_eeprom_len(netdev); ++ eeprom.offset = 0; ++ ++ data = kmalloc(eeprom.len, GFP_KERNEL); ++ if (!data) { ++ printk(KERN_ERR "Unable to allocate memory to dump EEPROM" ++ " data\n"); ++ return; + } ++ ++ ops->get_eeprom(netdev, &eeprom, data); ++ ++ csum_old = (data[EEPROM_CHECKSUM_REG * 2]) + ++ (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8); ++ for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2) ++ csum_new += data[i] + (data[i + 1] << 8); ++ csum_new = EEPROM_SUM - csum_new; ++ ++ printk(KERN_ERR "/*********************/\n"); ++ printk(KERN_ERR "Current EEPROM Checksum : 0x%04x\n", csum_old); ++ printk(KERN_ERR "Calculated : 0x%04x\n", csum_new); ++ ++ printk(KERN_ERR "Offset Values\n"); ++ printk(KERN_ERR "======== ======\n"); ++ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0); ++ ++ printk(KERN_ERR "Include this output when contacting your support " ++ "provider.\n"); ++ printk(KERN_ERR "This is not a software error! Something bad " ++ "happened to your hardware or\n"); ++ printk(KERN_ERR "EEPROM image. Ignoring this " ++ "problem could result in further problems,\n"); ++ printk(KERN_ERR "possibly loss of data, corruption or system hangs!\n"); ++ printk(KERN_ERR "The MAC Address will be reset to 00:00:00:00:00:00, " ++ "which is invalid\n"); ++ printk(KERN_ERR "and requires you to set the proper MAC " ++ "address manually before continuing\n"); ++ printk(KERN_ERR "to enable this network device.\n"); ++ printk(KERN_ERR "Please inspect the EEPROM dump and report the issue " ++ "to your hardware vendor\n"); ++ printk(KERN_ERR "or Intel Customer Support.\n"); ++ printk(KERN_ERR "/*********************/\n"); ++ ++ kfree(data); + } + + /** +@@ -721,184 +735,166 @@ iegbe_reset(struct iegbe_adapter *adapte + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + **/ +- +-static int __devinit +-iegbe_probe(struct pci_dev *pdev, ++static int __devinit iegbe_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { +- struct net_device *netdev; +- struct iegbe_adapter *adapter; +- unsigned long mmio_start, mmio_len; +- uint32_t ctrl_ext; +- uint32_t swsm; ++ struct net_device *netdev; ++ struct iegbe_adapter *adapter; ++ struct iegbe_hw *hw; + + static int cards_found = 0; ++ int i, err, pci_using_dac; ++ u16 eeprom_data = 0; ++ u16 eeprom_apme_mask = E1000_EEPROM_APME; ++ int bars; ++ DECLARE_MAC_BUF(mac); + +- int i, err, pci_using_dac; +- uint16_t eeprom_data = 0; +- uint16_t eeprom_apme_mask = E1000_EEPROM_APME; ++ bars = pci_select_bars(pdev, IORESOURCE_MEM); ++ err = pci_enable_device(pdev); + ++ if (err) ++ return err; + +- if((err = pci_enable_device(pdev))) { +- return err; +- } +- if(!(err = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) { ++ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && ++ !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { + pci_using_dac = 1; +- } else { +- if((err = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) { +- E1000_ERR("No usable DMA configuration, aborting\n"); +- return err; +- } ++ } else { ++ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); ++ if (err) { ++ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); ++ if (err) { ++ E1000_ERR("No usable DMA configuration, " ++ "aborting\n"); ++ goto err_dma; ++ } ++ } + pci_using_dac = 0; +- } +- +- if((err = pci_request_regions(pdev, iegbe_driver_name))) { +- return err; + } +- pci_set_master(pdev); + +- netdev = alloc_etherdev(sizeof(struct iegbe_adapter)); +- if(!netdev) { +- err = -ENOMEM; +- goto err_alloc_etherdev; +- } ++ err = pci_request_selected_regions(pdev, bars, iegbe_driver_name); ++ if (err) ++ goto err_pci_reg; ++ ++ pci_set_master(pdev); ++ ++ err = -ENOMEM; ++ netdev = alloc_etherdev(sizeof(struct iegbe_adapter)); ++ if (!netdev) ++ goto err_alloc_etherdev; + +- SET_MODULE_OWNER(netdev); + SET_NETDEV_DEV(netdev, &pdev->dev); + +- pci_set_drvdata(pdev, netdev); +- adapter = netdev_priv(netdev); +- adapter->netdev = netdev; +- adapter->pdev = pdev; +- adapter->hw.back = adapter; +- adapter->msg_enable = (0x1 << debug) - 0x1; +- +- mmio_start = pci_resource_start(pdev, BAR_0); +- mmio_len = pci_resource_len(pdev, BAR_0); +- +- adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); +- if(!adapter->hw.hw_addr) { +- err = -EIO; +- goto err_ioremap; +- } +- +- for(i = BAR_1; i <= BAR_5; i++) { +- if(pci_resource_len(pdev, i) == 0) { +- continue; +- } +- if(pci_resource_flags(pdev, i) & IORESOURCE_IO) { +- adapter->hw.io_base = pci_resource_start(pdev, i); +- break; +- } +- } +- +- netdev->open = &iegbe_open; +- netdev->stop = &iegbe_close; +- netdev->hard_start_xmit = &iegbe_xmit_frame; +- netdev->get_stats = &iegbe_get_stats; +- netdev->set_multicast_list = &iegbe_set_multi; ++ pci_set_drvdata(pdev, netdev); ++ adapter = netdev_priv(netdev); ++ adapter->netdev = netdev; ++ adapter->pdev = pdev; ++ adapter->msg_enable = (1 << debug) - 1; ++ adapter->bars = bars; ++ ++ hw = &adapter->hw; ++ hw->back = adapter; ++ ++ err = -EIO; ++ hw->hw_addr = ioremap(pci_resource_start(pdev, BAR_0), ++ pci_resource_len(pdev, BAR_0)); ++ if (!hw->hw_addr) ++ goto err_ioremap; ++ ++ netdev->open = &iegbe_open; ++ netdev->stop = &iegbe_close; ++ netdev->hard_start_xmit = &iegbe_xmit_frame; ++ netdev->get_stats = &iegbe_get_stats; ++ netdev->set_rx_mode = &iegbe_set_rx_mode; + netdev->set_mac_address = &iegbe_set_mac; +- netdev->change_mtu = &iegbe_change_mtu; +- netdev->do_ioctl = &iegbe_ioctl; ++ netdev->change_mtu = &iegbe_change_mtu; ++ netdev->do_ioctl = &iegbe_ioctl; + set_ethtool_ops(netdev); +-#ifdef HAVE_TX_TIMEOUT +- netdev->tx_timeout = &iegbe_tx_timeout; +- netdev->watchdog_timeo = 0x5 * HZ; +-#endif +-#ifdef CONFIG_E1000_NAPI +- netdev->poll = &iegbe_clean; +- netdev->weight = 0x40; +-#endif +-#ifdef NETIF_F_HW_VLAN_TX +- netdev->vlan_rx_register = iegbe_vlan_rx_register; +- netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid; +- netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid; +-#endif ++ netdev->tx_timeout = &iegbe_tx_timeout; ++ netdev->watchdog_timeo = 5 * HZ; ++ netif_napi_add(netdev, &adapter->napi, iegbe_clean, 64); ++ netdev->vlan_rx_register = iegbe_vlan_rx_register; ++ netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid; ++ netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid; + #ifdef CONFIG_NET_POLL_CONTROLLER +- netdev->poll_controller = iegbe_netpoll; ++ netdev->poll_controller = iegbe_netpoll; + #endif +- strcpy(netdev->name, pci_name(pdev)); ++ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + +- netdev->mem_start = mmio_start; +- netdev->mem_end = mmio_start + mmio_len; +- netdev->base_addr = adapter->hw.io_base; + +- adapter->bd_number = cards_found; ++ adapter->bd_number = cards_found; + +- /* setup the private structure */ ++ /* setup the private structure */ + +- if((err = iegbe_sw_init(adapter))) { +- goto err_sw_init; +- } +- if((err = iegbe_check_phy_reset_block(&adapter->hw))) { +- DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); +- } +-#ifdef MAX_SKB_FRAGS +- if(adapter->hw.mac_type >= iegbe_82543) { +-#ifdef NETIF_F_HW_VLAN_TX +- netdev->features = NETIF_F_SG | +- NETIF_F_HW_CSUM | +- NETIF_F_HW_VLAN_TX | +- NETIF_F_HW_VLAN_RX | +- NETIF_F_HW_VLAN_FILTER; +-#else +- netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM; +-#endif +- } ++ err = iegbe_sw_init(adapter); ++ if (err) ++ goto err_sw_init; ++ err = -EIO; ++ if (iegbe_check_phy_reset_block(hw)) ++ DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); + +-#ifdef NETIF_F_TSO +- if((adapter->hw.mac_type >= iegbe_82544) && +- (adapter->hw.mac_type != iegbe_82547)) { +- netdev->features |= NETIF_F_TSO; +- } +-#ifdef NETIF_F_TSO_IPV6 +- if(adapter->hw.mac_type > iegbe_82547_rev_2) { +- netdev->features |= NETIF_F_TSO_IPV6; +- } +-#endif +-#endif +- if(pci_using_dac) { +- netdev->features |= NETIF_F_HIGHDMA; ++ if (hw->mac_type >= iegbe_82543) { ++ netdev->features = NETIF_F_SG | ++ NETIF_F_HW_CSUM | ++ NETIF_F_HW_VLAN_TX | ++ NETIF_F_HW_VLAN_RX | ++ NETIF_F_HW_VLAN_FILTER; + } +-#endif +-#ifdef NETIF_F_LLTX +- netdev->features |= NETIF_F_LLTX; +-#endif + +- adapter->en_mng_pt = iegbe_enable_mng_pass_thru(&adapter->hw); ++ if ((hw->mac_type >= iegbe_82544) && ++ (hw->mac_type != iegbe_82547)) ++ netdev->features |= NETIF_F_TSO; + +- /* before reading the EEPROM, reset the controller to +- * put the device in a known good starting state */ ++ if (hw->mac_type > iegbe_82547_rev_2) ++ netdev->features |= NETIF_F_TSO6; ++ if (pci_using_dac) ++ netdev->features |= NETIF_F_HIGHDMA; ++ ++ netdev->features |= NETIF_F_LLTX; + +- iegbe_reset_hw(&adapter->hw); ++ adapter->en_mng_pt = iegbe_enable_mng_pass_thru(hw); + +- /* make sure the EEPROM is good */ +- if(iegbe_validate_eeprom_checksum(&adapter->hw) < 0) { +- DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); +- err = -EIO; ++ /* initialize eeprom parameters */ ++ ++ if (iegbe_init_eeprom_params(hw)) { ++ E1000_ERR("EEPROM initialization failed\n"); + goto err_eeprom; + } + +- /* copy the MAC address out of the EEPROM */ ++ /* before reading the EEPROM, reset the controller to ++ * put the device in a known good starting state */ + +- if(iegbe_read_mac_addr(&adapter->hw)) { +- DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); +- } +- memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); ++ iegbe_reset_hw(hw); + +- if(!is_valid_ether_addr(netdev->dev_addr)) { +- DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); +- err = -EIO; +- goto err_eeprom; +- } ++ /* make sure the EEPROM is good */ ++ if (iegbe_validate_eeprom_checksum(hw) < 0) { ++ DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); ++ iegbe_dump_eeprom(adapter); ++ /* ++ * set MAC address to all zeroes to invalidate and temporary ++ * disable this device for the user. This blocks regular ++ * traffic while still permitting ethtool ioctls from reaching ++ * the hardware as well as allowing the user to run the ++ * interface after manually setting a hw addr using ++ * `ip set address` ++ */ ++ memset(hw->mac_addr, 0, netdev->addr_len); ++ } else { ++ /* copy the MAC address out of the EEPROM */ ++ if (iegbe_read_mac_addr(hw)) ++ DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); ++ } ++ /* don't block initalization here due to bad MAC address */ ++ memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len); ++ memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len); + +- iegbe_read_part_num(&adapter->hw, &(adapter->part_num)); ++ if (!is_valid_ether_addr(netdev->perm_addr)) ++ DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); + +- iegbe_get_bus_info(&adapter->hw); ++ iegbe_get_bus_info(hw); + + init_timer(&adapter->tx_fifo_stall_timer); + adapter->tx_fifo_stall_timer.function = &iegbe_82547_tx_fifo_stall; +- adapter->tx_fifo_stall_timer.data = (unsigned long) adapter; ++ adapter->tx_fifo_stall_timer.data = (unsigned long)adapter; + + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = &iegbe_watchdog; +@@ -906,75 +902,50 @@ iegbe_probe(struct pci_dev *pdev, + + init_timer(&adapter->phy_info_timer); + adapter->phy_info_timer.function = &iegbe_update_phy_info; +- adapter->phy_info_timer.data = (unsigned long) adapter; +- +- INIT_WORK(&adapter->tx_timeout_task, +- (void (*)(void *))iegbe_tx_timeout_task, netdev); ++ adapter->phy_info_timer.data = (unsigned long)adapter; + +- /* we're going to reset, so assume we have no link for now */ +- +- netif_carrier_off(netdev); +- netif_stop_queue(netdev); ++ INIT_WORK(&adapter->reset_task, iegbe_reset_task); + +- iegbe_check_options(adapter); ++ iegbe_check_options(adapter); + +- /* Initial Wake on LAN setting +- * If APM wake is enabled in the EEPROM, +- * enable the ACPI Magic Packet filter +- */ ++ /* Initial Wake on LAN setting ++ * If APM wake is enabled in the EEPROM, ++ * enable the ACPI Magic Packet filter ++ */ + +- switch(adapter->hw.mac_type) { +- case iegbe_82542_rev2_0: +- case iegbe_82542_rev2_1: +- case iegbe_82543: +- break; +- case iegbe_82544: +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); +- eeprom_apme_mask = E1000_EEPROM_82544_APM; +- break; ++ switch(adapter->hw.mac_type) { ++ case iegbe_82542_rev2_0: ++ case iegbe_82542_rev2_1: ++ case iegbe_82543: ++ break; ++ case iegbe_82544: ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); ++ eeprom_apme_mask = E1000_EEPROM_82544_APM; ++ break; + case iegbe_icp_xxxx: +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL3_ICP_xxxx(adapter->bd_number), +- 1, &eeprom_data); +- eeprom_apme_mask = EEPROM_CTRL3_APME_ICP_xxxx; +- break; +- case iegbe_82546: +- case iegbe_82546_rev_3: +- if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) +- && (adapter->hw.media_type == iegbe_media_type_copper)) { +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); +- break; +- } +- /* Fall Through */ +- default: +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); +- break; +- } ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL3_ICP_xxxx(adapter->bd_number), ++ 1, &eeprom_data); ++ eeprom_apme_mask = EEPROM_CTRL3_APME_ICP_xxxx; ++ break; ++ case iegbe_82546: ++ case iegbe_82546_rev_3: ++ if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) ++ && (adapter->hw.media_type == iegbe_media_type_copper)) { ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); ++ break; ++ } ++ /* Fall Through */ ++ default: ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); ++ break; ++ } + if(eeprom_data & eeprom_apme_mask) { +- adapter->wol |= E1000_WUFC_MAG; ++ adapter->wol |= E1000_WUFC_MAG; + } +- /* reset the hardware with the new settings */ +- iegbe_reset(adapter); +- +- /* Let firmware know the driver has taken over */ +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm | E1000_SWSM_DRV_LOAD); +- break; +- default: +- break; +- } + + /* The ICP_xxxx device has multiple, duplicate interrupt + * registers, so disable all but the first one +@@ -987,24 +958,40 @@ iegbe_probe(struct pci_dev *pdev, + E1000_WRITE_REG(&adapter->hw, IMC2, ~0UL); + } + +- strcpy(netdev->name, "eth%d"); +- if((err = register_netdev(netdev))) { +- goto err_register; +- } ++ iegbe_reset(adapter); ++ netif_carrier_off(netdev); ++ netif_stop_queue(netdev); ++ strcpy(netdev->name, "eth%d"); ++ err = register_netdev(netdev); ++ if (err) ++ goto err_register; ++ + DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); + +- cards_found++; +- return 0; ++ cards_found++; ++ return 0; + + err_register: +-err_sw_init: + err_eeprom: +- iounmap(adapter->hw.hw_addr); ++ if (!iegbe_check_phy_reset_block(hw)) ++ iegbe_phy_hw_reset(hw); ++ if (hw->flash_address) ++ iounmap(hw->flash_address); ++ for (i = 0; i < adapter->num_rx_queues; i++) ++ dev_put(&adapter->polling_netdev[i]); ++ kfree(adapter->tx_ring); ++ kfree(adapter->rx_ring); ++ kfree(adapter->polling_netdev); ++err_sw_init: ++ iounmap(hw->hw_addr); + err_ioremap: +- free_netdev(netdev); ++ free_netdev(netdev); + err_alloc_etherdev: +- pci_release_regions(pdev); +- return err; ++ pci_release_selected_regions(pdev, bars); ++err_pci_reg: ++err_dma: ++ pci_disable_device(pdev); ++ return err; + } + + /** +@@ -1020,64 +1007,36 @@ err_alloc_etherdev: + static void __devexit + iegbe_remove(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t ctrl_ext; +- uint32_t manc, swsm; +-#ifdef CONFIG_E1000_NAPI +- int i; +-#endif +- +- if(adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.mac_type != iegbe_icp_xxxx +- && adapter->hw.media_type == iegbe_media_type_copper) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- if(manc & E1000_MANC_SMBUS_EN) { +- manc |= E1000_MANC_ARP_EN; +- E1000_WRITE_REG(&adapter->hw, MANC, manc); +- } +- } +- +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm & ~E1000_SWSM_DRV_LOAD); +- break; +- +- default: +- break; +- } ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t manc; ++ int i; ++ ++ if(adapter->hw.mac_type >= iegbe_82540 ++ && adapter->hw.mac_type != iegbe_icp_xxxx ++ && adapter->hw.media_type == iegbe_media_type_copper) { ++ manc = E1000_READ_REG(&adapter->hw, MANC); ++ if(manc & E1000_MANC_SMBUS_EN) { ++ manc |= E1000_MANC_ARP_EN; ++ E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ } ++ } + +- unregister_netdev(netdev); +-#ifdef CONFIG_E1000_NAPI +- for (i = 0; i < adapter->num_queues; i++) ++ unregister_netdev(netdev); ++ for (i = 0x0; i < adapter->num_rx_queues; i++) + dev_put(&adapter->polling_netdev[i]); +-#endif + + if(!iegbe_check_phy_reset_block(&adapter->hw)) { +- iegbe_phy_hw_reset(&adapter->hw); ++ iegbe_phy_hw_reset(&adapter->hw); + } +- kfree(adapter->tx_ring); +- kfree(adapter->rx_ring); +-#ifdef CONFIG_E1000_NAPI +- kfree(adapter->polling_netdev); +-#endif ++ kfree(adapter->tx_ring); ++ kfree(adapter->rx_ring); ++ kfree(adapter->polling_netdev); + +- iounmap(adapter->hw.hw_addr); +- pci_release_regions(pdev); ++ iounmap(adapter->hw.hw_addr); ++ pci_release_regions(pdev); + +-#ifdef CONFIG_E1000_MQ +- free_percpu(adapter->cpu_netdev); +- free_percpu(adapter->cpu_tx_ring); +-#endif +- free_netdev(netdev); ++ free_netdev(netdev); + } + + /** +@@ -1092,118 +1051,78 @@ iegbe_remove(struct pci_dev *pdev) + static int __devinit + iegbe_sw_init(struct iegbe_adapter *adapter) + { +- struct iegbe_hw *hw = &adapter->hw; +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +-#ifdef CONFIG_E1000_NAPI +- int i; +-#endif ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ int i; + +- /* PCI config space info */ ++ /* PCI config space info */ + +- hw->vendor_id = pdev->vendor; +- hw->device_id = pdev->device; +- hw->subsystem_vendor_id = pdev->subsystem_vendor; +- hw->subsystem_id = pdev->subsystem_device; ++ hw->vendor_id = pdev->vendor; ++ hw->device_id = pdev->device; ++ hw->subsystem_vendor_id = pdev->subsystem_vendor; ++ hw->subsystem_id = pdev->subsystem_device; + +- pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); ++ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); + +- pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); ++ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); + +- adapter->rx_buffer_len = E1000_RXBUFFER_2048; +- adapter->rx_ps_bsize0 = E1000_RXBUFFER_256; +- hw->max_frame_size = netdev->mtu + +- ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; +- hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; ++ adapter->rx_buffer_len = E1000_RXBUFFER_2048; ++ adapter->rx_ps_bsize0 = E1000_RXBUFFER_256; ++ hw->max_frame_size = netdev->mtu + ++ ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; ++ hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; + +- /* identify the MAC */ ++ /* identify the MAC */ + +- if(iegbe_set_mac_type(hw)) { ++ if (iegbe_set_mac_type(hw)) { + DPRINTK(PROBE, ERR, "Unknown MAC Type\n"); + return -EIO; + } + +- /* initialize eeprom parameters */ +- +- if(iegbe_init_eeprom_params(hw)) { +- E1000_ERR("EEPROM initialization failed\n"); +- return -EIO; +- } +- +- switch(hw->mac_type) { +- default: +- break; +- case iegbe_82541: +- case iegbe_82547: +- case iegbe_82541_rev_2: +- case iegbe_82547_rev_2: +- hw->phy_init_script = 0x1; +- break; +- } +- +- iegbe_set_media_type(hw); ++ iegbe_set_media_type(hw); + +- hw->wait_autoneg_complete = FALSE; +- hw->tbi_compatibility_en = TRUE; +- hw->adaptive_ifs = TRUE; ++ hw->wait_autoneg_complete = FALSE; ++ hw->tbi_compatibility_en = TRUE; ++ hw->adaptive_ifs = TRUE; + +- /* Copper options */ ++ /* Copper options */ + +- if(hw->media_type == iegbe_media_type_copper ++ if(hw->media_type == iegbe_media_type_copper + || (hw->media_type == iegbe_media_type_oem + && iegbe_oem_phy_is_copper(&adapter->hw))) { +- hw->mdix = AUTO_ALL_MODES; +- hw->disable_polarity_correction = FALSE; +- hw->master_slave = E1000_MASTER_SLAVE; +- } ++ hw->mdix = AUTO_ALL_MODES; ++ hw->disable_polarity_correction = FALSE; ++ hw->master_slave = E1000_MASTER_SLAVE; ++ } + +-#ifdef CONFIG_E1000_MQ +- /* Number of supported queues */ +- switch (hw->mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- adapter->num_queues = 0x2; +- break; +- default: +- adapter->num_queues = 0x1; +- break; +- } +- adapter->num_queues = min(adapter->num_queues, num_online_cpus()); +-#else +- adapter->num_queues = 0x1; +-#endif ++ adapter->num_tx_queues = 0x1; ++ adapter->num_rx_queues = 0x1; + + if (iegbe_alloc_queues(adapter)) { + DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + +-#ifdef CONFIG_E1000_NAPI +- for (i = 0; i < adapter->num_queues; i++) { ++ for (i = 0; i < adapter->num_rx_queues; i++) { + adapter->polling_netdev[i].priv = adapter; +- adapter->polling_netdev[i].poll = &iegbe_clean; +- adapter->polling_netdev[i].weight = 0x40; + dev_hold(&adapter->polling_netdev[i]); + set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state); + } +-#endif +- +-#ifdef CONFIG_E1000_MQ +- iegbe_setup_queue_mapping(adapter); +-#endif ++ spin_lock_init(&adapter->tx_queue_lock); + + /* +- * for ICP_XXXX style controllers, it is necessary to keep +- * track of the last known state of the link to determine if +- * the link experienced a change in state when iegbe_watchdog +- * fires +- */ +- adapter->hw.icp_xxxx_is_link_up = FALSE; ++ * for ICP_XXXX style controllers, it is necessary to keep ++ * track of the last known state of the link to determine if ++ * the link experienced a change in state when iegbe_watchdog ++ * fires ++ */ ++ adapter->hw.icp_xxxx_is_link_up = FALSE; + +- atomic_set(&adapter->irq_sem, 1); +- spin_lock_init(&adapter->stats_lock); ++ spin_lock_init(&adapter->stats_lock); + +- return 0; ++ set_bit(__E1000_DOWN, &adapter->flags); ++ return 0x0; + } + + /** +@@ -1218,71 +1137,31 @@ iegbe_sw_init(struct iegbe_adapter *adap + static int __devinit + iegbe_alloc_queues(struct iegbe_adapter *adapter) + { +- int size; + +- size = sizeof(struct iegbe_tx_ring) * adapter->num_queues; +- adapter->tx_ring = kmalloc(size, GFP_KERNEL); +- if (!adapter->tx_ring){ ++ ++ adapter->tx_ring = kcalloc(adapter->num_tx_queues, ++ sizeof(struct iegbe_tx_ring), GFP_KERNEL); ++ if (!adapter->tx_ring) + return -ENOMEM; +- } +- memset(adapter->tx_ring, 0, size); + +- size = sizeof(struct iegbe_rx_ring) * adapter->num_queues; +- adapter->rx_ring = kmalloc(size, GFP_KERNEL); ++ adapter->rx_ring = kcalloc(adapter->num_rx_queues, ++ sizeof(struct iegbe_rx_ring), GFP_KERNEL); + if (!adapter->rx_ring) { + kfree(adapter->tx_ring); + return -ENOMEM; + } +- memset(adapter->rx_ring, 0, size); + +-#ifdef CONFIG_E1000_NAPI +- size = sizeof(struct net_device) * adapter->num_queues; +- adapter->polling_netdev = kmalloc(size, GFP_KERNEL); ++ adapter->polling_netdev = kcalloc(adapter->num_rx_queues, ++ sizeof(struct net_device), ++ GFP_KERNEL); + if (!adapter->polling_netdev) { + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); + return -ENOMEM; + } +- memset(adapter->polling_netdev, 0, size); +-#endif +- +- return E1000_SUCCESS; +-} + +-#ifdef CONFIG_E1000_MQ +-static void __devinit +-iegbe_setup_queue_mapping(struct iegbe_adapter *adapter) +-{ +- int i, cpu; +- +- adapter->rx_sched_call_data.func = iegbe_rx_schedule; +- adapter->rx_sched_call_data.info = adapter->netdev; +- cpus_clear(adapter->rx_sched_call_data.cpumask); +- +- adapter->cpu_netdev = alloc_percpu(struct net_device *); +- adapter->cpu_tx_ring = alloc_percpu(struct iegbe_tx_ring *); +- +- lock_cpu_hotplug(); +- i = 0; +- for_each_online_cpu(cpu) { +- *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = +- &adapter->tx_ring[i % adapter->num_queues]; +- /* This is incomplete because we'd like to assign separate +- * physical cpus to these netdev polling structures and +- * avoid saturating a subset of cpus. +- */ +- if (i < adapter->num_queues) { +- *per_cpu_ptr(adapter->cpu_netdev, cpu) = +- &adapter->polling_netdev[i]; +- adapter->cpu_for_queue[i] = cpu; +- } else { +- *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL; +- } +- i++; +- } +- unlock_cpu_hotplug(); ++ return E1000_SUCCESS; + } +-#endif + + /** + * iegbe_open - Called when a network interface is made active +@@ -1300,40 +1179,62 @@ iegbe_setup_queue_mapping(struct iegbe_a + static int + iegbe_open(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- int err; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ int err; ++ + ++ /* allocate receive descriptors */ ++ if (test_bit(__E1000_TESTING, &adapter->flags)) ++ return -EBUSY; + +- /* allocate receive descriptors */ ++ /* allocate transmit descriptors */ ++ err = iegbe_setup_all_tx_resources(adapter); ++ if (err) ++ goto err_setup_tx; + +- if ((err = iegbe_setup_all_rx_resources(adapter))) { ++ err = iegbe_setup_all_rx_resources(adapter); ++ if (err) + goto err_setup_rx; +- } +- /* allocate transmit descriptors */ +- if ((err = iegbe_setup_all_tx_resources(adapter))) { +- goto err_setup_tx; +- } +- if ((err = iegbe_up(adapter))) { +- goto err_up; +- } +-#ifdef NETIF_F_HW_VLAN_TX +- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- if ((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { +- iegbe_update_mng_vlan(adapter); +- } +-#endif + +- return E1000_SUCCESS; ++ iegbe_power_up_phy(adapter); ++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; ++ if ((hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { ++ iegbe_update_mng_vlan(adapter); ++ } ++ ++ /* before we allocate an interrupt, we must be ready to handle it. ++ * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt ++ * as soon as we call pci_request_irq, so we have to setup our ++ * clean_rx handler before we do so. */ ++ iegbe_configure(adapter); ++ err = iegbe_request_irq(adapter); ++ if (err) ++ goto err_req_irq; + +-err_up: +- iegbe_free_all_tx_resources(adapter); +-err_setup_tx: +- iegbe_free_all_rx_resources(adapter); ++ /* From here on the code is the same as iegbe_up() */ ++ clear_bit(__E1000_DOWN, &adapter->flags); ++ ++ napi_enable(&adapter->napi); ++ ++ iegbe_irq_enable(adapter); ++ ++ netif_start_queue(netdev); ++ ++ /* fire a link status change interrupt to start the watchdog */ ++ ++ return E1000_SUCCESS; ++ ++err_req_irq: ++ iegbe_power_down_phy(adapter); ++ iegbe_free_all_rx_resources(adapter); + err_setup_rx: +- iegbe_reset(adapter); ++ iegbe_free_all_tx_resources(adapter); ++err_setup_tx: ++ iegbe_reset(adapter); + +- return err; ++ return err; + } + + /** +@@ -1348,22 +1249,25 @@ err_setup_rx: + * hardware, and all transmit and receive resources are freed. + **/ + +-static int +-iegbe_close(struct net_device *netdev) ++static int iegbe_close(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- +- iegbe_down(adapter); +- +- iegbe_free_all_tx_resources(adapter); +- iegbe_free_all_rx_resources(adapter); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; + +-#ifdef NETIF_F_HW_VLAN_TX +- if((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { ++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); ++ iegbe_down(adapter); ++ iegbe_power_down_phy(adapter); ++ iegbe_free_irq(adapter); ++ ++ iegbe_free_all_tx_resources(adapter); ++ iegbe_free_all_rx_resources(adapter); ++ ++ if ((hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && ++ !(adapter->vlgrp && ++ vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) { + iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); + } +-#endif + return 0; + } + +@@ -1375,19 +1279,19 @@ iegbe_close(struct net_device *netdev) + **/ + static inline boolean_t + iegbe_check_64k_bound(struct iegbe_adapter *adapter, +- void *start, unsigned long len) ++ void *start, unsigned long len) + { +- unsigned long begin = (unsigned long) start; +- unsigned long end = begin + len; ++ unsigned long begin = (unsigned long) start; ++ unsigned long end = begin + len; + +- /* First rev 82545 and 82546 need to not allow any memory +- * write location to cross 64k boundary due to errata 23 */ +- if(adapter->hw.mac_type == iegbe_82545 || +- adapter->hw.mac_type == iegbe_82546) { +- return ((begin ^ (end - 1)) >> 0x10) != 0 ? FALSE : TRUE; +- } ++ /* First rev 82545 and 82546 need to not allow any memory ++ * write location to cross 64k boundary due to errata 23 */ ++ if(adapter->hw.mac_type == iegbe_82545 || ++ adapter->hw.mac_type == iegbe_82546) { ++ return ((begin ^ (end - 1)) >> 0x10) != 0x0 ? FALSE : TRUE; ++ } + +- return TRUE; ++ return TRUE; + } + + /** +@@ -1398,102 +1302,98 @@ iegbe_check_64k_bound(struct iegbe_adapt + * Return 0 on success, negative on failure + **/ + +-int +-iegbe_setup_tx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *txdr) + { +- struct pci_dev *pdev = adapter->pdev; +- int size; ++ struct pci_dev *pdev = adapter->pdev; ++ int size; + +- size = sizeof(struct iegbe_buffer) * txdr->count; +- txdr->buffer_info = vmalloc(size); +- if (!txdr->buffer_info) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the transmit descriptor ring\n"); +- return -ENOMEM; +- } ++ size = sizeof(struct iegbe_buffer) * txdr->count; ++ txdr->buffer_info = vmalloc(size); ++ if (!txdr->buffer_info) { ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the transmit descriptor ring\n"); ++ return -ENOMEM; ++ } + memset(txdr->buffer_info, 0, size); +- memset(&txdr->previous_buffer_info, 0, sizeof(struct iegbe_buffer)); + +- /* round up to nearest 4K */ ++ /* round up to nearest 4K */ + +- txdr->size = txdr->count * sizeof(struct iegbe_tx_desc); +- E1000_ROUNDUP(txdr->size, 0x1000); ++ txdr->size = txdr->count * sizeof(struct iegbe_tx_desc); ++ txdr->size = ALIGN(txdr->size, 4096); + +- txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); +- if (!txdr->desc) { ++ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); ++ if (!txdr->desc) { + setup_tx_desc_die: +- vfree(txdr->buffer_info); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the transmit descriptor ring\n"); +- return -ENOMEM; +- } +- +- /* Fix for errata 23, can't cross 64kB boundary */ +- if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { +- void *olddesc = txdr->desc; +- dma_addr_t olddma = txdr->dma; +- DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes " +- "at %p\n", txdr->size, txdr->desc); +- /* Try again, without freeing the previous */ +- txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); +- /* Failed allocation, critical failure */ +- if (!txdr->desc) { +- pci_free_consistent(pdev, txdr->size, olddesc, olddma); +- goto setup_tx_desc_die; +- } ++ vfree(txdr->buffer_info); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the transmit descriptor ring\n"); ++ return -ENOMEM; ++ } ++ ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { ++ void *olddesc = txdr->desc; ++ dma_addr_t olddma = txdr->dma; ++ DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes " ++ "at %p\n", txdr->size, txdr->desc); ++ /* Try again, without freeing the previous */ ++ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); ++ /* Failed allocation, critical failure */ ++ if (!txdr->desc) { ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ goto setup_tx_desc_die; ++ } + +- if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { +- /* give up */ +- pci_free_consistent(pdev, txdr->size, txdr->desc, +- txdr->dma); +- pci_free_consistent(pdev, txdr->size, olddesc, olddma); +- DPRINTK(PROBE, ERR, +- "Unable to allocate aligned memory " +- "for the transmit descriptor ring\n"); +- vfree(txdr->buffer_info); +- return -ENOMEM; +- } else { +- /* Free old allocation, new allocation was successful */ +- pci_free_consistent(pdev, txdr->size, olddesc, olddma); +- } +- } ++ if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { ++ /* give up */ ++ pci_free_consistent(pdev, txdr->size, txdr->desc, ++ txdr->dma); ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate aligned memory " ++ "for the transmit descriptor ring\n"); ++ vfree(txdr->buffer_info); ++ return -ENOMEM; ++ } else { ++ /* Free old allocation, new allocation was successful */ ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ } ++ } + memset(txdr->desc, 0, txdr->size); + + txdr->next_to_use = 0; + txdr->next_to_clean = 0; +- spin_lock_init(&txdr->tx_lock); ++ spin_lock_init(&txdr->tx_lock); + + return 0; + } + + /** + * iegbe_setup_all_tx_resources - wrapper to allocate Tx resources +- * (Descriptors) for all queues ++ * (Descriptors) for all queues + * @adapter: board private structure + * +- * If this function returns with an error, then it's possible one or +- * more of the rings is populated (while the rest are not). It is the +- * callers duty to clean those orphaned rings. +- * + * Return 0 on success, negative on failure + **/ + +-int +-iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter) ++int iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter) + { + int i, err = 0; + +- for (i = 0; i < adapter->num_queues; i++) { ++ for (i = 0; i < adapter->num_tx_queues; i++) { + err = iegbe_setup_tx_resources(adapter, &adapter->tx_ring[i]); + if (err) { + DPRINTK(PROBE, ERR, + "Allocation for Tx Queue %u failed\n", i); ++ for (i-- ; i >= 0; i--) ++ iegbe_free_tx_resources(adapter, ++ &adapter->tx_ring[i]); + break; + } + } + +- return err; ++ return err; + } + + /** +@@ -1512,113 +1412,108 @@ iegbe_configure_tx(struct iegbe_adapter + + /* Setup the HW Tx Head and Tail descriptor pointers */ + +- switch (adapter->num_queues) { ++ switch (adapter->num_tx_queues) { + case 0x2: + tdba = adapter->tx_ring[0x1].dma; + tdlen = adapter->tx_ring[0x1].count * +- sizeof(struct iegbe_tx_desc); +- E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL)); ++ sizeof(struct iegbe_tx_desc); ++ E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL)); + E1000_WRITE_REG(hw, TDBAH1, (tdba >> 0x20)); +- E1000_WRITE_REG(hw, TDLEN1, tdlen); +- E1000_WRITE_REG(hw, TDH1, 0); +- E1000_WRITE_REG(hw, TDT1, 0); ++ E1000_WRITE_REG(hw, TDLEN1, tdlen); ++ E1000_WRITE_REG(hw, TDH1, 0x0); ++ E1000_WRITE_REG(hw, TDT1, 0x0); + adapter->tx_ring[0x1].tdh = E1000_TDH1; + adapter->tx_ring[0x1].tdt = E1000_TDT1; +- /* Fall Through */ ++ /* Fall Through */ + case 0x1: +- default: +- tdba = adapter->tx_ring[0].dma; +- tdlen = adapter->tx_ring[0].count * +- sizeof(struct iegbe_tx_desc); +- E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL)); ++ default: ++ tdba = adapter->tx_ring[0x0].dma; ++ tdlen = adapter->tx_ring[0x0].count * ++ sizeof(struct iegbe_tx_desc); ++ E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL)); + E1000_WRITE_REG(hw, TDBAH, (tdba >> 0x20)); +- E1000_WRITE_REG(hw, TDLEN, tdlen); +- E1000_WRITE_REG(hw, TDH, 0); +- E1000_WRITE_REG(hw, TDT, 0); +- adapter->tx_ring[0].tdh = E1000_TDH; +- adapter->tx_ring[0].tdt = E1000_TDT; +- break; +- } +- +- /* Set the default values for the Tx Inter Packet Gap timer */ +- +- switch (hw->mac_type) { +- case iegbe_82542_rev2_0: +- case iegbe_82542_rev2_1: +- tipg = DEFAULT_82542_TIPG_IPGT; +- tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; +- tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; +- break; +- default: +- switch(hw->media_type) { +- case iegbe_media_type_fiber: +- case iegbe_media_type_internal_serdes: +- tipg = DEFAULT_82543_TIPG_IPGT_FIBER; +- break; +- case iegbe_media_type_copper: +- tipg = DEFAULT_82543_TIPG_IPGT_COPPER; +- break; +- case iegbe_media_type_oem: +- default: ++ E1000_WRITE_REG(hw, TDLEN, tdlen); ++ E1000_WRITE_REG(hw, TDH, 0x0); ++ E1000_WRITE_REG(hw, TDT, 0x0); ++ adapter->tx_ring[0x0].tdh = E1000_TDH; ++ adapter->tx_ring[0x0].tdt = E1000_TDT; ++ break; ++ } ++ ++ /* Set the default values for the Tx Inter Packet Gap timer */ ++ ++ switch (hw->mac_type) { ++ case iegbe_82542_rev2_0: ++ case iegbe_82542_rev2_1: ++ tipg = DEFAULT_82542_TIPG_IPGT; ++ tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; ++ tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; ++ break; ++ default: ++ switch(hw->media_type) { ++ case iegbe_media_type_fiber: ++ case iegbe_media_type_internal_serdes: ++ tipg = DEFAULT_82543_TIPG_IPGT_FIBER; ++ break; ++ case iegbe_media_type_copper: ++ tipg = DEFAULT_82543_TIPG_IPGT_COPPER; ++ break; ++ case iegbe_media_type_oem: ++ default: + tipg = (0xFFFFFFFFUL >> (sizeof(tipg)*0x8 - + E1000_TIPG_IPGR1_SHIFT)) +- & iegbe_oem_get_tipg(&adapter->hw); +- break; +- } +- tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; +- tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; +- } +- E1000_WRITE_REG(hw, TIPG, tipg); ++ & iegbe_oem_get_tipg(&adapter->hw); ++ break; ++ } ++ tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; ++ tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; ++ } ++ E1000_WRITE_REG(hw, TIPG, tipg); + +- /* Set the Tx Interrupt Delay register */ ++ /* Set the Tx Interrupt Delay register */ + +- E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay); ++ E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay); + if (hw->mac_type >= iegbe_82540) { +- E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay); ++ E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay); + } +- /* Program the Transmit Control Register */ ++ /* Program the Transmit Control Register */ + +- tctl = E1000_READ_REG(hw, TCTL); ++ tctl = E1000_READ_REG(hw, TCTL); + +- tctl &= ~E1000_TCTL_CT; +- tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC | +- (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); ++ tctl &= ~E1000_TCTL_CT; ++ tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC | ++ (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); + +- E1000_WRITE_REG(hw, TCTL, tctl); ++ E1000_WRITE_REG(hw, TCTL, tctl); + +- if (hw->mac_type == iegbe_82571 || hw->mac_type == iegbe_82572) { +- tarc = E1000_READ_REG(hw, TARC0); ++ if (hw->mac_type == iegbe_82571 || hw->mac_type == iegbe_82572) { ++ tarc = E1000_READ_REG(hw, TARC0); + tarc |= ((0x1 << 0x19) | (0x1 << 0x15)); +- E1000_WRITE_REG(hw, TARC0, tarc); +- tarc = E1000_READ_REG(hw, TARC1); ++ E1000_WRITE_REG(hw, TARC0, tarc); ++ tarc = E1000_READ_REG(hw, TARC1); + tarc |= (0x1 << 0x19); + if (tctl & E1000_TCTL_MULR) { + tarc &= ~(0x1 << 0x1c); + } else { + tarc |= (0x1 << 0x1c); + } +- E1000_WRITE_REG(hw, TARC1, tarc); +- } ++ E1000_WRITE_REG(hw, TARC1, tarc); ++ } + +- iegbe_config_collision_dist(hw); ++ iegbe_config_collision_dist(hw); + +- /* Setup Transmit Descriptor Settings for eop descriptor */ +- adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | +- E1000_TXD_CMD_IFCS; ++ /* Setup Transmit Descriptor Settings for eop descriptor */ ++ adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | ++ E1000_TXD_CMD_IFCS; + + if (hw->mac_type < iegbe_82543) { +- adapter->txd_cmd |= E1000_TXD_CMD_RPS; ++ adapter->txd_cmd |= E1000_TXD_CMD_RPS; + } else { +-#ifdef IEGBE_GBE_WORKAROUND +- /* Disable the RS bit in the Tx descriptor */ +- adapter->txd_cmd &= ~E1000_TXD_CMD_RS; +-#else +- adapter->txd_cmd |= E1000_TXD_CMD_RS; +-#endif ++ adapter->txd_cmd |= E1000_TXD_CMD_RS; + } +- /* Cache if we're 82544 running in PCI-X because we'll +- * need this to apply a workaround later in the send path. */ +- if (hw->mac_type == iegbe_82544 && ++ /* Cache if we're 82544 running in PCI-X because we'll ++ * need this to apply a workaround later in the send path. */ ++ if (hw->mac_type == iegbe_82544 && + hw->bus_type == iegbe_bus_type_pcix) { + adapter->pcix_82544 = 0x1; + } +@@ -1632,96 +1527,95 @@ iegbe_configure_tx(struct iegbe_adapter + * Returns 0 on success, negative on failure + **/ + +-int +-iegbe_setup_rx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rxdr) + { +- struct pci_dev *pdev = adapter->pdev; +- int size, desc_len; +- +- size = sizeof(struct iegbe_buffer) * rxdr->count; +- rxdr->buffer_info = vmalloc(size); +- if (!rxdr->buffer_info) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); +- return -ENOMEM; +- } +- memset(rxdr->buffer_info, 0, size); +- +- size = sizeof(struct iegbe_ps_page) * rxdr->count; +- rxdr->ps_page = kmalloc(size, GFP_KERNEL); +- if (!rxdr->ps_page) { +- vfree(rxdr->buffer_info); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); +- return -ENOMEM; +- } +- memset(rxdr->ps_page, 0, size); +- +- size = sizeof(struct iegbe_ps_page_dma) * rxdr->count; +- rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL); +- if (!rxdr->ps_page_dma) { +- vfree(rxdr->buffer_info); +- kfree(rxdr->ps_page); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); +- return -ENOMEM; +- } +- memset(rxdr->ps_page_dma, 0, size); ++ struct iegbe_hw *hw = &adapter->hw; ++ struct pci_dev *pdev = adapter->pdev; ++ int size, desc_len; + +- if (adapter->hw.mac_type <= iegbe_82547_rev_2) { +- desc_len = sizeof(struct iegbe_rx_desc); +- } else { +- desc_len = sizeof(union iegbe_rx_desc_packet_split); ++ size = sizeof(struct iegbe_buffer) * rxdr->count; ++ rxdr->buffer_info = vmalloc(size); ++ if (!rxdr->buffer_info) { ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); ++ return -ENOMEM; + } +- /* Round up to nearest 4K */ +- +- rxdr->size = rxdr->count * desc_len; +- E1000_ROUNDUP(rxdr->size, 0x1000); +- +- rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ memset(rxdr->buffer_info, 0, size); + +- if (!rxdr->desc) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); ++ rxdr->ps_page = kcalloc(rxdr->count, sizeof(struct iegbe_ps_page), ++ GFP_KERNEL); ++ if (!rxdr->ps_page) { ++ vfree(rxdr->buffer_info); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); ++ return -ENOMEM; ++ } ++ ++ rxdr->ps_page_dma = kcalloc(rxdr->count, ++ sizeof(struct iegbe_ps_page_dma), ++ GFP_KERNEL); ++ if (!rxdr->ps_page_dma) { ++ vfree(rxdr->buffer_info); ++ kfree(rxdr->ps_page); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); ++ return -ENOMEM; ++ } ++ ++ if (hw->mac_type <= iegbe_82547_rev_2) ++ desc_len = sizeof(struct iegbe_rx_desc); ++ else ++ desc_len = sizeof(union iegbe_rx_desc_packet_split); ++ ++ /* Round up to nearest 4K */ ++ ++ rxdr->size = rxdr->count * desc_len; ++ rxdr->size = ALIGN(rxdr->size, 4096); ++ ++ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ ++ if (!rxdr->desc) { ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); + setup_rx_desc_die: +- vfree(rxdr->buffer_info); +- kfree(rxdr->ps_page); +- kfree(rxdr->ps_page_dma); +- return -ENOMEM; +- } +- +- /* Fix for errata 23, can't cross 64kB boundary */ +- if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { +- void *olddesc = rxdr->desc; +- dma_addr_t olddma = rxdr->dma; +- DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes " +- "at %p\n", rxdr->size, rxdr->desc); +- /* Try again, without freeing the previous */ +- rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); +- /* Failed allocation, critical failure */ +- if (!rxdr->desc) { +- pci_free_consistent(pdev, rxdr->size, olddesc, olddma); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory " +- "for the receive descriptor ring\n"); +- goto setup_rx_desc_die; +- } ++ vfree(rxdr->buffer_info); ++ kfree(rxdr->ps_page); ++ kfree(rxdr->ps_page_dma); ++ return -ENOMEM; ++ } ++ ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { ++ void *olddesc = rxdr->desc; ++ dma_addr_t olddma = rxdr->dma; ++ DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes " ++ "at %p\n", rxdr->size, rxdr->desc); ++ /* Try again, without freeing the previous */ ++ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ /* Failed allocation, critical failure */ ++ if (!rxdr->desc) { ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory " ++ "for the receive descriptor ring\n"); ++ goto setup_rx_desc_die; ++ } + +- if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { +- /* give up */ +- pci_free_consistent(pdev, rxdr->size, rxdr->desc, +- rxdr->dma); +- pci_free_consistent(pdev, rxdr->size, olddesc, olddma); +- DPRINTK(PROBE, ERR, +- "Unable to allocate aligned memory " +- "for the receive descriptor ring\n"); +- goto setup_rx_desc_die; +- } else { +- /* Free old allocation, new allocation was successful */ +- pci_free_consistent(pdev, rxdr->size, olddesc, olddma); +- } +- } ++ if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { ++ /* give up */ ++ pci_free_consistent(pdev, rxdr->size, rxdr->desc, ++ rxdr->dma); ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate aligned memory " ++ "for the receive descriptor ring\n"); ++ goto setup_rx_desc_die; ++ } else { ++ /* Free old allocation, new allocation was successful */ ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ } ++ } + memset(rxdr->desc, 0, rxdr->size); + + rxdr->next_to_clean = 0; +@@ -1732,7 +1626,7 @@ setup_rx_desc_die: + + /** + * iegbe_setup_all_rx_resources - wrapper to allocate Rx resources +- * (Descriptors) for all queues ++ * (Descriptors) for all queues + * @adapter: board private structure + * + * If this function returns with an error, then it's possible one or +@@ -1742,21 +1636,23 @@ setup_rx_desc_die: + * Return 0 on success, negative on failure + **/ + +-int +-iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter) ++int iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter) + { + int i, err = 0; + +- for (i = 0; i < adapter->num_queues; i++) { ++ for (i = 0; i < adapter->num_rx_queues; i++) { + err = iegbe_setup_rx_resources(adapter, &adapter->rx_ring[i]); + if (err) { + DPRINTK(PROBE, ERR, + "Allocation for Rx Queue %u failed\n", i); ++ for (i-- ; i >= 0; i--) ++ iegbe_free_rx_resources(adapter, ++ &adapter->rx_ring[i]); + break; + } + } + +- return err; ++ return err; + } + + /** +@@ -1765,105 +1661,104 @@ iegbe_setup_all_rx_resources(struct iegb + **/ + #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ + (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) +-static void +-iegbe_setup_rctl(struct iegbe_adapter *adapter) ++static void iegbe_setup_rctl(struct iegbe_adapter *adapter) + { +- uint32_t rctl, rfctl; +- uint32_t psrctl = 0; +-#ifdef CONFIG_E1000_PACKET_SPLIT +- uint32_t pages = 0; +-#endif +- +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- +- rctl &= ~(0x3 << E1000_RCTL_MO_SHIFT); +- +- rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | +- E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | +- (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT); +- +- if(adapter->hw.tbi_compatibility_on == 0x1) { +- rctl |= E1000_RCTL_SBP; +- } else { +- rctl &= ~E1000_RCTL_SBP; +- } +- if(adapter->netdev->mtu <= ETH_DATA_LEN) { +- rctl &= ~E1000_RCTL_LPE; +- } else { +- rctl |= E1000_RCTL_LPE; +- } +- /* Setup buffer sizes */ +- if(adapter->hw.mac_type >= iegbe_82571) { +- /* We can now specify buffers in 1K increments. +- * BSIZE and BSEX are ignored in this case. */ +- rctl |= adapter->rx_buffer_len << 0x11; +- } else { +- rctl &= ~E1000_RCTL_SZ_4096; +- rctl |= E1000_RCTL_BSEX; +- switch (adapter->rx_buffer_len) { +- case E1000_RXBUFFER_2048: +- default: +- rctl |= E1000_RCTL_SZ_2048; ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 rctl, rfctl; ++ u32 psrctl = 0; ++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT ++ u32 pages = 0; ++#endif ++ ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ ++ rctl &= ~(3 << E1000_RCTL_MO_SHIFT); ++ ++ rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | ++ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | ++ (hw->mc_filter_type << E1000_RCTL_MO_SHIFT); ++ ++ if (hw->tbi_compatibility_on == 1) ++ rctl |= E1000_RCTL_SBP; ++ else ++ rctl &= ~E1000_RCTL_SBP; ++ ++ if (adapter->netdev->mtu <= ETH_DATA_LEN) ++ rctl &= ~E1000_RCTL_LPE; ++ else ++ rctl |= E1000_RCTL_LPE; ++ ++ /* Setup buffer sizes */ ++ /* We can now specify buffers in 1K increments. ++ * BSIZE and BSEX are ignored in this case. */ ++ rctl &= ~E1000_RCTL_SZ_4096; ++ rctl |= E1000_RCTL_BSEX; ++ switch (adapter->rx_buffer_len) { ++ case E1000_RXBUFFER_256: ++ rctl |= E1000_RCTL_SZ_256; + rctl &= ~E1000_RCTL_BSEX; + break; +- case E1000_RXBUFFER_4096: +- rctl |= E1000_RCTL_SZ_4096; +- break; +- case E1000_RXBUFFER_8192: +- rctl |= E1000_RCTL_SZ_8192; +- break; +- case E1000_RXBUFFER_16384: +- rctl |= E1000_RCTL_SZ_16384; +- break; +- } +- } ++ case E1000_RXBUFFER_2048: ++ default: ++ rctl |= E1000_RCTL_SZ_2048; ++ rctl &= ~E1000_RCTL_BSEX; ++ break; ++ case E1000_RXBUFFER_4096: ++ rctl |= E1000_RCTL_SZ_4096; ++ break; ++ case E1000_RXBUFFER_8192: ++ rctl |= E1000_RCTL_SZ_8192; ++ break; ++ case E1000_RXBUFFER_16384: ++ rctl |= E1000_RCTL_SZ_16384; ++ break; ++ } + +-#ifdef CONFIG_E1000_PACKET_SPLIT +- /* 82571 and greater support packet-split where the protocol +- * header is placed in skb->data and the packet data is +- * placed in pages hanging off of skb_shinfo(skb)->nr_frags. +- * In the case of a non-split, skb->data is linearly filled, +- * followed by the page buffers. Therefore, skb->data is +- * sized to hold the largest protocol header. +- */ +- pages = PAGE_USE_COUNT(adapter->netdev->mtu); +- if ((adapter->hw.mac_type > iegbe_82547_rev_2) && (pages <= 0x3) && +- PAGE_SIZE <= 0x4000) { +- adapter->rx_ps_pages = pages; +- } else { ++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT ++ /* 82571 and greater support packet-split where the protocol ++ * header is placed in skb->data and the packet data is ++ * placed in pages hanging off of skb_shinfo(skb)->nr_frags. ++ * In the case of a non-split, skb->data is linearly filled, ++ * followed by the page buffers. Therefore, skb->data is ++ * sized to hold the largest protocol header. ++ */ ++ pages = PAGE_USE_COUNT(adapter->netdev->mtu); ++ if ((hw->mac_type >= iegbe_82571) && (pages <= 3) && ++ PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE)) ++ adapter->rx_ps_pages = pages; ++ else + adapter->rx_ps_pages = 0; +- } + #endif +- if (adapter->rx_ps_pages) { +- /* Configure extra packet-split registers */ +- rfctl = E1000_READ_REG(&adapter->hw, RFCTL); +- rfctl |= E1000_RFCTL_EXTEN; +- /* disable IPv6 packet split support */ +- rfctl |= E1000_RFCTL_IPV6_DIS; +- E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl); +- +- rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC; +- +- psrctl |= adapter->rx_ps_bsize0 >> +- E1000_PSRCTL_BSIZE0_SHIFT; +- +- switch (adapter->rx_ps_pages) { +- case 0x3: +- psrctl |= PAGE_SIZE << +- E1000_PSRCTL_BSIZE3_SHIFT; +- case 0x2: +- psrctl |= PAGE_SIZE << +- E1000_PSRCTL_BSIZE2_SHIFT; +- case 0x1: +- psrctl |= PAGE_SIZE >> +- E1000_PSRCTL_BSIZE1_SHIFT; +- break; +- } ++ if (adapter->rx_ps_pages) { ++ /* Configure extra packet-split registers */ ++ rfctl = E1000_READ_REG(&adapter->hw, RFCTL); ++ rfctl |= E1000_RFCTL_EXTEN; ++ /* disable IPv6 packet split support */ ++ rfctl |= (E1000_RFCTL_IPV6_EX_DIS | ++ E1000_RFCTL_NEW_IPV6_EXT_DIS); ++ ++ rctl |= E1000_RCTL_DTYP_PS; ++ ++ psrctl |= adapter->rx_ps_bsize0 >> ++ E1000_PSRCTL_BSIZE0_SHIFT; ++ ++ switch (adapter->rx_ps_pages) { ++ case 3: ++ psrctl |= PAGE_SIZE << ++ E1000_PSRCTL_BSIZE3_SHIFT; ++ case 2: ++ psrctl |= PAGE_SIZE << ++ E1000_PSRCTL_BSIZE2_SHIFT; ++ case 1: ++ psrctl |= PAGE_SIZE >> ++ E1000_PSRCTL_BSIZE1_SHIFT; ++ break; ++ } + +- E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl); +- } ++ E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl); ++ } + +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + } + + /** +@@ -1873,145 +1768,87 @@ iegbe_setup_rctl(struct iegbe_adapter *a + * Configure the Rx unit of the MAC after a reset. + **/ + +-static void +-iegbe_configure_rx(struct iegbe_adapter *adapter) ++static void iegbe_configure_rx(struct iegbe_adapter *adapter) + { +- uint64_t rdba; +- struct iegbe_hw *hw = &adapter->hw; +- uint32_t rdlen, rctl, rxcsum, ctrl_ext; +-#ifdef CONFIG_E1000_MQ +- uint32_t reta, mrqc; +- int i; +-#endif ++ u64 rdba; ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 rdlen, rctl, rxcsum, ctrl_ext; + +- if (adapter->rx_ps_pages) { ++ if (adapter->rx_ps_pages) { + rdlen = adapter->rx_ring[0].count * +- sizeof(union iegbe_rx_desc_packet_split); +- adapter->clean_rx = iegbe_clean_rx_irq_ps; +- adapter->alloc_rx_buf = iegbe_alloc_rx_buffers_ps; +- } else { ++ sizeof(union iegbe_rx_desc_packet_split); ++ adapter->clean_rx = iegbe_clean_rx_irq_ps; ++ adapter->alloc_rx_buf = iegbe_alloc_rx_buffers_ps; ++ } else { + rdlen = adapter->rx_ring[0].count * +- sizeof(struct iegbe_rx_desc); +- adapter->clean_rx = iegbe_clean_rx_irq; +- adapter->alloc_rx_buf = iegbe_alloc_rx_buffers; +- } ++ sizeof(struct iegbe_rx_desc); ++ adapter->clean_rx = iegbe_clean_rx_irq; ++ adapter->alloc_rx_buf = iegbe_alloc_rx_buffers; ++ } + +- /* disable receives while setting up the descriptors */ +- rctl = E1000_READ_REG(hw, RCTL); +- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); ++ /* disable receives while setting up the descriptors */ ++ rctl = E1000_READ_REG(hw, RCTL); ++ E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); + +- /* set the Receive Delay Timer Register */ +- E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay); ++ /* set the Receive Delay Timer Register */ ++ E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay); + +- if (hw->mac_type >= iegbe_82540) { +- E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); +- if(adapter->itr > 0x1) { +- E1000_WRITE_REG(hw, ITR, +- 0x3b9aca00 / (adapter->itr * 0x100)); ++ if (hw->mac_type >= iegbe_82540) { ++ E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); ++ if (adapter->itr_setting != 0) ++ E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (adapter->itr * 256)); + } +- } + +- if (hw->mac_type >= iegbe_82571) { +- /* Reset delay timers after every interrupt */ +- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); +- ctrl_ext |= E1000_CTRL_EXT_CANC; +- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); +- E1000_WRITE_FLUSH(hw); +- } ++ if (hw->mac_type >= iegbe_82571) { ++ /* Reset delay timers after every interrupt */ ++ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); ++ ctrl_ext |= E1000_CTRL_EXT_CANC; ++ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); ++ E1000_WRITE_FLUSH(hw); ++ } + + /* Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring */ +- switch (adapter->num_queues) { +-#ifdef CONFIG_E1000_MQ +- case 0x2: +- rdba = adapter->rx_ring[0x1].dma; +- E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL)); +- E1000_WRITE_REG(hw, RDBAH1, (rdba >> 0x20)); +- E1000_WRITE_REG(hw, RDLEN1, rdlen); +- E1000_WRITE_REG(hw, RDH1, 0); +- E1000_WRITE_REG(hw, RDT1, 0); +- adapter->rx_ring[1].rdh = E1000_RDH1; +- adapter->rx_ring[1].rdt = E1000_RDT1; +- /* Fall Through */ +-#endif +- case 0x1: +- default: ++ switch (adapter->num_rx_queues) { ++ case 1: ++ default: + rdba = adapter->rx_ring[0].dma; +- E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL)); ++ E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL)); + E1000_WRITE_REG(hw, RDBAH, (rdba >> 0x20)); +- E1000_WRITE_REG(hw, RDLEN, rdlen); +- E1000_WRITE_REG(hw, RDH, 0); +- E1000_WRITE_REG(hw, RDT, 0); +- adapter->rx_ring[0].rdh = E1000_RDH; +- adapter->rx_ring[0].rdt = E1000_RDT; +- break; +- } ++ E1000_WRITE_REG(hw, RDLEN, rdlen); ++ adapter->rx_ring[0].rdh = ((hw->mac_type >= iegbe_82543) ? E1000_RDH : E1000_82542_RDH); ++ adapter->rx_ring[0].rdt = ((hw->mac_type >= iegbe_82543) ? E1000_RDT : E1000_82542_RDT); ++ break; ++ } + +-#ifdef CONFIG_E1000_MQ +- if (adapter->num_queues > 0x1) { +- uint32_t random[0xa]; +- +- get_random_bytes(&random[0], FORTY); +- +- if (hw->mac_type <= iegbe_82572) { +- E1000_WRITE_REG(hw, RSSIR, 0); +- E1000_WRITE_REG(hw, RSSIM, 0); +- } + +- switch (adapter->num_queues) { +- case 0x2: +- default: +- reta = 0x00800080; +- mrqc = E1000_MRQC_ENABLE_RSS_2Q; +- break; +- } +- +- /* Fill out redirection table */ +- for (i = 0; i < 0x20; i++) +- E1000_WRITE_REG_ARRAY(hw, RETA, i, reta); +- /* Fill out hash function seeds */ +- for (i = 0; i < 0xa; i++) +- E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]); +- +- mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 | +- E1000_MRQC_RSS_FIELD_IPV4_TCP); +- E1000_WRITE_REG(hw, MRQC, mrqc); +- } +- +- /* Multiqueue and packet checksumming are mutually exclusive. */ +- if (hw->mac_type >= iegbe_82571) { +- rxcsum = E1000_READ_REG(hw, RXCSUM); +- rxcsum |= E1000_RXCSUM_PCSD; +- E1000_WRITE_REG(hw, RXCSUM, rxcsum); +- } +- +-#else ++ /* Enable 82543 Receive Checksum Offload for TCP and UDP */ ++ if (hw->mac_type >= iegbe_82543) { ++ rxcsum = E1000_READ_REG(hw, RXCSUM); ++ if(adapter->rx_csum == TRUE) { ++ rxcsum |= E1000_RXCSUM_TUOFL; ++ ++ /* Enable 82571 IPv4 payload checksum for UDP fragments ++ * Must be used in conjunction with packet-split. */ ++ if ((hw->mac_type >= iegbe_82571) && ++ (adapter->rx_ps_pages)) { ++ rxcsum |= E1000_RXCSUM_IPPCSE; ++ } ++ } else { ++ rxcsum &= ~E1000_RXCSUM_TUOFL; ++ /* don't need to clear IPPCSE as it defaults to 0 */ ++ } ++ E1000_WRITE_REG(hw, RXCSUM, rxcsum); ++ } + +- /* Enable 82543 Receive Checksum Offload for TCP and UDP */ +- if (hw->mac_type >= iegbe_82543) { +- rxcsum = E1000_READ_REG(hw, RXCSUM); +- if(adapter->rx_csum == TRUE) { +- rxcsum |= E1000_RXCSUM_TUOFL; +- +- /* Enable 82571 IPv4 payload checksum for UDP fragments +- * Must be used in conjunction with packet-split. */ +- if ((hw->mac_type >= iegbe_82571) && +- (adapter->rx_ps_pages)) { +- rxcsum |= E1000_RXCSUM_IPPCSE; +- } +- } else { +- rxcsum &= ~E1000_RXCSUM_TUOFL; +- /* don't need to clear IPPCSE as it defaults to 0 */ +- } +- E1000_WRITE_REG(hw, RXCSUM, rxcsum); +- } +-#endif /* CONFIG_E1000_MQ */ ++ /* enable early receives on 82573, only takes effect if using > 2048 ++ * byte total frame size. for example only for jumbo frames */ ++#define E1000_ERT_2048 0x100 ++ if (hw->mac_type == iegbe_82573) ++ E1000_WRITE_REG(&adapter->hw, ERT, E1000_ERT_2048); + +- if (hw->mac_type == iegbe_82573) { +- E1000_WRITE_REG(hw, ERT, 0x0100); +- } + /* Enable Receives */ +- E1000_WRITE_REG(hw, RCTL, rctl); ++ E1000_WRITE_REG(hw, RCTL, rctl); + } + + /** +@@ -2022,20 +1859,19 @@ iegbe_configure_rx(struct iegbe_adapter + * Free all transmit software resources + **/ + +-void +-iegbe_free_tx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring) + { +- struct pci_dev *pdev = adapter->pdev; ++ struct pci_dev *pdev = adapter->pdev; + +- iegbe_clean_tx_ring(adapter, tx_ring); ++ iegbe_clean_tx_ring(adapter, tx_ring); + +- vfree(tx_ring->buffer_info); +- tx_ring->buffer_info = NULL; ++ vfree(tx_ring->buffer_info); ++ tx_ring->buffer_info = NULL; + +- pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma); ++ pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma); + +- tx_ring->desc = NULL; ++ tx_ring->desc = NULL; + } + + /** +@@ -2048,85 +1884,29 @@ iegbe_free_tx_resources(struct iegbe_ada + void + iegbe_free_all_tx_resources(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0x0; i < adapter->num_tx_queues; i++) + iegbe_free_tx_resources(adapter, &adapter->tx_ring[i]); + } + + static inline void + iegbe_unmap_and_free_tx_resource(struct iegbe_adapter *adapter, +- struct iegbe_buffer *buffer_info) +-{ +- if(buffer_info->dma) { +- pci_unmap_page(adapter->pdev, +- buffer_info->dma, +- buffer_info->length, +- PCI_DMA_TODEVICE); +- buffer_info->dma = 0; +- } +- if(buffer_info->skb) { +- dev_kfree_skb_any(buffer_info->skb); +- buffer_info->skb = NULL; +- } +-} +- +-#ifdef IEGBE_GBE_WORKAROUND +-/** +- * iegbe_clean_tx_ring_partial - Free Tx Buffers without using the DD +- * bit in the descriptor +- * @adapter: board private structure +- * @tx_ring: ring to be cleaned +- **/ +-static void iegbe_clean_tx_ring_partial(struct iegbe_adapter *adapter, +- struct iegbe_tx_ring *tx_ring) ++ struct iegbe_buffer *buffer_info) + { +- struct iegbe_buffer *buffer_info; +- struct iegbe_tx_desc *tx_desc; +- struct net_device *netdev = adapter->netdev; +- unsigned int i; +- unsigned tail; +- unsigned head; +- int cleaned = FALSE; +- +- tail = readl(adapter->hw.hw_addr + tx_ring->tdt); +- head = readl(adapter->hw.hw_addr + tx_ring->tdh); +- +- if (head != tail) { +- adapter->stats.tx_hnet++; +- } +- if (head != tx_ring->next_to_use) { +- adapter->stats.tx_hnentu++; +- } +- /* Free all the Tx ring sk_buffs from next_to_clean up until +- * the current head pointer +- */ +- i = tx_ring->next_to_clean; +- while(i != head) { +- cleaned = TRUE; +- tx_desc = E1000_TX_DESC(*tx_ring, i); +- +- buffer_info = &tx_ring->buffer_info[i]; +- iegbe_unmap_and_free_tx_resource(adapter, buffer_info); +- +- tx_desc->upper.data = 0; +- +- if (unlikely(++i == tx_ring->count)) { i = 0; } +- +- } +- tx_ring->next_to_clean = head; +- +- spin_lock(&tx_ring->tx_lock); +- +- /* Wake up the queue if it's currently stopped */ +- if (unlikely(cleaned && netif_queue_stopped(netdev) && +- netif_carrier_ok(netdev))) { +- netif_wake_queue(netdev); ++ if(buffer_info->dma) { ++ pci_unmap_page(adapter->pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_TODEVICE); ++ buffer_info->dma = 0x0; ++ } ++ if(buffer_info->skb) { ++ dev_kfree_skb_any(buffer_info->skb); ++ buffer_info->skb = NULL; + } +- +- spin_unlock(&tx_ring->tx_lock); + } +-#endif ++ + + /** + * iegbe_clean_tx_ring - Free Tx Buffers +@@ -2134,38 +1914,34 @@ static void iegbe_clean_tx_ring_partial( + * @tx_ring: ring to be cleaned + **/ + +-static void +-iegbe_clean_tx_ring(struct iegbe_adapter *adapter, ++static void iegbe_clean_tx_ring(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring) + { +- struct iegbe_buffer *buffer_info; +- unsigned long size; +- unsigned int i; +- +- /* Free all the Tx ring sk_buffs */ ++ struct iegbe_hw *hw = &adapter->hw; ++ struct iegbe_buffer *buffer_info; ++ unsigned long size; ++ unsigned int i; + +- if (likely(tx_ring->previous_buffer_info.skb != NULL)) { +- iegbe_unmap_and_free_tx_resource(adapter, +- &tx_ring->previous_buffer_info); +- } ++ /* Free all the Tx ring sk_buffs */ + + for (i = 0; i < tx_ring->count; i++) { +- buffer_info = &tx_ring->buffer_info[i]; +- iegbe_unmap_and_free_tx_resource(adapter, buffer_info); +- } ++ buffer_info = &tx_ring->buffer_info[i]; ++ iegbe_unmap_and_free_tx_resource(adapter, buffer_info); ++ } + +- size = sizeof(struct iegbe_buffer) * tx_ring->count; ++ size = sizeof(struct iegbe_buffer) * tx_ring->count; + memset(tx_ring->buffer_info, 0, size); + +- /* Zero out the descriptor ring */ ++ /* Zero out the descriptor ring */ + + memset(tx_ring->desc, 0, tx_ring->size); + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; ++ tx_ring->last_tx_tso = 0; + +- writel(0, adapter->hw.hw_addr + tx_ring->tdh); +- writel(0, adapter->hw.hw_addr + tx_ring->tdt); ++ writel(0, hw->hw_addr + tx_ring->tdh); ++ writel(0, hw->hw_addr + tx_ring->tdt); + } + + /** +@@ -2173,12 +1949,11 @@ iegbe_clean_tx_ring(struct iegbe_adapter + * @adapter: board private structure + **/ + +-static void +-iegbe_clean_all_tx_rings(struct iegbe_adapter *adapter) ++static void iegbe_clean_all_tx_rings(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_tx_queues; i++) + iegbe_clean_tx_ring(adapter, &adapter->tx_ring[i]); + } + +@@ -2190,24 +1965,23 @@ iegbe_clean_all_tx_rings(struct iegbe_ad + * Free all receive software resources + **/ + +-void +-iegbe_free_rx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring) + { +- struct pci_dev *pdev = adapter->pdev; ++ struct pci_dev *pdev = adapter->pdev; + +- iegbe_clean_rx_ring(adapter, rx_ring); ++ iegbe_clean_rx_ring(adapter, rx_ring); + +- vfree(rx_ring->buffer_info); +- rx_ring->buffer_info = NULL; +- kfree(rx_ring->ps_page); +- rx_ring->ps_page = NULL; +- kfree(rx_ring->ps_page_dma); +- rx_ring->ps_page_dma = NULL; ++ vfree(rx_ring->buffer_info); ++ rx_ring->buffer_info = NULL; ++ kfree(rx_ring->ps_page); ++ rx_ring->ps_page = NULL; ++ kfree(rx_ring->ps_page_dma); ++ rx_ring->ps_page_dma = NULL; + +- pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); ++ pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); + +- rx_ring->desc = NULL; ++ rx_ring->desc = NULL; + } + + /** +@@ -2217,12 +1991,11 @@ iegbe_free_rx_resources(struct iegbe_ada + * Free all receive software resources + **/ + +-void +-iegbe_free_all_rx_resources(struct iegbe_adapter *adapter) ++void iegbe_free_all_rx_resources(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_rx_queues; i++) + iegbe_free_rx_resources(adapter, &adapter->rx_ring[i]); + } + +@@ -2232,60 +2005,59 @@ iegbe_free_all_rx_resources(struct iegbe + * @rx_ring: ring to free buffers from + **/ + +-static void +-iegbe_clean_rx_ring(struct iegbe_adapter *adapter, ++static void iegbe_clean_rx_ring(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring) + { +- struct iegbe_buffer *buffer_info; +- struct iegbe_ps_page *ps_page; +- struct iegbe_ps_page_dma *ps_page_dma; +- struct pci_dev *pdev = adapter->pdev; +- unsigned long size; +- unsigned int i, j; +- +- /* Free all the Rx ring sk_buffs */ ++ struct iegbe_hw *hw = &adapter->hw; ++ struct iegbe_buffer *buffer_info; ++ struct iegbe_ps_page *ps_page; ++ struct iegbe_ps_page_dma *ps_page_dma; ++ struct pci_dev *pdev = adapter->pdev; ++ unsigned long size; ++ unsigned int i, j; ++ ++ /* Free all the Rx ring sk_buffs */ ++ ++ for (i = 0; i < rx_ring->count; i++) { ++ buffer_info = &rx_ring->buffer_info[i]; ++ if(buffer_info->skb) { ++ pci_unmap_single(pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_FROMDEVICE); + +- for(i = 0; i < rx_ring->count; i++) { +- buffer_info = &rx_ring->buffer_info[i]; +- if(buffer_info->skb) { +- ps_page = &rx_ring->ps_page[i]; +- ps_page_dma = &rx_ring->ps_page_dma[i]; +- pci_unmap_single(pdev, +- buffer_info->dma, +- buffer_info->length, +- PCI_DMA_FROMDEVICE); +- +- dev_kfree_skb(buffer_info->skb); +- buffer_info->skb = NULL; +- +- for(j = 0; j < adapter->rx_ps_pages; j++) { +- if(!ps_page->ps_page[j]) { break; } +- pci_unmap_single(pdev, +- ps_page_dma->ps_page_dma[j], +- PAGE_SIZE, PCI_DMA_FROMDEVICE); +- ps_page_dma->ps_page_dma[j] = 0; +- put_page(ps_page->ps_page[j]); +- ps_page->ps_page[j] = NULL; +- } ++ dev_kfree_skb(buffer_info->skb); ++ buffer_info->skb = NULL; + } +- } ++ ps_page = &rx_ring->ps_page[i]; ++ ps_page_dma = &rx_ring->ps_page_dma[i]; ++ for (j = 0; j < adapter->rx_ps_pages; j++) { ++ if (!ps_page->ps_page[j]) break; ++ pci_unmap_page(pdev, ++ ps_page_dma->ps_page_dma[j], ++ PAGE_SIZE, PCI_DMA_FROMDEVICE); ++ ps_page_dma->ps_page_dma[j] = 0; ++ put_page(ps_page->ps_page[j]); ++ ps_page->ps_page[j] = NULL; ++ } ++ } + +- size = sizeof(struct iegbe_buffer) * rx_ring->count; ++ size = sizeof(struct iegbe_buffer) * rx_ring->count; + memset(rx_ring->buffer_info, 0, size); +- size = sizeof(struct iegbe_ps_page) * rx_ring->count; ++ size = sizeof(struct iegbe_ps_page) * rx_ring->count; + memset(rx_ring->ps_page, 0, size); +- size = sizeof(struct iegbe_ps_page_dma) * rx_ring->count; ++ size = sizeof(struct iegbe_ps_page_dma) * rx_ring->count; + memset(rx_ring->ps_page_dma, 0, size); + +- /* Zero out the descriptor ring */ ++ /* Zero out the descriptor ring */ + + memset(rx_ring->desc, 0, rx_ring->size); + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + +- writel(0, adapter->hw.hw_addr + rx_ring->rdh); +- writel(0, adapter->hw.hw_addr + rx_ring->rdt); ++ writel(0, hw->hw_addr + rx_ring->rdh); ++ writel(0, hw->hw_addr + rx_ring->rdt); + } + + /** +@@ -2293,60 +2065,54 @@ iegbe_clean_rx_ring(struct iegbe_adapter + * @adapter: board private structure + **/ + +-static void +-iegbe_clean_all_rx_rings(struct iegbe_adapter *adapter) ++static void iegbe_clean_all_rx_rings(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_rx_queues; i++) + iegbe_clean_rx_ring(adapter, &adapter->rx_ring[i]); + } + + /* The 82542 2.0 (revision 2) needs to have the receive unit in reset + * and memory write and invalidate disabled for certain operations + */ +-static void +-iegbe_enter_82542_rst(struct iegbe_adapter *adapter) ++static void iegbe_enter_82542_rst(struct iegbe_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- uint32_t rctl; ++ struct net_device *netdev = adapter->netdev; ++ uint32_t rctl; + +- iegbe_pci_clear_mwi(&adapter->hw); ++ iegbe_pci_clear_mwi(&adapter->hw); + +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl |= E1000_RCTL_RST; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- E1000_WRITE_FLUSH(&adapter->hw); ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl |= E1000_RCTL_RST; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ E1000_WRITE_FLUSH(&adapter->hw); + mdelay(0x5); + + if(netif_running(netdev)) { +- iegbe_clean_all_rx_rings(adapter); +-} ++ iegbe_clean_all_rx_rings(adapter); ++ } + } + + static void + iegbe_leave_82542_rst(struct iegbe_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- uint32_t rctl; ++ struct net_device *netdev = adapter->netdev; ++ uint32_t rctl; + +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl &= ~E1000_RCTL_RST; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- E1000_WRITE_FLUSH(&adapter->hw); ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl &= ~E1000_RCTL_RST; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ E1000_WRITE_FLUSH(&adapter->hw); + mdelay(0x5); + + if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE) { +- iegbe_pci_set_mwi(&adapter->hw); ++ iegbe_pci_set_mwi(&adapter->hw); + } + if(netif_running(netdev)) { ++ struct iegbe_rx_ring *ring = &adapter->rx_ring[0x0]; + iegbe_configure_rx(adapter); +-#ifdef IEGBE_GBE_WORKAROUND +- iegbe_alloc_rx_buffers(adapter, &adapter->rx_ring[0], +- IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS + 1); +-#else +- iegbe_alloc_rx_buffers(adapter, &adapter->rx_ring[0]); +-#endif ++ adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring)); + } + } + +@@ -2358,133 +2124,153 @@ iegbe_leave_82542_rst(struct iegbe_adapt + * Returns 0 on success, negative on failure + **/ + +-static int +-iegbe_set_mac(struct net_device *netdev, void *p) ++static int iegbe_set_mac(struct net_device *netdev, void *p) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- struct sockaddr *addr = p; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct sockaddr *addr = p; + + if(!is_valid_ether_addr(addr->sa_data)) { +- return -EADDRNOTAVAIL; ++ return -EADDRNOTAVAIL; + } +- /* 82542 2.0 needs to be in reset to write receive address registers */ ++ /* 82542 2.0 needs to be in reset to write receive address registers */ + + if(adapter->hw.mac_type == iegbe_82542_rev2_0) { +- iegbe_enter_82542_rst(adapter); ++ iegbe_enter_82542_rst(adapter); + } +- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); +- memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); ++ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); ++ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + +- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0); ++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0x0); + +- /* With 82571 controllers, LAA may be overwritten (with the default) +- * due to controller reset from the other port. */ +- if (adapter->hw.mac_type == iegbe_82571) { +- /* activate the work around */ ++ /* With 82571 controllers, LAA may be overwritten (with the default) ++ * due to controller reset from the other port. */ ++ if (adapter->hw.mac_type == iegbe_82571) { ++ /* activate the work around */ + adapter->hw.laa_is_present = 0x1; + +- /* Hold a copy of the LAA in RAR[14] This is done so that +- * between the time RAR[0] gets clobbered and the time it +- * gets fixed (in iegbe_watchdog), the actual LAA is in one +- * of the RARs and no incoming packets directed to this port +- * are dropped. Eventaully the LAA will be in RAR[0] and +- * RAR[14] */ +- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, ++ /* Hold a copy of the LAA in RAR[14] This is done so that ++ * between the time RAR[0] gets clobbered and the time it ++ * gets fixed (in iegbe_watchdog), the actual LAA is in one ++ * of the RARs and no incoming packets directed to this port ++ * are dropped. Eventaully the LAA will be in RAR[0] and ++ * RAR[14] */ ++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, + E1000_RAR_ENTRIES - 0x1); +- } ++ } + + if(adapter->hw.mac_type == iegbe_82542_rev2_0) { +- iegbe_leave_82542_rst(adapter); ++ iegbe_leave_82542_rst(adapter); + } +- return 0; ++ return 0x0; + } + + /** +- * iegbe_set_multi - Multicast and Promiscuous mode set ++ * iegbe_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set + * @netdev: network interface device structure + * +- * The set_multi entry point is called whenever the multicast address +- * list or the network interface flags are updated. This routine is +- * responsible for configuring the hardware for proper multicast, ++ * The set_rx_mode entry point is called whenever the unicast or multicast ++ * address lists or the network interface flags are updated. This routine is ++ * responsible for configuring the hardware for proper unicast, multicast, + * promiscuous mode, and all-multi behavior. + **/ + +-static void +-iegbe_set_multi(struct net_device *netdev) ++static void iegbe_set_rx_mode(struct net_device *netdev) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); + struct iegbe_hw *hw = &adapter->hw; +- struct dev_mc_list *mc_ptr; +- uint32_t rctl; +- uint32_t hash_value; ++ struct dev_addr_list *uc_ptr; ++ struct dev_addr_list *mc_ptr; ++ u32 rctl; ++ u32 hash_value; + int i, rar_entries = E1000_RAR_ENTRIES; ++int mta_reg_count = E1000_NUM_MTA_REGISTERS; + + /* reserve RAR[14] for LAA over-write work-around */ +- if (adapter->hw.mac_type == iegbe_82571) { ++ if (hw->mac_type == iegbe_82571) + rar_entries--; +- } ++ + /* Check for Promiscuous and All Multicast modes */ + +- rctl = E1000_READ_REG(hw, RCTL); ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); + + if (netdev->flags & IFF_PROMISC) { + rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); +- } else if (netdev->flags & IFF_ALLMULTI) { +- rctl |= E1000_RCTL_MPE; +- rctl &= ~E1000_RCTL_UPE; ++ rctl &= ~E1000_RCTL_VFE; + } else { +- rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); ++ if (netdev->flags & IFF_ALLMULTI) { ++ rctl |= E1000_RCTL_MPE; ++ } else { ++ rctl &= ~E1000_RCTL_MPE; ++ } ++ } ++ ++ uc_ptr = NULL; ++ if (netdev->uc_count > rar_entries - 1) { ++ rctl |= E1000_RCTL_UPE; ++ } else if (!(netdev->flags & IFF_PROMISC)) { ++ rctl &= ~E1000_RCTL_UPE; ++ uc_ptr = netdev->uc_list; + } + +- E1000_WRITE_REG(hw, RCTL, rctl); ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + + /* 82542 2.0 needs to be in reset to write receive address registers */ + +- if (hw->mac_type == iegbe_82542_rev2_0) { ++ if (hw->mac_type == iegbe_82542_rev2_0) + iegbe_enter_82542_rst(adapter); +- } +- /* load the first 14 multicast address into the exact filters 1-14 ++ ++ /* load the first 14 addresses into the exact filters 1-14. Unicast ++ * addresses take precedence to avoid disabling unicast filtering ++ * when possible. ++ * + * RAR 0 is used for the station MAC adddress + * if there are not 14 addresses, go ahead and clear the filters + * -- with 82571 controllers only 0-13 entries are filled here + */ + mc_ptr = netdev->mc_list; + +- for (i = 0x1; i < rar_entries; i++) { +- if (mc_ptr) { +- iegbe_rar_set(hw, mc_ptr->dmi_addr, i); ++ for (i = 1; i < rar_entries; i++) { ++ if (uc_ptr) { ++ iegbe_rar_set(hw, uc_ptr->da_addr, i); ++ uc_ptr = uc_ptr->next; ++ } else if (mc_ptr) { ++ iegbe_rar_set(hw, mc_ptr->da_addr, i); + mc_ptr = mc_ptr->next; + } else { +- E1000_WRITE_REG_ARRAY(hw, RA, i << 0x1, 0); +- E1000_WRITE_REG_ARRAY(hw, RA, (i << 0x1) + 0x1, 0); ++ E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0); ++ E1000_WRITE_FLUSH(&adapter->hw); + } + } ++ WARN_ON(uc_ptr != NULL); + + /* clear the old settings from the multicast hash table */ + +- for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++) ++ for (i = 0; i < mta_reg_count; i++) { + E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ } + + /* load any remaining addresses into the hash table */ + + for (; mc_ptr; mc_ptr = mc_ptr->next) { +- hash_value = iegbe_hash_mc_addr(hw, mc_ptr->dmi_addr); ++ hash_value = iegbe_hash_mc_addr(hw, mc_ptr->da_addr); + iegbe_mta_set(hw, hash_value); + } + +- if (hw->mac_type == iegbe_82542_rev2_0) { ++ if (hw->mac_type == iegbe_82542_rev2_0) + iegbe_leave_82542_rst(adapter); + } +-} + + /* Need to wait a few seconds after link up to get diagnostic information from + * the phy */ + +-static void +-iegbe_update_phy_info(unsigned long data) ++static void iegbe_update_phy_info(unsigned long data) + { +- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; +- iegbe_phy_get_info(&adapter->hw, &adapter->phy_info); ++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; ++ struct iegbe_hw *hw = &adapter->hw; ++ iegbe_phy_get_info(hw, &adapter->phy_info); + } + + /** +@@ -2492,54 +2278,54 @@ iegbe_update_phy_info(unsigned long data + * @data: pointer to adapter cast into an unsigned long + **/ + +-static void +-iegbe_82547_tx_fifo_stall(unsigned long data) ++static void iegbe_82547_tx_fifo_stall(unsigned long data) + { +- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; +- struct net_device *netdev = adapter->netdev; +- uint32_t tctl; ++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; ++ struct net_device *netdev = adapter->netdev; ++ u32 tctl; + +- if(atomic_read(&adapter->tx_fifo_stall)) { +- if((E1000_READ_REG(&adapter->hw, TDT) == +- E1000_READ_REG(&adapter->hw, TDH)) && +- (E1000_READ_REG(&adapter->hw, TDFT) == +- E1000_READ_REG(&adapter->hw, TDFH)) && +- (E1000_READ_REG(&adapter->hw, TDFTS) == +- E1000_READ_REG(&adapter->hw, TDFHS))) { +- tctl = E1000_READ_REG(&adapter->hw, TCTL); +- E1000_WRITE_REG(&adapter->hw, TCTL, +- tctl & ~E1000_TCTL_EN); +- E1000_WRITE_REG(&adapter->hw, TDFT, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TDFH, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TDFTS, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TDFHS, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TCTL, tctl); +- E1000_WRITE_FLUSH(&adapter->hw); +- +- adapter->tx_fifo_head = 0; +- atomic_set(&adapter->tx_fifo_stall, 0); +- netif_wake_queue(netdev); +- } else { ++ if(atomic_read(&adapter->tx_fifo_stall)) { ++ if((E1000_READ_REG(&adapter->hw, TDT) == ++ E1000_READ_REG(&adapter->hw, TDH)) && ++ (E1000_READ_REG(&adapter->hw, TDFT) == ++ E1000_READ_REG(&adapter->hw, TDFH)) && ++ (E1000_READ_REG(&adapter->hw, TDFTS) == ++ E1000_READ_REG(&adapter->hw, TDFHS))) { ++ tctl = E1000_READ_REG(&adapter->hw, TCTL); ++ E1000_WRITE_REG(&adapter->hw, TCTL, ++ tctl & ~E1000_TCTL_EN); ++ E1000_WRITE_REG(&adapter->hw, TDFT, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TDFH, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TDFTS, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TDFHS, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TCTL, tctl); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ ++ adapter->tx_fifo_head = 0x0; ++ atomic_set(&adapter->tx_fifo_stall, 0x0); ++ netif_wake_queue(netdev); ++ } else { + mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 0x1); +- } +- } ++ } ++ } + } + ++ + /** + * iegbe_watchdog - Timer Call-back + * @data: pointer to adapter cast into an unsigned long + **/ +-static void +-iegbe_watchdog(unsigned long data) ++static void iegbe_watchdog(unsigned long data) + { +- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; +- struct net_device *netdev = adapter->netdev; +- struct iegbe_tx_ring *txdr = &adapter->tx_ring[0]; +- uint32_t link; ++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct iegbe_tx_ring *txdr = adapter->tx_ring; ++ u32 link, tctl; + + /* + * Test the PHY for link status on icp_xxxx MACs. +@@ -2547,123 +2333,305 @@ iegbe_watchdog(unsigned long data) + * in the adapter->hw structure, then set hw->get_link_status = 1 + */ + if(adapter->hw.mac_type == iegbe_icp_xxxx) { +- int isUp = 0; ++ int isUp = 0x0; + int32_t ret_val; + + ret_val = iegbe_oem_phy_is_link_up(&adapter->hw, &isUp); + if(ret_val != E1000_SUCCESS) { +- isUp = 0; +- } ++ isUp = 0x0; ++ } + if(isUp != adapter->hw.icp_xxxx_is_link_up) { + adapter->hw.get_link_status = 0x1; + } + } + +- iegbe_check_for_link(&adapter->hw); +- if (adapter->hw.mac_type == iegbe_82573) { +- iegbe_enable_tx_pkt_filtering(&adapter->hw); ++ iegbe_check_for_link(&adapter->hw); ++ if (adapter->hw.mac_type == iegbe_82573) { ++ iegbe_enable_tx_pkt_filtering(&adapter->hw); + #ifdef NETIF_F_HW_VLAN_TX + if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id) { +- iegbe_update_mng_vlan(adapter); ++ iegbe_update_mng_vlan(adapter); + } + #endif +- } ++ } + +- if ((adapter->hw.media_type == iegbe_media_type_internal_serdes) && +- !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) { +- link = !adapter->hw.serdes_link_down; +- } else { ++ if ((adapter->hw.media_type == iegbe_media_type_internal_serdes) && ++ !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) { ++ link = !adapter->hw.serdes_link_down; ++ } else { + +- if(adapter->hw.mac_type != iegbe_icp_xxxx) { +- link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU; +- } else { +- int isUp = 0; ++ if(adapter->hw.mac_type != iegbe_icp_xxxx) { ++ link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU; ++ } else { ++ int isUp = 0x0; + if(iegbe_oem_phy_is_link_up(&adapter->hw, &isUp) != E1000_SUCCESS) { +- isUp = 0; ++ isUp = 0x0; + } +- link = isUp; +- } +- } ++ link = isUp; ++ } ++ } + +- if (link) { +- if (!netif_carrier_ok(netdev)) { +- iegbe_get_speed_and_duplex(&adapter->hw, +- &adapter->link_speed, +- &adapter->link_duplex); +- +- DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s\n", +- adapter->link_speed, +- adapter->link_duplex == FULL_DUPLEX ? +- "Full Duplex" : "Half Duplex"); ++ if (link) { ++ if (!netif_carrier_ok(netdev)) { ++ u32 ctrl; ++ bool txb2b = true; ++ iegbe_get_speed_and_duplex(hw, ++ &adapter->link_speed, ++ &adapter->link_duplex); + +- netif_carrier_on(netdev); +- netif_wake_queue(netdev); +- mod_timer(&adapter->phy_info_timer, jiffies + 0x2 * HZ); ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s, " ++ "Flow Control: %s\n", ++ adapter->link_speed, ++ adapter->link_duplex == FULL_DUPLEX ? ++ "Full Duplex" : "Half Duplex", ++ ((ctrl & E1000_CTRL_TFCE) && (ctrl & ++ E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl & ++ E1000_CTRL_RFCE) ? "RX" : ((ctrl & ++ E1000_CTRL_TFCE) ? "TX" : "None" ))); ++ ++ /* tweak tx_queue_len according to speed/duplex ++ * and adjust the timeout factor */ ++ netdev->tx_queue_len = adapter->tx_queue_len; ++ adapter->tx_timeout_factor = 1; ++ switch (adapter->link_speed) { ++ case SPEED_10: ++ txb2b = false; ++ netdev->tx_queue_len = 10; ++ adapter->tx_timeout_factor = 8; ++ break; ++ case SPEED_100: ++ txb2b = false; ++ netdev->tx_queue_len = 100; ++ break; ++ } ++ if ((hw->mac_type == iegbe_82571 || ++ hw->mac_type == iegbe_82572) && ++ !txb2b) { ++ u32 tarc0; ++ tarc0 = E1000_READ_REG(&adapter->hw, TARC0); ++ tarc0 &= ~(1 << 21); ++ E1000_WRITE_REG(&adapter->hw, TARC0, tarc0); ++ } ++ /* disable TSO for pcie and 10/100 speeds, to avoid ++ * some hardware issues */ ++ if (!adapter->tso_force && ++ hw->bus_type == iegbe_bus_type_pci_express){ ++ switch (adapter->link_speed) { ++ case SPEED_10: ++ case SPEED_100: ++ DPRINTK(PROBE,INFO, ++ "10/100 speed: disabling TSO\n"); ++ netdev->features &= ~NETIF_F_TSO; ++ netdev->features &= ~NETIF_F_TSO6; ++ break; ++ case SPEED_1000: ++ netdev->features |= NETIF_F_TSO; ++ netdev->features |= NETIF_F_TSO6; ++ break; ++ default: ++ break; ++ } ++ } ++ tctl = E1000_READ_REG(&adapter->hw, TCTL); ++ tctl |= E1000_TCTL_EN; ++ E1000_WRITE_REG(&adapter->hw, TCTL, tctl); ++ netif_carrier_on(netdev); ++ netif_wake_queue(netdev); ++ mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); + adapter->smartspeed = 0; ++ } else { ++ if (hw->rx_needs_kicking) { ++ u32 rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl | E1000_RCTL_EN); ++ } + } +- } else { +- if (netif_carrier_ok(netdev)) { ++ } else { ++ if (netif_carrier_ok(netdev)) { + adapter->link_speed = 0; + adapter->link_duplex = 0; +- DPRINTK(LINK, INFO, "NIC Link is Down\n"); +- netif_carrier_off(netdev); +- netif_stop_queue(netdev); +- mod_timer(&adapter->phy_info_timer, jiffies + 0x2 * HZ); +- } ++ DPRINTK(LINK, INFO, "NIC Link is Down\n"); ++ netif_carrier_off(netdev); ++ netif_stop_queue(netdev); ++ mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); ++ } + +- iegbe_smartspeed(adapter); +- } ++ iegbe_smartspeed(adapter); ++ } ++ ++ iegbe_update_stats(adapter); ++ ++ hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; ++ adapter->tpt_old = adapter->stats.tpt; ++ hw->collision_delta = adapter->stats.colc - adapter->colc_old; ++ adapter->colc_old = adapter->stats.colc; ++ ++ adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; ++ adapter->gorcl_old = adapter->stats.gorcl; ++ adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; ++ adapter->gotcl_old = adapter->stats.gotcl; ++ ++ iegbe_update_adaptive(hw); ++ ++ if (!netif_carrier_ok(netdev)) { ++ if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) { ++ /* We've lost link, so the controller stops DMA, ++ * but we've got queued Tx work that's never going ++ * to get done, so reset controller to flush Tx. ++ * (Do the reset outside of interrupt context). */ ++ adapter->tx_timeout_count++; ++ schedule_work(&adapter->reset_task); ++ } ++ } ++ ++ /* Cause software interrupt to ensure rx ring is cleaned */ ++ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); ++ ++ /* Force detection of hung controller every watchdog period */ ++ adapter->detect_tx_hung = TRUE; ++ ++ /* With 82571 controllers, LAA may be overwritten due to controller ++ * reset from the other port. Set the appropriate LAA in RAR[0] */ ++ if (adapter->hw.mac_type == iegbe_82571 && adapter->hw.laa_is_present) { ++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0x0); ++ } ++ /* Reset the timer */ ++ mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ)); ++} ++ ++enum latency_range { ++ lowest_latency = 0, ++ low_latency = 1, ++ bulk_latency = 2, ++ latency_invalid = 255 ++}; + +- iegbe_update_stats(adapter); ++/** ++ * iegbe_update_itr - update the dynamic ITR value based on statistics ++ * Stores a new ITR value based on packets and byte ++ * counts during the last interrupt. The advantage of per interrupt ++ * computation is faster updates and more accurate ITR for the current ++ * traffic pattern. Constants in this function were computed ++ * based on theoretical maximum wire speed and thresholds were set based ++ * on testing data as well as attempting to minimize response time ++ * while increasing bulk throughput. ++ * this functionality is controlled by the InterruptThrottleRate module ++ * parameter (see iegbe_param.c) ++ * @adapter: pointer to adapter ++ * @itr_setting: current adapter->itr ++ * @packets: the number of packets during this measurement interval ++ * @bytes: the number of bytes during this measurement interval ++ **/ ++static unsigned int iegbe_update_itr(struct iegbe_adapter *adapter, ++ u16 itr_setting, int packets, int bytes) ++{ ++ unsigned int retval = itr_setting; ++ struct iegbe_hw *hw = &adapter->hw; + +- adapter->hw.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; +- adapter->tpt_old = adapter->stats.tpt; +- adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old; +- adapter->colc_old = adapter->stats.colc; +- +- adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; +- adapter->gorcl_old = adapter->stats.gorcl; +- adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; +- adapter->gotcl_old = adapter->stats.gotcl; +- +- iegbe_update_adaptive(&adapter->hw); +- +- if (adapter->num_queues == 0x1 && !netif_carrier_ok(netdev)) { +- if (E1000_DESC_UNUSED(txdr) + 0x1 < txdr->count) { +- /* We've lost link, so the controller stops DMA, +- * but we've got queued Tx work that's never going +- * to get done, so reset controller to flush Tx. +- * (Do the reset outside of interrupt context). */ +- schedule_work(&adapter->tx_timeout_task); ++ if (unlikely(hw->mac_type < iegbe_82540)) ++ goto update_itr_done; ++ ++ if (packets == 0) ++ goto update_itr_done; ++ ++ switch (itr_setting) { ++ case lowest_latency: ++ /* jumbo frames get bulk treatment*/ ++ if (bytes/packets > 8000) ++ retval = bulk_latency; ++ else if ((packets < 5) && (bytes > 512)) ++ retval = low_latency; ++ break; ++ case low_latency: /* 50 usec aka 20000 ints/s */ ++ if (bytes > 10000) { ++ /* jumbo frames need bulk latency setting */ ++ if (bytes/packets > 8000) ++ retval = bulk_latency; ++ else if ((packets < 10) || ((bytes/packets) > 1200)) ++ retval = bulk_latency; ++ else if ((packets > 35)) ++ retval = lowest_latency; ++ } else if (bytes/packets > 2000) ++ retval = bulk_latency; ++ else if (packets <= 2 && bytes < 512) ++ retval = lowest_latency; ++ break; ++ case bulk_latency: /* 250 usec aka 4000 ints/s */ ++ if (bytes > 25000) { ++ if (packets > 35) ++ retval = low_latency; ++ } else if (bytes < 6000) { ++ retval = low_latency; + } ++ break; + } + +- /* Dynamic mode for Interrupt Throttle Rate (ITR) */ +- if (adapter->hw.mac_type >= iegbe_82540 && adapter->itr == 0x1) { +- /* Symmetric Tx/Rx gets a reduced ITR=2000; Total +- * asymmetrical Tx or Rx gets ITR=8000; everyone +- * else is between 2000-8000. */ +- uint32_t goc = (adapter->gotcl + adapter->gorcl) / 0x2710; +- uint32_t dif = (adapter->gotcl > adapter->gorcl ? +- adapter->gotcl - adapter->gorcl : +- adapter->gorcl - adapter->gotcl) / 0x2710; +- uint32_t itr = goc > 0 ? (dif * 0x1770 / goc + 0x7d0) : 0x1f40; +- E1000_WRITE_REG(&adapter->hw, ITR, 0x3b9aca00 / (itr * 0x100)); +- } ++update_itr_done: ++ return retval; ++} + +- /* Cause software interrupt to ensure rx ring is cleaned */ +- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); ++static void iegbe_set_itr(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ u16 current_itr; ++ u32 new_itr = adapter->itr; + +- /* Force detection of hung controller every watchdog period */ +- adapter->detect_tx_hung = TRUE; ++ if (unlikely(hw->mac_type < iegbe_82540)) ++ return; + +- /* With 82571 controllers, LAA may be overwritten due to controller +- * reset from the other port. Set the appropriate LAA in RAR[0] */ +- if (adapter->hw.mac_type == iegbe_82571 && adapter->hw.laa_is_present) { +- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0); +- } +- /* Reset the timer */ +- mod_timer(&adapter->watchdog_timer, jiffies + 0x2 * HZ); ++ /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ ++ if (unlikely(adapter->link_speed != SPEED_1000)) { ++ current_itr = 0; ++ new_itr = 4000; ++ goto set_itr_now; ++ } ++ ++ adapter->tx_itr = iegbe_update_itr(adapter, ++ adapter->tx_itr, ++ adapter->total_tx_packets, ++ adapter->total_tx_bytes); ++ /* conservative mode (itr 3) eliminates the lowest_latency setting */ ++ if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) ++ adapter->tx_itr = low_latency; ++ ++ adapter->rx_itr = iegbe_update_itr(adapter, ++ adapter->rx_itr, ++ adapter->total_rx_packets, ++ adapter->total_rx_bytes); ++ /* conservative mode (itr 3) eliminates the lowest_latency setting */ ++ if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) ++ adapter->rx_itr = low_latency; ++ ++ current_itr = max(adapter->rx_itr, adapter->tx_itr); ++ ++ switch (current_itr) { ++ /* counts and packets in update_itr are dependent on these numbers */ ++ case lowest_latency: ++ new_itr = 70000; ++ break; ++ case low_latency: ++ new_itr = 20000; /* aka hwitr = ~200 */ ++ break; ++ case bulk_latency: ++ new_itr = 4000; ++ break; ++ default: ++ break; ++ } ++ ++set_itr_now: ++ if (new_itr != adapter->itr) { ++ /* this attempts to bias the interrupt rate towards Bulk ++ * by adding intermediate steps when interrupt rate is ++ * increasing */ ++ new_itr = new_itr > adapter->itr ? ++ min(adapter->itr + (new_itr >> 2), new_itr) : ++ new_itr; ++ adapter->itr = new_itr; ++ E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (new_itr * 256)); ++ } ++ ++ return; + } + + #define E1000_TX_FLAGS_CSUM 0x00000001 +@@ -2673,55 +2641,48 @@ iegbe_watchdog(unsigned long data) + #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 + #define E1000_TX_FLAGS_VLAN_SHIFT 16 + +-static inline int +-iegbe_tso(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- struct sk_buff *skb) ++static int iegbe_tso(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, struct sk_buff *skb) + { +-#ifdef NETIF_F_TSO + struct iegbe_context_desc *context_desc; ++ struct iegbe_buffer *buffer_info; + unsigned int i; +- uint32_t cmd_length = 0; +- uint16_t ipcse = 0, tucse, mss; +- uint8_t ipcss, ipcso, tucss, tucso, hdr_len; ++ u32 cmd_length = 0; ++ u16 ipcse = 0, tucse, mss; ++ u8 ipcss, ipcso, tucss, tucso, hdr_len; + int err; + + if (skb_is_gso(skb)) { + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); +- if (err) { ++ if (err) + return err; + } +- } + +- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 0x2)); ++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + mss = skb_shinfo(skb)->gso_size; + if (skb->protocol == htons(ETH_P_IP)) { +- skb->nh.iph->tot_len = 0; +- skb->nh.iph->check = 0; +- skb->h.th->check = +- ~csum_tcpudp_magic(skb->nh.iph->saddr, +- skb->nh.iph->daddr, +- 0, +- IPPROTO_TCP, +- 0); ++ struct iphdr *iph = ip_hdr(skb); ++ iph->tot_len = 0; ++ iph->check = 0; ++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, ++ iph->daddr, 0, ++ IPPROTO_TCP, ++ 0); + cmd_length = E1000_TXD_CMD_IP; +- ipcse = skb->h.raw - skb->data - 0x1; +-#ifdef NETIF_F_TSO_IPV6 +- } else if (skb->protocol == ntohs(ETH_P_IPV6)) { +- skb->nh.ipv6h->payload_len = 0; +- skb->h.th->check = +- ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, +- &skb->nh.ipv6h->daddr, +- 0, +- IPPROTO_TCP, +- 0); ++ ipcse = skb_transport_offset(skb) - 1; ++ } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ ipv6_hdr(skb)->payload_len = 0; ++ tcp_hdr(skb)->check = ++ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, ++ &ipv6_hdr(skb)->daddr, ++ 0, IPPROTO_TCP, 0); + ipcse = 0; +-#endif + } +- ipcss = skb->nh.raw - skb->data; +- ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data; +- tucss = skb->h.raw - skb->data; +- tucso = (void *)&(skb->h.th->check) - (void *)skb->data; ++ ipcss = skb_network_offset(skb); ++ ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; ++ tucss = skb_transport_offset(skb); ++ tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; + tucse = 0; + + cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | +@@ -2729,6 +2690,7 @@ iegbe_tso(struct iegbe_adapter *adapter, + + i = tx_ring->next_to_use; + context_desc = E1000_CONTEXT_DESC(*tx_ring, i); ++ buffer_info = &tx_ring->buffer_info[i]; + + context_desc->lower_setup.ip_fields.ipcss = ipcss; + context_desc->lower_setup.ip_fields.ipcso = ipcso; +@@ -2740,205 +2702,218 @@ iegbe_tso(struct iegbe_adapter *adapter, + context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; + context_desc->cmd_and_length = cpu_to_le32(cmd_length); + +- if (++i == tx_ring->count) { i = 0; } ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ if (++i == tx_ring->count) i = 0; + tx_ring->next_to_use = i; + +- return TRUE; ++ return true; + } +-#endif +- +- return FALSE; ++ return false; + } + +-static inline boolean_t +-iegbe_tx_csum(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- struct sk_buff *skb) ++static bool iegbe_tx_csum(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, struct sk_buff *skb) + { + struct iegbe_context_desc *context_desc; ++ struct iegbe_buffer *buffer_info; + unsigned int i; +- uint8_t css; ++ u8 css; + +- if (likely(skb->ip_summed == CHECKSUM_HW)) { +- css = skb->h.raw - skb->data; ++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { ++ css = skb_transport_offset(skb); + +- i = tx_ring->next_to_use; +- context_desc = E1000_CONTEXT_DESC(*tx_ring, i); ++ i = tx_ring->next_to_use; ++ buffer_info = &tx_ring->buffer_info[i]; ++ context_desc = E1000_CONTEXT_DESC(*tx_ring, i); + ++ context_desc->lower_setup.ip_config = 0; + context_desc->upper_setup.tcp_fields.tucss = css; +- context_desc->upper_setup.tcp_fields.tucso = css + skb->csum; ++ context_desc->upper_setup.tcp_fields.tucso = ++ css + skb->csum_offset; + context_desc->upper_setup.tcp_fields.tucse = 0; + context_desc->tcp_seg_setup.data = 0; + context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); + +- if (unlikely(++i == tx_ring->count)) { i = 0; } ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ if (unlikely(++i == tx_ring->count)) i = 0; + tx_ring->next_to_use = i; + +- return TRUE; ++ return true; + } + +- return FALSE; ++ return false; + } + +-#define E1000_MAX_TXD_PWR 12 +-#define E1000_MAX_DATA_PER_TXD (1<len; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct iegbe_buffer *buffer_info; ++ unsigned int len = skb->len; + unsigned int offset = 0, size, count = 0, i; +-#ifdef MAX_SKB_FRAGS +- unsigned int f; +- len -= skb->data_len; +-#endif ++ unsigned int f; ++ len -= skb->data_len; + +- i = tx_ring->next_to_use; ++ i = tx_ring->next_to_use; ++ ++ while(len) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ size = min(len, max_per_txd); ++ /* Workaround for Controller erratum -- ++ * descriptor for non-tso packet in a linear SKB that follows a ++ * tso gets written back prematurely before the data is fully ++ * DMA'd to the controller */ ++ if (!skb->data_len && tx_ring->last_tx_tso && ++ !skb_is_gso(skb)) { ++ tx_ring->last_tx_tso = 0; ++ size -= 4; ++ } + +- while(len) { +- buffer_info = &tx_ring->buffer_info[i]; +- size = min(len, max_per_txd); +-#ifdef NETIF_F_TSO + /* Workaround for premature desc write-backs + * in TSO mode. Append 4-byte sentinel desc */ +- if(unlikely(mss && !nr_frags && size == len && size > 0x8)) { +- size -= 0x4; ++ if (unlikely(mss && !nr_frags && size == len && size > 8)) ++ size -= 4; ++ /* work-around for errata 10 and it applies ++ * to all controllers in PCI-X mode ++ * The fix is to make sure that the first descriptor of a ++ * packet is smaller than 2048 - 16 - 16 (or 2016) bytes ++ */ ++ if (unlikely((hw->bus_type == iegbe_bus_type_pcix) && ++ (size > 2015) && count == 0)) ++ size = 2015; ++ ++ /* Workaround for potential 82544 hang in PCI-X. Avoid ++ * terminating buffers within evenly-aligned dwords. */ ++ if(unlikely(adapter->pcix_82544 && ++ !((unsigned long)(skb->data + offset + size - 1) & 4) && ++ size > 4)) ++ size -= 4; ++ ++ buffer_info->length = size; ++ buffer_info->dma = ++ pci_map_single(adapter->pdev, ++ skb->data + offset, ++ size, ++ PCI_DMA_TODEVICE); ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ len -= size; ++ offset += size; ++ count++; ++ if (unlikely(++i == tx_ring->count)) i = 0; ++ } ++ ++ for (f = 0; f < nr_frags; f++) { ++ struct skb_frag_struct *frag; ++ ++ frag = &skb_shinfo(skb)->frags[f]; ++ len = frag->size; ++ offset = frag->page_offset; ++ ++ while(len) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ size = min(len, max_per_txd); ++ /* Workaround for premature desc write-backs ++ * in TSO mode. Append 4-byte sentinel desc */ ++ if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8)) ++ size -= 4; ++ /* Workaround for potential 82544 hang in PCI-X. ++ * Avoid terminating buffers within evenly-aligned ++ * dwords. */ ++ if(unlikely(adapter->pcix_82544 && ++ !((unsigned long)(frag->page+offset+size-1) & 4) && ++ size > 4)) ++ size -= 4; ++ ++ buffer_info->length = size; ++ buffer_info->dma = ++ pci_map_page(adapter->pdev, ++ frag->page, ++ offset, ++ size, ++ PCI_DMA_TODEVICE); ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ len -= size; ++ offset += size; ++ count++; ++ if (unlikely(++i == tx_ring->count)) i = 0; + } +-#endif +- /* work-around for errata 10 and it applies +- * to all controllers in PCI-X mode +- * The fix is to make sure that the first descriptor of a +- * packet is smaller than 2048 - 16 - 16 (or 2016) bytes +- */ +- if(unlikely((adapter->hw.bus_type == iegbe_bus_type_pcix) && +- (size > 0x7df) && count == 0)) { +- size = 0x7df; +- } +- /* Workaround for potential 82544 hang in PCI-X. Avoid +- * terminating buffers within evenly-aligned dwords. */ +- if(unlikely(adapter->pcix_82544 && +- !((unsigned long)(skb->data + offset + size - 0x8) & 0x4) && +- size > 0x4)) { +- size -= 0x4; +- } +- buffer_info->length = size; +- buffer_info->dma = +- pci_map_single(adapter->pdev, +- skb->data + offset, +- size, +- PCI_DMA_TODEVICE); +- buffer_info->time_stamp = jiffies; +- +- len -= size; +- offset += size; +- count++; +- if(unlikely(++i == tx_ring->count)) { i = 0; } +- } +- +-#ifdef MAX_SKB_FRAGS +- for(f = 0; f < nr_frags; f++) { +- struct skb_frag_struct *frag; +- +- frag = &skb_shinfo(skb)->frags[f]; +- len = frag->size; +- offset = frag->page_offset; +- +- while(len) { +- buffer_info = &tx_ring->buffer_info[i]; +- size = min(len, max_per_txd); +-#ifdef NETIF_F_TSO +- /* Workaround for premature desc write-backs +- * in TSO mode. Append 4-byte sentinel desc */ +- if(unlikely(mss && f == (nr_frags-0x1) && +- size == len && size > 0x8)) { +- size -= 0x4; +- } +-#endif +- /* Workaround for potential 82544 hang in PCI-X. +- * Avoid terminating buffers within evenly-aligned +- * dwords. */ +- if(unlikely(adapter->pcix_82544 && +- !((unsigned long)(frag->page+offset+size-0x1) & 0x4) && +- size > 0x4)) { +- size -= 0x4; +- } +- buffer_info->length = size; +- buffer_info->dma = +- pci_map_page(adapter->pdev, +- frag->page, +- offset, +- size, +- PCI_DMA_TODEVICE); +- buffer_info->time_stamp = jiffies; +- +- len -= size; +- offset += size; +- count++; +- if(unlikely(++i == tx_ring->count)) { i = 0; } +- } +- } +-#endif ++ } + +- i = (i == 0) ? tx_ring->count - 0x1 : i - 0x1; +- tx_ring->buffer_info[i].skb = skb; +- tx_ring->buffer_info[first].next_to_watch = i; ++ i = (i == 0) ? tx_ring->count - 1 : i - 1; ++ tx_ring->buffer_info[i].skb = skb; ++ tx_ring->buffer_info[first].next_to_watch = i; + +- return count; ++ return count; + } + +-static inline void +-iegbe_tx_queue(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- int tx_flags, int count) ++static void iegbe_tx_queue(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, int tx_flags, ++ int count) + { ++ struct iegbe_hw *hw = &adapter->hw; + struct iegbe_tx_desc *tx_desc = NULL; + struct iegbe_buffer *buffer_info; +- uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; ++ u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; + unsigned int i; + +- if(likely(tx_flags & E1000_TX_FLAGS_TSO)) { ++ if (likely(tx_flags & E1000_TX_FLAGS_TSO)) { + txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | + E1000_TXD_CMD_TSE; +- txd_upper |= E1000_TXD_POPTS_TXSM << 0x8; ++ txd_upper |= E1000_TXD_POPTS_TXSM << 8; + +- if(likely(tx_flags & E1000_TX_FLAGS_IPV4)) { +- txd_upper |= E1000_TXD_POPTS_IXSM << 0x8; +- } ++ if (likely(tx_flags & E1000_TX_FLAGS_IPV4)) ++ txd_upper |= E1000_TXD_POPTS_IXSM << 8; + } + +- if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) { ++ if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) { + txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; +- txd_upper |= E1000_TXD_POPTS_TXSM << 0x8; +- } +- +- if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { +- txd_lower |= E1000_TXD_CMD_VLE; +- txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); ++ txd_upper |= E1000_TXD_POPTS_TXSM << 8; + } + +- i = tx_ring->next_to_use; ++ if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { ++ txd_lower |= E1000_TXD_CMD_VLE; ++ txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); ++ } + +- while(count--) { +- buffer_info = &tx_ring->buffer_info[i]; +- tx_desc = E1000_TX_DESC(*tx_ring, i); +- tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); +- tx_desc->lower.data = +- cpu_to_le32(txd_lower | buffer_info->length); +- tx_desc->upper.data = cpu_to_le32(txd_upper); +- if(unlikely(++i == tx_ring->count)) { i = 0; } +- } +- if(tx_desc != NULL) { +- tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); +- } +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); ++ i = tx_ring->next_to_use; + +- tx_ring->next_to_use = i; +- writel(i, adapter->hw.hw_addr + tx_ring->tdt); ++ while(count--) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ tx_desc = E1000_TX_DESC(*tx_ring, i); ++ tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); ++ tx_desc->lower.data = ++ cpu_to_le32(txd_lower | buffer_info->length); ++ tx_desc->upper.data = cpu_to_le32(txd_upper); ++ if (unlikely(++i == tx_ring->count)) i = 0; ++ } ++ ++ tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); ++ ++ /* Force memory writes to complete before letting h/w ++ * know there are new descriptors to fetch. (Only ++ * applicable for weak-ordered memory model archs, ++ * such as IA-64). */ ++ wmb(); ++ ++ tx_ring->next_to_use = i; ++ writel(i, hw->hw_addr + tx_ring->tdt); ++ /* we need this if more than one processor can write to our tail ++ * at a time, it syncronizes IO on IA64/Altix systems */ ++ mmiowb(); + } + + /** +@@ -2950,113 +2925,132 @@ iegbe_tx_queue(struct iegbe_adapter *ada + * to the beginning of the Tx FIFO. + **/ + +-static inline int +-iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, struct sk_buff *skb) ++#define E1000_FIFO_HDR 0x10 ++#define E1000_82547_PAD_LEN 0x3E0 ++static int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, ++ struct sk_buff *skb) + { +- uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; +- uint32_t skb_fifo_len = skb->len + E1000_FIFO_HDR; ++ u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; ++ u32 skb_fifo_len = skb->len + E1000_FIFO_HDR; + +- E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR); ++ skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR); + +- if(adapter->link_duplex != HALF_DUPLEX) { +- goto no_fifo_stall_required; +- } +- if(atomic_read(&adapter->tx_fifo_stall)) { +- return 1; ++ if (adapter->link_duplex != HALF_DUPLEX) ++ goto no_fifo_stall_required; ++ ++ if (atomic_read(&adapter->tx_fifo_stall)) ++ return 1; ++ ++ if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { ++ atomic_set(&adapter->tx_fifo_stall, 1); ++ return 1; + } +- if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { +- atomic_set(&adapter->tx_fifo_stall, 0x1); +- return 1; +- } + + no_fifo_stall_required: +- adapter->tx_fifo_head += skb_fifo_len; +- if(adapter->tx_fifo_head >= adapter->tx_fifo_size) { +- adapter->tx_fifo_head -= adapter->tx_fifo_size; +- } ++ adapter->tx_fifo_head += skb_fifo_len; ++ if (adapter->tx_fifo_head >= adapter->tx_fifo_size) ++ adapter->tx_fifo_head -= adapter->tx_fifo_size; + return 0; + } + +-static inline int +-iegbe_transfer_dhcp_info(struct iegbe_adapter *adapter, struct sk_buff *skb) ++#define MINIMUM_DHCP_PACKET_SIZE 282 ++static int iegbe_transfer_dhcp_info(struct iegbe_adapter *adapter, ++ struct sk_buff *skb) + { + struct iegbe_hw *hw = &adapter->hw; +- uint16_t length, offset; +-#ifdef NETIF_F_HW_VLAN_TX +- if(vlan_tx_tag_present(skb)) { +- if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && +- ( adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) { ++ u16 length, offset; ++ if (vlan_tx_tag_present(skb)) { ++ if (!((vlan_tx_tag_get(skb) == hw->mng_cookie.vlan_id) && ++ ( hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) + return 0; + } +- } +-#endif +- if(htons(ETH_P_IP) == skb->protocol) { +- const struct iphdr *ip = skb->nh.iph; +- if(IPPROTO_UDP == ip->protocol) { +- struct udphdr *udp = (struct udphdr *)(skb->h.uh); +- if(ntohs(udp->dest) == 0x43) { /* 0x43 = 67 */ +- offset = (uint8_t *)udp + 0x8 - skb->data; +- length = skb->len - offset; +- +- return iegbe_mng_write_dhcp_info(hw, +- (uint8_t *)udp + 0x8, length); +- } +- } +- } else if((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) { +- struct ethhdr *eth = (struct ethhdr *) skb->data; +- if((htons(ETH_P_IP) == eth->h_proto)) { ++ if (skb->len > MINIMUM_DHCP_PACKET_SIZE) { ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ if ((htons(ETH_P_IP) == eth->h_proto)) { + const struct iphdr *ip = +- (struct iphdr *)((uint8_t *)skb->data+0xe); +- if(IPPROTO_UDP == ip->protocol) { ++ (struct iphdr *)((u8 *)skb->data+14); ++ if (IPPROTO_UDP == ip->protocol) { + struct udphdr *udp = +- (struct udphdr *)((uint8_t *)ip + +- (ip->ihl << 0x2)); +- if(ntohs(udp->dest) == 0x43) { +- offset = (uint8_t *)udp + 0x8 - skb->data; ++ (struct udphdr *)((u8 *)ip + ++ (ip->ihl << 2)); ++ if (ntohs(udp->dest) == 67) { ++ offset = (u8 *)udp + 8 - skb->data; + length = skb->len - offset; + + return iegbe_mng_write_dhcp_info(hw, +- (uint8_t *)udp + 0x8, ++ (u8 *)udp + 8, + length); +- } ++ } + } + } + } + return 0; + } + +-static int +-iegbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ++static int __iegbe_maybe_stop_tx(struct net_device *netdev, int size) ++{ ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_tx_ring *tx_ring = adapter->tx_ring; ++ ++ netif_stop_queue(netdev); ++ /* Herbert's original patch had: ++ * smp_mb__after_netif_stop_queue(); ++ * but since that doesn't exist yet, just open code it. */ ++ smp_mb(); ++ ++ /* We need to check again in a case another CPU has just ++ * made room available. */ ++ if (likely(E1000_DESC_UNUSED(tx_ring) < size)) ++ return -EBUSY; ++ ++ /* A reprieve! */ ++ netif_start_queue(netdev); ++ ++adapter->restart_queue; ++ return 0; ++} ++ ++static int iegbe_maybe_stop_tx(struct net_device *netdev, ++ struct iegbe_tx_ring *tx_ring, int size) ++{ ++ if (likely(E1000_DESC_UNUSED(tx_ring) >= size)) ++ return 0; ++ return __iegbe_maybe_stop_tx(netdev, size); ++} ++ ++#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) ++static int iegbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; + struct iegbe_tx_ring *tx_ring; + unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; + unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; + unsigned int tx_flags = 0; +- unsigned int len = skb->len; ++ unsigned int len = skb->len - skb->data_len; + unsigned long flags = 0; +- unsigned int nr_frags = 0; +- unsigned int mss = 0; ++ unsigned int nr_frags; ++ unsigned int mss; + int count = 0; +- int tso; +-#ifdef MAX_SKB_FRAGS ++ int tso; + unsigned int f; +- len -= skb->data_len; +-#endif + +-#ifdef CONFIG_E1000_MQ +- tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id()); +-#else ++ /* This goes back to the question of how to logically map a tx queue ++ * to a flow. Right now, performance is impacted slightly negatively ++ * if using multiple tx queues. If the stack breaks away from a ++ * single qdisc implementation, we can look at this again. */ + tx_ring = adapter->tx_ring; +-#endif + + if (unlikely(skb->len <= 0)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +-#ifdef NETIF_F_TSO ++ /* 82571 and newer doesn't need the workaround that limited descriptor ++ * length to 4kB */ ++ if (hw->mac_type >= iegbe_82571) ++ max_per_txd = 8192; ++ + mss = skb_shinfo(skb)->gso_size; + /* The controller does a simple calculation to + * make sure there is enough room in the FIFO before +@@ -3064,164 +3058,150 @@ iegbe_xmit_frame(struct sk_buff *skb, st + * 4 = ceil(buffer len/mss). To make sure we don't + * overrun the FIFO, adjust the max buffer len if mss + * drops. */ +- if(mss) { +- max_per_txd = min(mss << 0x2, max_per_txd); +- max_txd_pwr = fls(max_per_txd) - 0x1; ++ if (mss) { ++ u8 hdr_len; ++ max_per_txd = min(mss << 2, max_per_txd); ++ max_txd_pwr = fls(max_per_txd) - 1; ++ ++ /* TSO Workaround for 82571/2/3 Controllers -- if skb->data ++ * points to just header, pull a few bytes of payload from ++ * frags into skb->data */ ++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); ++ if (skb->data_len && hdr_len == len) { ++ switch (hw->mac_type) { ++ case iegbe_82544: ++ /* Make sure we have room to chop off 4 bytes, ++ * and that the end alignment will work out to ++ * this hardware's requirements ++ * NOTE: this is a TSO only workaround ++ * if end byte alignment not correct move us ++ * into the next dword */ ++ break; ++ /* fall through */ ++ case iegbe_82571: ++ case iegbe_82572: ++ case iegbe_82573: ++ break; ++ default: ++ /* do nothing */ ++ break; ++ } ++ } + } + +- if((mss) || (skb->ip_summed == CHECKSUM_HW)) { ++ /* reserve a descriptor for the offload context */ ++ if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) + count++; +- } + count++; +-#else +- if(skb->ip_summed == CHECKSUM_HW) { ++ ++ /* Controller Erratum workaround */ ++ if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb)) + count++; +- { +-#endif ++ + count += TXD_USE_COUNT(len, max_txd_pwr); + +- if(adapter->pcix_82544) { ++ if (adapter->pcix_82544) + count++; +- } ++ + /* work-around for errata 10 and it applies to all controllers + * in PCI-X mode, so add one more descriptor to the count + */ +- if(unlikely((adapter->hw.bus_type == iegbe_bus_type_pcix) && +- (len > 0x7df))) { ++ if (unlikely((hw->bus_type == iegbe_bus_type_pcix) && ++ (len > 2015))) + count++; +- } +-#ifdef MAX_SKB_FRAGS ++ + nr_frags = skb_shinfo(skb)->nr_frags; +- for(f = 0; f < nr_frags; f++) ++ for (f = 0; f < nr_frags; f++) + count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, + max_txd_pwr); +- if(adapter->pcix_82544) { ++ if (adapter->pcix_82544) + count += nr_frags; +- } +-#ifdef NETIF_F_TSO +- /* TSO Workaround for 82571/2 Controllers -- if skb->data +- * points to just header, pull a few bytes of payload from +- * frags into skb->data */ +- if (skb_is_gso(skb)) { +- uint8_t hdr_len; +- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 0x2)); +- if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) && +- (adapter->hw.mac_type == iegbe_82571 || +- adapter->hw.mac_type == iegbe_82572)) { +- unsigned int pull_size; +- pull_size = min((unsigned int)0x4, skb->data_len); +- if (!__pskb_pull_tail(skb, pull_size)) { +- printk(KERN_ERR "__pskb_pull_tail failed.\n"); +- dev_kfree_skb_any(skb); +- return -EFAULT; +- } +- } +- } +-#endif +-#endif + +- if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == iegbe_82573) ) { ++ ++ if (hw->tx_pkt_filtering && ++ (hw->mac_type == iegbe_82573)) + iegbe_transfer_dhcp_info(adapter, skb); +- } +-#ifdef NETIF_F_LLTX +- local_irq_save(flags); +- if (!spin_trylock(&tx_ring->tx_lock)) { ++ ++ if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) + /* Collision - tell upper layer to requeue */ +- local_irq_restore(flags); + return NETDEV_TX_LOCKED; +- } +-#else +- spin_lock_irqsave(&tx_ring->tx_lock, flags); +-#endif + + /* need: count + 2 desc gap to keep tail from touching + * head, otherwise try next time */ +- if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 0x2)) { +- netif_stop_queue(netdev); ++ if (unlikely(iegbe_maybe_stop_tx(netdev, tx_ring, count + 2))) { + spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + return NETDEV_TX_BUSY; + } + +- if(unlikely(adapter->hw.mac_type == iegbe_82547)) { +- if(unlikely(iegbe_82547_fifo_workaround(adapter, skb))) { ++ if (unlikely(hw->mac_type == iegbe_82547)) { ++ if (unlikely(iegbe_82547_fifo_workaround(adapter, skb))) { + netif_stop_queue(netdev); +- mod_timer(&adapter->tx_fifo_stall_timer, jiffies); ++ mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); + spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + return NETDEV_TX_BUSY; + } + } + +-#ifndef NETIF_F_LLTX +- spin_unlock_irqrestore(&tx_ring->tx_lock, flags); +-#endif +- +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { ++ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { + tx_flags |= E1000_TX_FLAGS_VLAN; + tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); + } +-#endif + + first = tx_ring->next_to_use; + + tso = iegbe_tso(adapter, tx_ring, skb); + if (tso < 0) { + dev_kfree_skb_any(skb); +-#ifdef NETIF_F_LLTX + spin_unlock_irqrestore(&tx_ring->tx_lock, flags); +-#endif + return NETDEV_TX_OK; + } + +- if (likely(tso)) { ++ if (likely(tso)) { ++ tx_ring->last_tx_tso = 1; + tx_flags |= E1000_TX_FLAGS_TSO; +- } else if (likely(iegbe_tx_csum(adapter, tx_ring, skb))) { ++ } else if (likely(iegbe_tx_csum(adapter, tx_ring, skb))) + tx_flags |= E1000_TX_FLAGS_CSUM; +- } ++ + /* Old method was to assume IPv4 packet by default if TSO was enabled. + * 82571 hardware supports TSO capabilities for IPv6 as well... + * no longer assume, we must. */ +- if (likely(skb->protocol == ntohs(ETH_P_IP))) { ++ if (likely(skb->protocol == htons(ETH_P_IP))) + tx_flags |= E1000_TX_FLAGS_IPV4; +- } ++ + iegbe_tx_queue(adapter, tx_ring, tx_flags, + iegbe_tx_map(adapter, tx_ring, skb, first, + max_per_txd, nr_frags, mss)); + + netdev->trans_start = jiffies; + +-#ifdef NETIF_F_LLTX + /* Make sure there is space in the ring for the next send. */ +- if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 0x2)) { +- netif_stop_queue(netdev); +- } +- spin_unlock_irqrestore(&tx_ring->tx_lock, flags); +-#endif ++ iegbe_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); + ++ spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + return NETDEV_TX_OK; + } + ++ + /** + * iegbe_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + **/ + +-static void +-iegbe_tx_timeout(struct net_device *netdev) ++static void iegbe_tx_timeout(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); + +- /* Do the reset outside of interrupt context */ +- schedule_work(&adapter->tx_timeout_task); ++ /* Do the reset outside of interrupt context */ ++ adapter->tx_timeout_count++; ++ schedule_work(&adapter->reset_task); + } + +-static void +-iegbe_tx_timeout_task(struct net_device *netdev) ++static void iegbe_reset_task(struct work_struct *work) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_adapter *adapter = ++ container_of(work, struct iegbe_adapter, reset_task); + +- iegbe_down(adapter); +- iegbe_up(adapter); ++ iegbe_reinit_locked(adapter); + } + + /** +@@ -3232,13 +3212,12 @@ iegbe_tx_timeout_task(struct net_device + * The statistics are actually updated from the timer callback. + **/ + +-static struct net_device_stats * +-iegbe_get_stats(struct net_device *netdev) ++static struct net_device_stats *iegbe_get_stats(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); + +- iegbe_update_stats(adapter); +- return &adapter->net_stats; ++ /* only return the current stats */ ++ return &adapter->net_stats; + } + + /** +@@ -3249,67 +3228,55 @@ iegbe_get_stats(struct net_device *netde + * Returns 0 on success, negative on failure + **/ + +-static int +-iegbe_change_mtu(struct net_device *netdev, int new_mtu) ++static int iegbe_change_mtu(struct net_device *netdev, int new_mtu) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; + +- if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || +- (max_frame > MAX_JUMBO_FRAME_SIZE)) { +- DPRINTK(PROBE, ERR, "Invalid MTU setting\n"); +- return -EINVAL; +- } ++ if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || ++ (max_frame > MAX_JUMBO_FRAME_SIZE)) { ++ DPRINTK(PROBE, ERR, "Invalid MTU setting\n"); ++ return -EINVAL; ++ } + ++ /* Adapter-specific max frame size limits. */ ++ switch (hw->mac_type) { ++ case iegbe_undefined ... iegbe_82542_rev2_1: ++ if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { ++ DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n"); ++ return -EINVAL; ++ } ++ break; ++ case iegbe_82571: ++ case iegbe_82572: + #define MAX_STD_JUMBO_FRAME_SIZE 9234 +- /* might want this to be bigger enum check... */ +- /* 82571 controllers limit jumbo frame size to 10500 bytes */ +- if ((adapter->hw.mac_type == iegbe_82571 || +- adapter->hw.mac_type == iegbe_82572) && +- max_frame > MAX_STD_JUMBO_FRAME_SIZE) { +- DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported " +- "on 82571 and 82572 controllers.\n"); +- return -EINVAL; +- } +- +- if(adapter->hw.mac_type == iegbe_82573 && +- max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { +- DPRINTK(PROBE, ERR, "Jumbo Frames not supported " +- "on 82573\n"); +- return -EINVAL; +- } +- +- if(adapter->hw.mac_type > iegbe_82547_rev_2) { +- adapter->rx_buffer_len = max_frame; +- E1000_ROUNDUP(adapter->rx_buffer_len, 0x1024); +- } else { +- if(unlikely((adapter->hw.mac_type < iegbe_82543) && +- (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) { +- DPRINTK(PROBE, ERR, "Jumbo Frames not supported " +- "on 82542\n"); +- return -EINVAL; +- +- } else { +- if(max_frame <= E1000_RXBUFFER_2048) { +- adapter->rx_buffer_len = E1000_RXBUFFER_2048; +- } else if(max_frame <= E1000_RXBUFFER_4096) { +- adapter->rx_buffer_len = E1000_RXBUFFER_4096; +- } else if(max_frame <= E1000_RXBUFFER_8192) { +- adapter->rx_buffer_len = E1000_RXBUFFER_8192; +- } else if(max_frame <= E1000_RXBUFFER_16384) { +- adapter->rx_buffer_len = E1000_RXBUFFER_16384; +- } ++ if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { ++ DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n"); ++ return -EINVAL; + } ++ break; ++ default: ++ break; + } ++ if (max_frame <= E1000_RXBUFFER_256) ++ adapter->rx_buffer_len = E1000_RXBUFFER_256; ++ else if (max_frame <= E1000_RXBUFFER_2048) ++ adapter->rx_buffer_len = E1000_RXBUFFER_2048; ++ else if (max_frame <= E1000_RXBUFFER_4096) ++ adapter->rx_buffer_len = E1000_RXBUFFER_4096; ++ else if (max_frame <= E1000_RXBUFFER_8192) ++ adapter->rx_buffer_len = E1000_RXBUFFER_8192; ++ else if (max_frame <= E1000_RXBUFFER_16384) ++ adapter->rx_buffer_len = E1000_RXBUFFER_16384; + +- netdev->mtu = new_mtu; ++ /* adjust allocation if LPE protects us, and we aren't using SBP */ + +- if(netif_running(netdev)) { +- iegbe_down(adapter); +- iegbe_up(adapter); +- } ++ netdev->mtu = new_mtu; ++ hw->max_frame_size = max_frame; + +- adapter->hw.max_frame_size = max_frame; ++ if (netif_running(netdev)) ++ iegbe_reinit_locked(adapter); + + return 0; + } +@@ -3319,224 +3286,189 @@ iegbe_change_mtu(struct net_device *netd + * @adapter: board private structure + **/ + +-void +-iegbe_update_stats(struct iegbe_adapter *adapter) ++void iegbe_update_stats(struct iegbe_adapter *adapter) + { +- struct iegbe_hw *hw = &adapter->hw; +- unsigned long flags = 0; +- uint16_t phy_tmp; ++ struct iegbe_hw *hw = &adapter->hw; ++ unsigned long flags = 0x0; ++ uint16_t phy_tmp; + + #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF + +- spin_lock_irqsave(&adapter->stats_lock, flags); ++ spin_lock_irqsave(&adapter->stats_lock, flags); + +- /* these counters are modified from iegbe_adjust_tbi_stats, +- * called from the interrupt context, so they must only +- * be written while holding adapter->stats_lock +- */ ++ /* these counters are modified from iegbe_adjust_tbi_stats, ++ * called from the interrupt context, so they must only ++ * be written while holding adapter->stats_lock ++ */ + +- adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); +- adapter->stats.gprc += E1000_READ_REG(hw, GPRC); +- adapter->stats.gorcl += E1000_READ_REG(hw, GORCL); +- adapter->stats.gorch += E1000_READ_REG(hw, GORCH); +- adapter->stats.bprc += E1000_READ_REG(hw, BPRC); +- adapter->stats.mprc += E1000_READ_REG(hw, MPRC); +- adapter->stats.roc += E1000_READ_REG(hw, ROC); +- adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); +- adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); +- adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); +- adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); +- adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); +- adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); +- +- adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); +- adapter->stats.mpc += E1000_READ_REG(hw, MPC); +- adapter->stats.scc += E1000_READ_REG(hw, SCC); +- adapter->stats.ecol += E1000_READ_REG(hw, ECOL); +- adapter->stats.mcc += E1000_READ_REG(hw, MCC); +- adapter->stats.latecol += E1000_READ_REG(hw, LATECOL); +- adapter->stats.dc += E1000_READ_REG(hw, DC); +- adapter->stats.sec += E1000_READ_REG(hw, SEC); +- adapter->stats.rlec += E1000_READ_REG(hw, RLEC); +- adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC); +- adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC); +- adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC); +- adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); +- adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); +- adapter->stats.gptc += E1000_READ_REG(hw, GPTC); +- adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL); +- adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); +- adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); +- adapter->stats.ruc += E1000_READ_REG(hw, RUC); +- adapter->stats.rfc += E1000_READ_REG(hw, RFC); +- adapter->stats.rjc += E1000_READ_REG(hw, RJC); +- adapter->stats.torl += E1000_READ_REG(hw, TORL); +- adapter->stats.torh += E1000_READ_REG(hw, TORH); +- adapter->stats.totl += E1000_READ_REG(hw, TOTL); +- adapter->stats.toth += E1000_READ_REG(hw, TOTH); +- adapter->stats.tpr += E1000_READ_REG(hw, TPR); +- adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); +- adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); +- adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); +- adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); +- adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); +- adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); +- adapter->stats.mptc += E1000_READ_REG(hw, MPTC); +- adapter->stats.bptc += E1000_READ_REG(hw, BPTC); +- +- /* used for adaptive IFS */ +- +- hw->tx_packet_delta = E1000_READ_REG(hw, TPT); +- adapter->stats.tpt += hw->tx_packet_delta; +- hw->collision_delta = E1000_READ_REG(hw, COLC); +- adapter->stats.colc += hw->collision_delta; +- +- if(hw->mac_type >= iegbe_82543) { +- adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC); +- adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC); +- adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS); +- adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR); +- adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); +- adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); +- } +- if(hw->mac_type > iegbe_82547_rev_2) { +- adapter->stats.iac += E1000_READ_REG(hw, IAC); +- adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC); +- adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); +- adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC); +- adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC); +- adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC); +- adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC); +- adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC); +- adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC); +- } +- +- /* Fill out the OS statistics structure */ +- +- adapter->net_stats.rx_packets = adapter->stats.gprc; +- adapter->net_stats.tx_packets = adapter->stats.gptc; +- adapter->net_stats.rx_bytes = adapter->stats.gorcl; +- adapter->net_stats.tx_bytes = adapter->stats.gotcl; +- adapter->net_stats.multicast = adapter->stats.mprc; +- adapter->net_stats.collisions = adapter->stats.colc; +- +- /* Rx Errors */ +- +- adapter->net_stats.rx_errors = adapter->stats.rxerrc + +- adapter->stats.crcerrs + adapter->stats.algnerrc + +- adapter->stats.rlec + adapter->stats.mpc + +- adapter->stats.cexterr; +- adapter->net_stats.rx_dropped = adapter->stats.mpc; +- adapter->net_stats.rx_length_errors = adapter->stats.rlec; +- adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; +- adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; +- adapter->net_stats.rx_fifo_errors = adapter->stats.mpc; +- adapter->net_stats.rx_missed_errors = adapter->stats.mpc; +- +- /* Tx Errors */ +- +- adapter->net_stats.tx_errors = adapter->stats.ecol + +- adapter->stats.latecol; +- adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; +- adapter->net_stats.tx_window_errors = adapter->stats.latecol; +- adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; ++ adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); ++ adapter->stats.gprc += E1000_READ_REG(hw, GPRC); ++ adapter->stats.gorcl += E1000_READ_REG(hw, GORCL); ++ adapter->stats.gorch += E1000_READ_REG(hw, GORCH); ++ adapter->stats.bprc += E1000_READ_REG(hw, BPRC); ++ adapter->stats.mprc += E1000_READ_REG(hw, MPRC); ++ adapter->stats.roc += E1000_READ_REG(hw, ROC); ++ adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); ++ adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); ++ adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); ++ adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); ++ adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); ++ adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); ++ ++ adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); ++ adapter->stats.mpc += E1000_READ_REG(hw, MPC); ++ adapter->stats.scc += E1000_READ_REG(hw, SCC); ++ adapter->stats.ecol += E1000_READ_REG(hw, ECOL); ++ adapter->stats.mcc += E1000_READ_REG(hw, MCC); ++ adapter->stats.latecol += E1000_READ_REG(hw, LATECOL); ++ adapter->stats.dc += E1000_READ_REG(hw, DC); ++ adapter->stats.sec += E1000_READ_REG(hw, SEC); ++ adapter->stats.rlec += E1000_READ_REG(hw, RLEC); ++ adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC); ++ adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC); ++ adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC); ++ adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); ++ adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); ++ adapter->stats.gptc += E1000_READ_REG(hw, GPTC); ++ adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL); ++ adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); ++ adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); ++ adapter->stats.ruc += E1000_READ_REG(hw, RUC); ++ adapter->stats.rfc += E1000_READ_REG(hw, RFC); ++ adapter->stats.rjc += E1000_READ_REG(hw, RJC); ++ adapter->stats.torl += E1000_READ_REG(hw, TORL); ++ adapter->stats.torh += E1000_READ_REG(hw, TORH); ++ adapter->stats.totl += E1000_READ_REG(hw, TOTL); ++ adapter->stats.toth += E1000_READ_REG(hw, TOTH); ++ adapter->stats.tpr += E1000_READ_REG(hw, TPR); ++ adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); ++ adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); ++ adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); ++ adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); ++ adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); ++ adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); ++ adapter->stats.mptc += E1000_READ_REG(hw, MPTC); ++ adapter->stats.bptc += E1000_READ_REG(hw, BPTC); ++ ++ /* used for adaptive IFS */ ++ ++ hw->tx_packet_delta = E1000_READ_REG(hw, TPT); ++ adapter->stats.tpt += hw->tx_packet_delta; ++ hw->collision_delta = E1000_READ_REG(hw, COLC); ++ adapter->stats.colc += hw->collision_delta; ++ ++ if(hw->mac_type >= iegbe_82543) { ++ adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC); ++ adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC); ++ adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS); ++ adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR); ++ adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); ++ adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); ++ } ++ if(hw->mac_type > iegbe_82547_rev_2) { ++ adapter->stats.iac += E1000_READ_REG(hw, IAC); ++ adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC); ++ adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); ++ adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC); ++ adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC); ++ adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC); ++ adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC); ++ adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC); ++ adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC); ++ } ++ ++ /* Fill out the OS statistics structure */ ++ ++ adapter->net_stats.rx_packets = adapter->stats.gprc; ++ adapter->net_stats.tx_packets = adapter->stats.gptc; ++ adapter->net_stats.rx_bytes = adapter->stats.gorcl; ++ adapter->net_stats.tx_bytes = adapter->stats.gotcl; ++ adapter->net_stats.multicast = adapter->stats.mprc; ++ adapter->net_stats.collisions = adapter->stats.colc; ++ ++ /* Rx Errors */ ++ ++ adapter->net_stats.rx_errors = adapter->stats.rxerrc + ++ adapter->stats.crcerrs + adapter->stats.algnerrc + ++ adapter->stats.rlec + adapter->stats.mpc + ++ adapter->stats.cexterr; ++ adapter->net_stats.rx_dropped = adapter->stats.mpc; ++ adapter->net_stats.rx_length_errors = adapter->stats.rlec; ++ adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; ++ adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; ++ adapter->net_stats.rx_fifo_errors = adapter->stats.mpc; ++ adapter->net_stats.rx_missed_errors = adapter->stats.mpc; ++ ++ /* Tx Errors */ ++ ++ adapter->net_stats.tx_errors = adapter->stats.ecol + ++ adapter->stats.latecol; ++ adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; ++ adapter->net_stats.tx_window_errors = adapter->stats.latecol; ++ adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; + +- /* Tx Dropped needs to be maintained elsewhere */ ++ /* Tx Dropped needs to be maintained elsewhere */ + +- /* Phy Stats */ ++ /* Phy Stats */ + +- if(hw->media_type == iegbe_media_type_copper ++ if(hw->media_type == iegbe_media_type_copper + || (hw->media_type == iegbe_media_type_oem + && iegbe_oem_phy_is_copper(&adapter->hw))) { +- if((adapter->link_speed == SPEED_1000) && +- (!iegbe_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { +- phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; +- adapter->phy_stats.idle_errors += phy_tmp; +- } ++ if((adapter->link_speed == SPEED_1000) && ++ (!iegbe_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { ++ phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; ++ adapter->phy_stats.idle_errors += phy_tmp; ++ } + +- if((hw->mac_type <= iegbe_82546) && +- (hw->phy_type == iegbe_phy_m88) && ++ if((hw->mac_type <= iegbe_82546) && ++ (hw->phy_type == iegbe_phy_m88) && + !iegbe_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) { +- adapter->phy_stats.receive_errors += phy_tmp; +- } ++ adapter->phy_stats.receive_errors += phy_tmp; ++ } + } + +- spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); + } + +-#ifdef CONFIG_E1000_MQ +-void +-iegbe_rx_schedule(void *data) ++/** ++ * iegbe_intr_msi - Interrupt Handler ++ * @irq: interrupt number ++ * @data: pointer to a network interface device structure ++ **/ ++ ++static irqreturn_t iegbe_intr_msi(int irq, void *data) + { +- struct net_device *poll_dev, *netdev = data; +- struct iegbe_adapter *adapter = netdev->priv; +- int this_cpu = get_cpu(); +- +- poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu); +- if (poll_dev == NULL) { +- put_cpu(); +- return; ++ struct net_device *netdev = data; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 icr = E1000_READ_REG(&adapter->hw, ICR); ++ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { ++ hw->get_link_status = 1; ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + +- if (likely(netif_rx_schedule_prep(poll_dev))) { +- __netif_rx_schedule(poll_dev); +- } else { +- iegbe_irq_enable(adapter); +- } +- put_cpu(); +-} +-#endif +- +-#ifdef IEGBE_GBE_WORKAROUND +-/* +- * Check for tx hang condition. This is the condition where a +- * decsriptor is in the hardware and hasn't been processed for a +- * while. This code is similar to the check in iegbe_clean_rx_irq() +- */ +-static void +-iegbe_tx_hang_check(struct iegbe_adapter *adapter, +- struct iegbe_tx_ring *tx_ring) +-{ +- struct net_device *netdev = adapter->netdev; +- unsigned int i; ++ if(unlikely(icr & (E1000_ICR_RX_DESC_FIFO_PAR ++ | E1000_ICR_TX_DESC_FIFO_PAR ++ | E1000_ICR_PB ++ | E1000_ICR_CPP_TARGET ++ | E1000_ICR_CPP_MASTER ))) { + +- /* Check for a hang condition using the buffer currently at the Tx +- head pointer */ +- i = readl(adapter->hw.hw_addr + tx_ring->tdh); +- +- if (adapter->detect_tx_hung) { +- /* Detect a transmit hang in hardware, this serializes the +- * check with the clearing of time_stamp and movement of i */ +- adapter->detect_tx_hung = FALSE; +- +- if (tx_ring->buffer_info[i].dma && +- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) +- && !(E1000_READ_REG(&adapter->hw, STATUS) & +- E1000_STATUS_TXOFF)) { +- +- /* detected Tx unit hang */ +- DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" +- " TDH <%x>\n" +- " TDT <%x>\n" +- " next_to_use <%x>\n" +- " next_to_clean <%x>\n" +- "buffer_info[tdh]\n" +- " dma <%zx>\n" +- " time_stamp <%lx>\n" +- " jiffies <%lx>\n", +- readl(adapter->hw.hw_addr + tx_ring->tdh), +- readl(adapter->hw.hw_addr + tx_ring->tdt), +- tx_ring->next_to_use, +- tx_ring->next_to_clean, +- (size_t)tx_ring->buffer_info[i].dma, +- tx_ring->buffer_info[i].time_stamp, +- jiffies); +- netif_stop_queue(netdev); +- } ++ iegbe_irq_disable(adapter); ++ printk("Critical error! ICR = 0x%x\n", icr); ++ return IRQ_HANDLED; + } +-} ++ if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ adapter->total_tx_bytes = 0; ++ adapter->total_tx_packets = 0; ++ adapter->total_rx_bytes = 0; ++ adapter->total_rx_packets = 0; ++ __netif_rx_schedule(netdev, &adapter->napi); ++ } else ++ iegbe_irq_enable(adapter); + +-#endif ++ return IRQ_HANDLED; ++} + + /** + * iegbe_intr - Interrupt Handler +@@ -3546,364 +3478,208 @@ iegbe_tx_hang_check(struct iegbe_adapter + **/ + + static irqreturn_t +-iegbe_intr(int irq, void *data, struct pt_regs *regs) ++iegbe_intr(int irq, void *data) + { +- struct net_device *netdev = data; +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- struct iegbe_hw *hw = &adapter->hw; +- uint32_t rctl, tctl; +- uint32_t icr = E1000_READ_REG(hw, ICR); +-#ifndef CONFIG_E1000_NAPI +- uint32_t i; +-#ifdef IEGBE_GBE_WORKAROUND +- int rx_cleaned; +-#endif +-#endif ++ struct net_device *netdev = data; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 icr = E1000_READ_REG(&adapter->hw, ICR); + +- if(unlikely(!icr)) { ++ if (unlikely(!icr)) + return IRQ_NONE; /* Not our interrupt */ +- } ++ ++ /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is ++ * not set, then the adapter didn't send an interrupt */ ++ if (unlikely(hw->mac_type >= iegbe_82571 && ++ !(icr & E1000_ICR_INT_ASSERTED))) ++ return IRQ_NONE; ++ ++ + if(unlikely(icr & (E1000_ICR_RX_DESC_FIFO_PAR +- | E1000_ICR_TX_DESC_FIFO_PAR +- | E1000_ICR_PB +- | E1000_ICR_CPP_TARGET +- | E1000_ICR_CPP_MASTER ))) { ++ | E1000_ICR_TX_DESC_FIFO_PAR ++ | E1000_ICR_PB ++ | E1000_ICR_CPP_TARGET ++ | E1000_ICR_CPP_MASTER ))) { + + iegbe_irq_disable(adapter); +- tctl = E1000_READ_REG(&adapter->hw, TCTL); +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_TCTL_EN); +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN); +- +- tasklet_data = (unsigned long) (icr + adapter->bd_number); +- tasklet_schedule(&iegbe_reset_tasklet); +- +- return IRQ_HANDLED; +- } +- +-#ifdef CONFIG_E1000_NAPI +- atomic_inc(&adapter->irq_sem); +-#ifdef IEGBE_GBE_WORKAROUND +- /* Ensure that the TXQE interrupt is enabled in NAPI mode */ +- E1000_WRITE_REG(hw, IMC, ~E1000_IMS_TXQE); +-#else +- E1000_WRITE_REG(hw, IMC, ~0); +-#endif +- E1000_WRITE_FLUSH(hw); +-#ifdef CONFIG_E1000_MQ +- if (atomic_read(&adapter->rx_sched_call_data.count) == 0) { +- cpu_set(adapter->cpu_for_queue[0], +- adapter->rx_sched_call_data.cpumask); +- for (i = 1; i < adapter->num_queues; i++) { +- cpu_set(adapter->cpu_for_queue[i], +- adapter->rx_sched_call_data.cpumask); +- atomic_inc(&adapter->irq_sem); +- } +- atomic_set(&adapter->rx_sched_call_data.count, i); +- smp_call_async_mask(&adapter->rx_sched_call_data); +- } else { +- DEBUGOUT("call_data.count == %u\n", +- atomic_read(&adapter->rx_sched_call_data.count)); ++ printk("Critical error! ICR = 0x%x\n", icr); ++ return IRQ_HANDLED; + } +-#else +- if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0]))) { +- __netif_rx_schedule(&adapter->polling_netdev[0]); +- } else { +- iegbe_irq_enable(adapter); +- } +-#endif +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Clean the Tx ring */ +- for (i = 0; i < E1000_MAX_INTR; i++) { +- adapter->stats.rx_next_to_clean = adapter->rx_ring->next_to_clean; +- adapter->stats.rx_next_to_use = adapter->rx_ring->next_to_use; +- +- adapter->stats.tx_next_to_clean = adapter->tx_ring->next_to_clean; +- adapter->stats.tx_next_to_use = adapter->tx_ring->next_to_use; +- +- /* Only clean Tx descriptors for a TXQE interrupt */ +- if(icr & E1000_ICR_TXQE) { +- adapter->stats.txqec++; +- iegbe_clean_tx_ring_partial(adapter, adapter->tx_ring); +- } +- else { +- iegbe_tx_hang_check(adapter, adapter->tx_ring); +- } +- } + +-#endif /*IEGBE_GBE_WORKAROUND */ +- +-#else +- /* Writing IMC and IMS is needed for 82547. +- * Due to Hub Link bus being occupied, an interrupt +- * de-assertion message is not able to be sent. +- * When an interrupt assertion message is generated later, +- * two messages are re-ordered and sent out. +- * That causes APIC to think 82547 is in de-assertion +- * state, while 82547 is in assertion state, resulting +- * in dead lock. Writing IMC forces 82547 into +- * de-assertion state. +- */ +- if (hw->mac_type == iegbe_82547 || hw->mac_type == iegbe_82547_rev_2) { +- atomic_inc(&adapter->irq_sem); +- E1000_WRITE_REG(hw, IMC, ~0); +- } +- +-#ifdef IEGBE_GBE_WORKAROUND +- +- for (i = 0; i < E1000_MAX_INTR; i++) { +- rx_cleaned = adapter->clean_rx(adapter, adapter->rx_ring); +- adapter->stats.rx_next_to_clean = adapter->rx_ring->next_to_clean; +- adapter->stats.rx_next_to_use = adapter->rx_ring->next_to_use; +- +- adapter->stats.tx_next_to_clean = adapter->tx_ring->next_to_clean; +- adapter->stats.tx_next_to_use = adapter->tx_ring->next_to_use; +- +- /* Only clean Tx descriptors for a TXQE interrupt */ +- if(icr & E1000_ICR_TXQE) { +- adapter->stats.txqec++; +- iegbe_clean_tx_ring_partial(adapter, adapter->tx_ring); +- } +- else { +- iegbe_tx_hang_check(adapter, adapter->tx_ring); +- } +- if(!rx_cleaned) { +- break; +- } ++ /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No ++ * need for the IMC write */ ++ if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { ++ hw->get_link_status = 1; ++ /* guard against interrupt when we're going down */ ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ mod_timer(&adapter->watchdog_timer, jiffies + 1); ++ + } + +-#else +- for (i = 0; i < E1000_MAX_INTR; i++) +- if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & +- !iegbe_clean_tx_irq(adapter, adapter->tx_ring))) { +- break; +- } +-#endif +- +- if (hw->mac_type == iegbe_82547 || hw->mac_type == iegbe_82547_rev_2) { +- iegbe_irq_enable(adapter); +- } +-#endif +-#ifdef E1000_COUNT_ICR +- adapter->icr_txdw += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_txqe += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_lsc += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxseq += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxdmt += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxo += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxt += icr & 0x01UL; +- if(hw->mac_type != iegbe_icp_xxxx) { +- icr >>= 0x2; +- adapter->icr_mdac += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxcfg += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_gpi += icr & 0x01UL; +- } else { +- icr >>= 0x4; +- } +- if(hw->mac_type == iegbe_icp_xxxx) { +- icr >>= 0xc; +- adapter->icr_pb += icr & 0x01UL; +- icr >>= 0x3; +- adapter->icr_intmem_icp_xxxx += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_cpp_target += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_cpp_master += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_stat += icr & 0x01UL; ++ if (unlikely(hw->mac_type < iegbe_82571)) { ++ E1000_WRITE_REG(&adapter->hw, IMC, ~0); ++ E1000_WRITE_FLUSH(&adapter->hw); + } +-#endif ++ if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ adapter->total_tx_bytes = 0; ++ adapter->total_tx_packets = 0; ++ adapter->total_rx_bytes = 0; ++ adapter->total_rx_packets = 0; ++ __netif_rx_schedule(netdev, &adapter->napi); ++ } else ++ /* this really should not happen! if it does it is basically a ++ * bug, but not a hard error, so enable ints and continue */ ++ iegbe_irq_enable(adapter); + + return IRQ_HANDLED; + } + +-#ifdef CONFIG_E1000_NAPI + /** + * iegbe_clean - NAPI Rx polling callback + * @adapter: board private structure + **/ +- +-static int +-iegbe_clean(struct net_device *poll_dev, int *budget) ++static int iegbe_clean(struct napi_struct *napi, int budget) + { +- struct iegbe_adapter *adapter; +- int work_to_do = min(*budget, poll_dev->quota); +- int tx_cleaned, i = 0, work_done = 0; ++ struct iegbe_adapter *adapter = container_of(napi, struct iegbe_adapter, napi); ++ struct net_device *poll_dev = adapter->netdev; ++ int tx_cleaned = 0, work_done = 0; + + /* Must NOT use netdev_priv macro here. */ + adapter = poll_dev->priv; + +- /* Keep link state information with original netdev */ +- if (!netif_carrier_ok(adapter->netdev)) { +- goto quit_polling; +- } +- while (poll_dev != &adapter->polling_netdev[i]) { +- i++; +- if (unlikely(i == adapter->num_queues)) { +- BUG(); +- } +- } +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Tx descriptors are cleaned in iegbe_intr(). No need to clean +- them here */ +- tx_cleaned = FALSE; +-#else +- tx_cleaned = iegbe_clean_tx_irq(adapter, &adapter->tx_ring[i]); +-#endif +- adapter->clean_rx(adapter, &adapter->rx_ring[i], +- &work_done, work_to_do); +- +- *budget -= work_done; +- poll_dev->quota -= work_done; +- +- /* If no Tx and not enough Rx work done, exit the polling mode */ +- if((!tx_cleaned && (work_done == 0)) || +- !netif_running(adapter->netdev)) { +-quit_polling: +- netif_rx_complete(poll_dev); ++ /* iegbe_clean is called per-cpu. This lock protects ++ * tx_ring[0] from being cleaned by multiple cpus ++ * simultaneously. A failure obtaining the lock means ++ * tx_ring[0] is currently being cleaned anyway. */ ++ if (spin_trylock(&adapter->tx_queue_lock)) { ++ tx_cleaned = iegbe_clean_tx_irq(adapter, ++ &adapter->tx_ring[0]); ++ spin_unlock(&adapter->tx_queue_lock); ++ } ++ ++ adapter->clean_rx(adapter, &adapter->rx_ring[0], ++ &work_done, budget); ++ ++ if (tx_cleaned) ++ work_done = budget; ++ ++ /* If budget not fully consumed, exit the polling mode */ ++ if (work_done < budget) { ++ if (likely(adapter->itr_setting & 3)) ++ iegbe_set_itr(adapter); ++ netif_rx_complete(poll_dev, napi); + iegbe_irq_enable(adapter); +- return 0; + } + +- return 1; ++ return work_done; + } + +-#endif +- +- +-#ifndef IEGBE_GBE_WORKAROUND + /** + * iegbe_clean_tx_irq - Reclaim resources after transmit completes + * @adapter: board private structure + **/ +- +-static boolean_t +-iegbe_clean_tx_irq(struct iegbe_adapter *adapter, ++static bool iegbe_clean_tx_irq(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring) + { +- struct net_device *netdev = adapter->netdev; +- struct iegbe_tx_desc *tx_desc, *eop_desc; +- struct iegbe_buffer *buffer_info; +- unsigned int i, eop; +- boolean_t cleaned = FALSE; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct iegbe_tx_desc *tx_desc, *eop_desc; ++ struct iegbe_buffer *buffer_info; ++ unsigned int i, eop; ++ unsigned int count = 0; ++ bool cleaned = false; ++ unsigned int total_tx_bytes=0, total_tx_packets=0; + +- i = tx_ring->next_to_clean; +- eop = tx_ring->buffer_info[i].next_to_watch; +- eop_desc = E1000_TX_DESC(*tx_ring, eop); ++ i = tx_ring->next_to_clean; ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC(*tx_ring, eop); + + while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { +- /* Premature writeback of Tx descriptors clear (free buffers +- * and unmap pci_mapping) previous_buffer_info */ +- if (likely(tx_ring->previous_buffer_info.skb != NULL)) { +- iegbe_unmap_and_free_tx_resource(adapter, +- &tx_ring->previous_buffer_info); +- } +- +- for (cleaned = FALSE; !cleaned; ) { +- tx_desc = E1000_TX_DESC(*tx_ring, i); +- buffer_info = &tx_ring->buffer_info[i]; +- cleaned = (i == eop); +- +-#ifdef NETIF_F_TSO +- if (!(netdev->features & NETIF_F_TSO)) { +-#endif +- iegbe_unmap_and_free_tx_resource(adapter, +- buffer_info); +-#ifdef NETIF_F_TSO +- } else { +- if (cleaned) { +- memcpy(&tx_ring->previous_buffer_info, +- buffer_info, +- sizeof(struct iegbe_buffer)); +- memset(buffer_info, 0, +- sizeof(struct iegbe_buffer)); +- } else { +- iegbe_unmap_and_free_tx_resource( +- adapter, buffer_info); +- } +- } +-#endif +- +- tx_desc->buffer_addr = 0; +- tx_desc->lower.data = 0; ++ for (cleaned = false; !cleaned; ) { ++ tx_desc = E1000_TX_DESC(*tx_ring, i); ++ buffer_info = &tx_ring->buffer_info[i]; ++ cleaned = (i == eop); ++ ++ if (cleaned) { ++ struct sk_buff *skb = buffer_info->skb; ++ unsigned int segs = 0, bytecount; ++ segs = skb_shinfo(skb)->gso_segs ?: 1; ++ bytecount = ((segs - 1) * skb_headlen(skb)) + ++ skb->len; ++ total_tx_packets += segs; ++ total_tx_bytes += bytecount; ++ } ++ iegbe_unmap_and_free_tx_resource(adapter, buffer_info); + tx_desc->upper.data = 0; + +- if (unlikely(++i == tx_ring->count)) { i = 0; } +- } +- +- tx_ring->pkt++; ++ if (unlikely(++i == tx_ring->count)) i = 0; ++ } + +- eop = tx_ring->buffer_info[i].next_to_watch; +- eop_desc = E1000_TX_DESC(*tx_ring, eop); +- } ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC(*tx_ring, eop); ++#define E1000_TX_WEIGHT 64 ++ /* weight of a sort for tx, to avoid endless transmit cleanup */ ++ if (count++ == E1000_TX_WEIGHT) ++ break; ++ } + + tx_ring->next_to_clean = i; + +- spin_lock(&tx_ring->tx_lock); ++#define TX_WAKE_THRESHOLD 32 + +- if (unlikely(cleaned && netif_queue_stopped(netdev) && +- netif_carrier_ok(netdev))) { +- netif_wake_queue(netdev); +- } +- spin_unlock(&tx_ring->tx_lock); +- +- if (adapter->detect_tx_hung) { +- /* Detect a transmit hang in hardware, this serializes the +- * check with the clearing of time_stamp and movement of i */ +- adapter->detect_tx_hung = FALSE; +- +- if (tx_ring->buffer_info[i].dma && +- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) +- && !(E1000_READ_REG(&adapter->hw, STATUS) & +- E1000_STATUS_TXOFF)) { +- +- /* detected Tx unit hang */ +- i = tx_ring->next_to_clean; +- eop = tx_ring->buffer_info[i].next_to_watch; +- eop_desc = E1000_TX_DESC(*tx_ring, eop); +- DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" +- " TDH <%x>\n" +- " TDT <%x>\n" +- " next_to_use <%x>\n" +- " next_to_clean <%x>\n" +- "buffer_info[next_to_clean]\n" +- " dma <%zx>\n" +- " time_stamp <%lx>\n" +- " next_to_watch <%x>\n" +- " jiffies <%lx>\n" +- " next_to_watch.status <%x>\n", +- readl(adapter->hw.hw_addr + tx_ring->tdh), +- readl(adapter->hw.hw_addr + tx_ring->tdt), +- tx_ring->next_to_use, +- i, +- (size_t)tx_ring->buffer_info[i].dma, +- tx_ring->buffer_info[i].time_stamp, +- eop, +- jiffies, +- eop_desc->upper.fields.status); +- netif_stop_queue(netdev); ++ if (unlikely(cleaned && netif_carrier_ok(netdev) && ++ E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) { ++ /* Make sure that anybody stopping the queue after this ++ * sees the new next_to_clean. ++ */ ++ smp_mb(); ++ if (netif_queue_stopped(netdev)) { ++ netif_wake_queue(netdev); ++ ++adapter->restart_queue; + } + } +-#ifdef NETIF_F_TSO +- if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && +- time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ))) { +- iegbe_unmap_and_free_tx_resource( +- adapter, &tx_ring->previous_buffer_info); ++ ++ if (adapter->detect_tx_hung) { ++ /* Detect a transmit hang in hardware, this serializes the ++ * check with the clearing of time_stamp and movement of i */ ++ adapter->detect_tx_hung = false; ++ ++ if (tx_ring->buffer_info[eop].dma && ++ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + ++ (adapter->tx_timeout_factor * HZ)) ++ && !(E1000_READ_REG(hw, STATUS) & E1000_STATUS_TXOFF)) { ++ ++ /* detected Tx unit hang */ ++ DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" ++ " Tx Queue <%lu>\n" ++ " TDH <%x>\n" ++ " TDT <%x>\n" ++ " next_to_use <%x>\n" ++ " next_to_clean <%x>\n" ++ "buffer_info[next_to_clean]\n" ++ " time_stamp <%lx>\n" ++ " next_to_watch <%x>\n" ++ " jiffies <%lx>\n" ++ " next_to_watch.status <%x>\n", ++ (unsigned long)((tx_ring - adapter->tx_ring) / ++ sizeof(struct iegbe_tx_ring)), ++ readl(hw->hw_addr + tx_ring->tdh), ++ readl(hw->hw_addr + tx_ring->tdt), ++ tx_ring->next_to_use, ++ tx_ring->next_to_clean, ++ tx_ring->buffer_info[eop].time_stamp, ++ eop, ++ jiffies, ++ eop_desc->upper.fields.status); ++ netif_stop_queue(netdev); ++ } + } +-#endif +- return cleaned; ++ adapter->total_tx_bytes += total_tx_bytes; ++ adapter->total_tx_packets += total_tx_packets; ++ adapter->net_stats.tx_bytes += total_tx_bytes; ++ adapter->net_stats.tx_packets += total_tx_packets; ++ return cleaned; + } +-#endif + + /** + * iegbe_rx_checksum - Receive Checksum Offload for 82543 +@@ -3913,192 +3689,193 @@ iegbe_clean_tx_irq(struct iegbe_adapter + * @sk_buff: socket buffer with received data + **/ + +-static inline void +-iegbe_rx_checksum(struct iegbe_adapter *adapter, +- uint32_t status_err, uint32_t csum, +- struct sk_buff *skb) ++static void iegbe_rx_checksum(struct iegbe_adapter *adapter, u32 status_err, ++ u32 csum, struct sk_buff *skb) + { +- uint16_t status = (uint16_t)status_err; +- uint8_t errors = (uint8_t)(status_err >> 0x18); ++ struct iegbe_hw *hw = &adapter->hw; ++ u16 status = (u16)status_err; ++ u8 errors = (u8)(status_err >> 24); + skb->ip_summed = CHECKSUM_NONE; + +- /* 82543 or newer only */ +- if(unlikely(adapter->hw.mac_type < iegbe_82543)) { return; } +- /* Ignore Checksum bit is set */ +- if(unlikely(status & E1000_RXD_STAT_IXSM)) { return; } +- /* TCP/UDP checksum error bit is set */ +- if(unlikely(errors & E1000_RXD_ERR_TCPE)) { +- /* let the stack verify checksum errors */ +- adapter->hw_csum_err++; +- return; +- } +- /* TCP/UDP Checksum has not been calculated */ +- if(adapter->hw.mac_type <= iegbe_82547_rev_2) { +- if(!(status & E1000_RXD_STAT_TCPCS)) { +- return; ++ /* 82543 or newer only */ ++ if (unlikely(hw->mac_type < iegbe_82543)) return; ++ /* Ignore Checksum bit is set */ ++ if (unlikely(status & E1000_RXD_STAT_IXSM)) return; ++ /* TCP/UDP checksum error bit is set */ ++ if(unlikely(errors & E1000_RXD_ERR_TCPE)) { ++ /* let the stack verify checksum errors */ ++ adapter->hw_csum_err++; ++ return; ++ } ++ /* TCP/UDP Checksum has not been calculated */ ++ if (hw->mac_type <= iegbe_82547_rev_2) { ++ if (!(status & E1000_RXD_STAT_TCPCS)) ++ return; ++ } else { ++ if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) ++ return; + } +- } else { +- if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) { +- return; +- } ++ /* It must be a TCP or UDP packet with a valid checksum */ ++ if(likely(status & E1000_RXD_STAT_TCPCS)) { ++ /* TCP checksum is good */ ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } else if (hw->mac_type > iegbe_82547_rev_2) { ++ /* IP fragment with UDP payload */ ++ /* Hardware complements the payload checksum, so we undo it ++ * and then put the value in host order for further stack use. ++ */ ++ __sum16 sum = (__force __sum16)htons(csum); ++ skb->csum = csum_unfold(~sum); ++ skb->ip_summed = CHECKSUM_COMPLETE; + } +- /* It must be a TCP or UDP packet with a valid checksum */ +- if(likely(status & E1000_RXD_STAT_TCPCS)) { +- /* TCP checksum is good */ +- skb->ip_summed = CHECKSUM_UNNECESSARY; +- } else if(adapter->hw.mac_type > iegbe_82547_rev_2) { +- /* IP fragment with UDP payload */ +- /* Hardware complements the payload checksum, so we undo it +- * and then put the value in host order for further stack use. +- */ +- csum = ntohl(csum ^ 0xFFFF); +- skb->csum = csum; +- skb->ip_summed = CHECKSUM_HW; +- } +- adapter->hw_csum_good++; ++ adapter->hw_csum_good++; + } + + /** + * iegbe_clean_rx_irq - Send received data up the network stack; legacy + * @adapter: board private structure + **/ +- +-static boolean_t +-#ifdef CONFIG_E1000_NAPI +-iegbe_clean_rx_irq(struct iegbe_adapter *adapter, ++static bool iegbe_clean_rx_irq(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do) +-#else +-iegbe_clean_rx_irq(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- struct iegbe_rx_desc *rx_desc; +- struct iegbe_buffer *buffer_info; +- struct sk_buff *skb; +- unsigned long flags = 0; +- uint32_t length; +- uint8_t last_byte; +- unsigned int i; +- boolean_t cleaned = FALSE; +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Need to keep track of the amount of Rx descriptors that we +- cleaned to ensure that we don't supply too many back to the +- hardware */ +- int cleaned_count = 0; +-#endif +- +- i = rx_ring->next_to_clean; +- rx_desc = E1000_RX_DESC(*rx_ring, i); +- +- while(rx_desc->status & E1000_RXD_STAT_DD) { +- buffer_info = &rx_ring->buffer_info[i]; +-#ifdef CONFIG_E1000_NAPI +- if(*work_done >= work_to_do) { +- break; +- } +- (*work_done)++; +-#endif +- cleaned = TRUE; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ struct iegbe_rx_desc *rx_desc, *next_rxd; ++ struct iegbe_buffer *buffer_info, *next_buffer; ++ unsigned long flags; ++ u32 length; ++ u8 last_byte; ++ unsigned int i; ++ int cleaned_count = 0; ++ bool cleaned = false; ++ unsigned int total_rx_bytes=0, total_rx_packets=0; + +-#ifdef IEGBE_GBE_WORKAROUND +- cleaned_count++; +-#endif ++ i = rx_ring->next_to_clean; ++ rx_desc = E1000_RX_DESC(*rx_ring, i); ++ buffer_info = &rx_ring->buffer_info[i]; + +- pci_unmap_single(pdev, +- buffer_info->dma, +- buffer_info->length, +- PCI_DMA_FROMDEVICE); ++ while(rx_desc->status & E1000_RXD_STAT_DD) { ++ struct sk_buff *skb; ++ u8 status; ++ if (*work_done >= work_to_do) ++ break; ++ (*work_done)++; + ++ status = rx_desc->status; + skb = buffer_info->skb; +- length = le16_to_cpu(rx_desc->length); ++ buffer_info->skb = NULL; ++ prefetch(skb->data - NET_IP_ALIGN); ++ if (++i == rx_ring->count) i = 0; ++ next_rxd = E1000_RX_DESC(*rx_ring, i); ++ prefetch(next_rxd); ++ next_buffer = &rx_ring->buffer_info[i]; ++ cleaned = true; ++ cleaned_count++; ++ pci_unmap_single(pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_FROMDEVICE); ++ ++ length = le16_to_cpu(rx_desc->length); ++ ++ if (unlikely(!(status & E1000_RXD_STAT_EOP))) { ++ /* All receives must fit into a single buffer */ ++ E1000_DBG("%s: Receive packet consumed multiple" ++ " buffers\n", netdev->name); ++ buffer_info->skb = skb; ++ goto next_desc; ++ } + +- if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) { +- /* All receives must fit into a single buffer */ +- E1000_DBG("%s: Receive packet consumed multiple" +- " buffers\n", netdev->name); +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } ++ if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { ++ last_byte = *(skb->data + length - 1); ++ if (TBI_ACCEPT(hw, status, rx_desc->errors, length, ++ last_byte)) { ++ spin_lock_irqsave(&adapter->stats_lock, flags); ++ iegbe_tbi_adjust_stats(hw, &adapter->stats, ++ length, skb->data); ++ spin_unlock_irqrestore(&adapter->stats_lock, ++ flags); ++ length--; ++ } else { ++ buffer_info->skb = skb; ++ goto next_desc; ++ } ++ } + +- if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { +- last_byte = *(skb->data + length - 0x1); +- if(TBI_ACCEPT(&adapter->hw, rx_desc->status, +- rx_desc->errors, length, last_byte)) { +- spin_lock_irqsave(&adapter->stats_lock, flags); +- iegbe_tbi_adjust_stats(&adapter->hw, +- &adapter->stats, +- length, skb->data); +- spin_unlock_irqrestore(&adapter->stats_lock, +- flags); +- length--; +- } else { +- dev_kfree_skb_irq(skb); +- goto next_desc; ++ /* adjust length to remove Ethernet CRC, this must be ++ * done after the TBI_ACCEPT workaround above */ ++ length -= 4; ++ ++ /* probably a little skewed due to removing CRC */ ++ total_rx_bytes += length; ++ total_rx_packets++; ++ ++ /* code added for copybreak, this should improve ++ * performance for small packets with large amounts ++ * of reassembly being done in the stack */ ++ if (length < copybreak) { ++ struct sk_buff *new_skb = ++ netdev_alloc_skb(netdev, length + NET_IP_ALIGN); ++ if (new_skb) { ++ skb_reserve(new_skb, NET_IP_ALIGN); ++ skb_copy_to_linear_data_offset(new_skb, ++ -NET_IP_ALIGN, ++ (skb->data - ++ NET_IP_ALIGN), ++ (length + ++ NET_IP_ALIGN)); ++ /* save the skb in buffer_info as good */ ++ buffer_info->skb = skb; ++ skb = new_skb; + } ++ /* else just continue with the old one */ + } +- +- /* Good Receive */ +- skb_put(skb, length - ETHERNET_FCS_SIZE); ++ /* Good Receive */ ++ skb_put(skb, length); + + /* Receive Checksum Offload */ + iegbe_rx_checksum(adapter, +- (uint32_t)(rx_desc->status) | +- ((uint32_t)(rx_desc->errors) << 0x18), +- rx_desc->csum, skb); ++ (u32)(status) | ++ ((u32)(rx_desc->errors) << 24), ++ le16_to_cpu(rx_desc->csum), skb); ++ + skb->protocol = eth_type_trans(skb, netdev); +-#ifdef CONFIG_E1000_NAPI +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && +- (rx_desc->status & E1000_RXD_STAT_VP))) { ++ ++ if (unlikely(adapter->vlgrp && ++ (status & E1000_RXD_STAT_VP))) { + vlan_hwaccel_receive_skb(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->special) & +- E1000_RXD_SPC_VLAN_MASK); ++ le16_to_cpu(rx_desc->special)); + } else { + netif_receive_skb(skb); + } +-#else +- netif_receive_skb(skb); +-#endif +-#else /* CONFIG_E1000_NAPI */ +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && +- (rx_desc->status & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_rx(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->special) & +- E1000_RXD_SPC_VLAN_MASK); +- } else { +- netif_rx(skb); +- } +-#else +- netif_rx(skb); +-#endif +-#endif /* CONFIG_E1000_NAPI */ ++ + netdev->last_rx = jiffies; +- rx_ring->pkt++; + + next_desc: + rx_desc->status = 0; +- buffer_info->skb = NULL; +- if(unlikely(++i == rx_ring->count)) { i = 0; } + +- rx_desc = E1000_RX_DESC(*rx_ring, i); ++ /* return some buffers to hardware, one at a time is too slow */ ++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ cleaned_count = 0; ++ } ++ ++ /* use prefetched values */ ++ rx_desc = next_rxd; ++ buffer_info = next_buffer; + } + rx_ring->next_to_clean = i; + +-#ifdef IEGBE_GBE_WORKAROUND +- /* Only allocate the number of buffers that we have actually +- cleaned! */ +- if (cleaned_count) { +- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); +- } +-#else +- adapter->alloc_rx_buf(adapter, rx_ring); +-#endif +- ++ cleaned_count = E1000_DESC_UNUSED(rx_ring); ++ if (cleaned_count) ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ ++ adapter->total_rx_packets += total_rx_packets; ++ adapter->total_rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_packets += total_rx_packets; + return cleaned; + } + +@@ -4107,161 +3884,153 @@ next_desc: + * @adapter: board private structure + **/ + +-static boolean_t +-#ifdef CONFIG_E1000_NAPI +-iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, ++static bool iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do) +-#else +-iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- union iegbe_rx_desc_packet_split *rx_desc; +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- struct iegbe_buffer *buffer_info; +- struct iegbe_ps_page *ps_page; +- struct iegbe_ps_page_dma *ps_page_dma; +- struct sk_buff *skb; +- unsigned int i, j; +- uint32_t length, staterr; +- boolean_t cleaned = FALSE; +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Need to keep track of the amount of Rx descriptors that we +- cleaned to ensure that we don't supply too many back to the +- hardware */ +- int cleaned_count = 0; +-#endif +- +- i = rx_ring->next_to_clean; +- rx_desc = E1000_RX_DESC_PS(*rx_ring, i); +- staterr = le32_to_cpu(rx_desc->wb.middle.status_error); +- +- while(staterr & E1000_RXD_STAT_DD) { +- buffer_info = &rx_ring->buffer_info[i]; +- ps_page = &rx_ring->ps_page[i]; +- ps_page_dma = &rx_ring->ps_page_dma[i]; +-#ifdef CONFIG_E1000_NAPI +- if(unlikely(*work_done >= work_to_do)) { +- break; +- } +- (*work_done)++; +-#endif +- cleaned = TRUE; +- +-#ifdef IEGBE_GBE_WORKAROUND +- cleaned_count++; +-#endif ++ union iegbe_rx_desc_packet_split *rx_desc, *next_rxd; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ struct iegbe_buffer *buffer_info, *next_buffer; ++ struct iegbe_ps_page *ps_page; ++ struct iegbe_ps_page_dma *ps_page_dma; ++ struct sk_buff *skb; ++ unsigned int i, j; ++ u32 length, staterr; ++ int cleaned_count = 0; ++ bool cleaned = false; ++ unsigned int total_rx_bytes=0, total_rx_packets=0; ++ ++ i = rx_ring->next_to_clean; ++ rx_desc = E1000_RX_DESC_PS(*rx_ring, i); ++ staterr = le32_to_cpu(rx_desc->wb.middle.status_error); ++ buffer_info = &rx_ring->buffer_info[i]; + +- pci_unmap_single(pdev, buffer_info->dma, +- buffer_info->length, +- PCI_DMA_FROMDEVICE); ++ while(staterr & E1000_RXD_STAT_DD) { ++ ps_page = &rx_ring->ps_page[i]; ++ ps_page_dma = &rx_ring->ps_page_dma[i]; ++ ++ if (unlikely(*work_done >= work_to_do)) ++ break; ++ (*work_done)++; + + skb = buffer_info->skb; ++ prefetch(skb->data - NET_IP_ALIGN); ++ if (++i == rx_ring->count) i = 0; ++ next_rxd = E1000_RX_DESC_PS(*rx_ring, i); ++ prefetch(next_rxd); ++ next_buffer = &rx_ring->buffer_info[i]; ++ cleaned = true; ++ cleaned_count++; ++ pci_unmap_single(pdev, buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_FROMDEVICE); ++ ++ if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) { ++ E1000_DBG("%s: Packet Split buffers didn't pick up" ++ " the full packet\n", netdev->name); ++ dev_kfree_skb_irq(skb); ++ goto next_desc; ++ } + +- if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) { +- E1000_DBG("%s: Packet Split buffers didn't pick up" +- " the full packet\n", netdev->name); +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } +- +- if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } +- +- length = le16_to_cpu(rx_desc->wb.middle.length0); ++ if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { ++ dev_kfree_skb_irq(skb); ++ goto next_desc; ++ } + +- if(unlikely(!length)) { +- E1000_DBG("%s: Last part of the packet spanning" +- " multiple descriptors\n", netdev->name); +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } ++ length = le16_to_cpu(rx_desc->wb.middle.length0); + +- /* Good Receive */ +- skb_put(skb, length); +- +- for(j = 0; j < adapter->rx_ps_pages; j++) { +- if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) { +- break; +- } +- pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], +- PAGE_SIZE, PCI_DMA_FROMDEVICE); +- ps_page_dma->ps_page_dma[j] = 0; +- skb_shinfo(skb)->frags[j].page = +- ps_page->ps_page[j]; +- ps_page->ps_page[j] = NULL; +- skb_shinfo(skb)->frags[j].page_offset = 0; +- skb_shinfo(skb)->frags[j].size = length; +- skb_shinfo(skb)->nr_frags++; +- skb->len += length; +- skb->data_len += length; +- } ++ if(unlikely(!length)) { ++ E1000_DBG("%s: Last part of the packet spanning" ++ " multiple descriptors\n", netdev->name); ++ dev_kfree_skb_irq(skb); ++ goto next_desc; ++ } + +- iegbe_rx_checksum(adapter, staterr, +- rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); +- skb->protocol = eth_type_trans(skb, netdev); ++ /* Good Receive */ ++ skb_put(skb, length); + +- if(likely(rx_desc->wb.upper.header_status & +- E1000_RXDPS_HDRSTAT_HDRSP)) { +- adapter->rx_hdr_split++; +-#ifdef HAVE_RX_ZERO_COPY +- skb_shinfo(skb)->zero_copy = TRUE; +-#endif +- } +-#ifdef CONFIG_E1000_NAPI +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_receive_skb(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->wb.middle.vlan) & +- E1000_RXD_SPC_VLAN_MASK); +- } else { +- netif_receive_skb(skb); +- } +-#else +- netif_receive_skb(skb); +-#endif +-#else /* CONFIG_E1000_NAPI */ +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_rx(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->wb.middle.vlan) & +- E1000_RXD_SPC_VLAN_MASK); +- } else { +- netif_rx(skb); +- } +-#else +- netif_rx(skb); +-#endif +-#endif /* CONFIG_E1000_NAPI */ +- netdev->last_rx = jiffies; +- rx_ring->pkt++; ++ { ++ int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); ++ if (l1 && (l1 <= copybreak) && ((length + l1) <= adapter->rx_ps_bsize0)) { ++ u8 *vaddr; ++ pci_dma_sync_single_for_cpu(pdev, ++ ps_page_dma->ps_page_dma[0], ++ PAGE_SIZE, ++ PCI_DMA_FROMDEVICE); ++ vaddr = kmap_atomic(ps_page->ps_page[0], ++ KM_SKB_DATA_SOFTIRQ); ++ memcpy(skb_tail_pointer(skb), vaddr, l1); ++ kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); ++ pci_dma_sync_single_for_device(pdev, ++ ps_page_dma->ps_page_dma[0], ++ PAGE_SIZE, PCI_DMA_FROMDEVICE); ++ l1 -= 4; ++ skb_put(skb, l1); ++ goto copydone; ++ } /* if */ ++ } ++ for (j = 0; j < adapter->rx_ps_pages; j++) { ++ length = le16_to_cpu(rx_desc->wb.upper.length[j]); ++ if (!length) ++ break; ++ pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], ++ PAGE_SIZE, PCI_DMA_FROMDEVICE); ++ ps_page_dma->ps_page_dma[j] = 0; ++ skb_fill_page_desc(skb, j, ps_page->ps_page[j], 0, ++ length); ++ ps_page->ps_page[j] = NULL; ++ skb->len += length; ++ skb->data_len += length; ++ skb->truesize += length; ++ } + +-next_desc: +- rx_desc->wb.middle.status_error &= ~0xFF; +- buffer_info->skb = NULL; +- if(unlikely(++i == rx_ring->count)) { i = 0; } ++ pskb_trim(skb, skb->len - 4); ++copydone: ++ total_rx_bytes += skb->len; ++ total_rx_packets++; ++ iegbe_rx_checksum(adapter, staterr, ++ le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb); ++ skb->protocol = eth_type_trans(skb, netdev); ++ ++ if(likely(rx_desc->wb.upper.header_status & ++ cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))) ++ adapter->rx_hdr_split++; ++ ++ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { ++ vlan_hwaccel_receive_skb(skb, adapter->vlgrp, ++ le16_to_cpu(rx_desc->wb.middle.vlan)); ++ } else { ++ netif_receive_skb(skb); ++ } + +- rx_desc = E1000_RX_DESC_PS(*rx_ring, i); +- staterr = le32_to_cpu(rx_desc->wb.middle.status_error); +- } +- rx_ring->next_to_clean = i; ++ netdev->last_rx = jiffies; + +-#ifdef IEGBE_GBE_WORKAROUND +- /* Only allocate the number of buffers that we have actually +- cleaned! */ +- if (cleaned_count) { +- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); +- } +-#else +- adapter->alloc_rx_buf(adapter, rx_ring); +-#endif ++next_desc: ++ rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF); ++ buffer_info->skb = NULL; + +- return cleaned; ++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ cleaned_count = 0; ++ } ++ ++ /* use prefetched values */ ++ rx_desc = next_rxd; ++ buffer_info = next_buffer; ++ staterr = le32_to_cpu(rx_desc->wb.middle.status_error); ++ } ++ rx_ring->next_to_clean = i; ++ ++ cleaned_count = E1000_DESC_UNUSED(rx_ring); ++ if (cleaned_count) ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ ++ adapter->total_rx_packets += total_rx_packets; ++ adapter->total_rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_packets += total_rx_packets; ++ return cleaned; + } + + /** +@@ -4269,142 +4038,115 @@ next_desc: + * @adapter: address of board private structure + **/ + +-#ifdef IEGBE_GBE_WORKAROUND +-static void +-iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, ++ ++static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count) +-#else +-static void +-iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- struct iegbe_rx_desc *rx_desc; +- struct iegbe_buffer *buffer_info; +- struct sk_buff *skb; +- unsigned int i; +- unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; +- +- i = rx_ring->next_to_use; +- buffer_info = &rx_ring->buffer_info[i]; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ struct iegbe_rx_desc *rx_desc; ++ struct iegbe_buffer *buffer_info; ++ struct sk_buff *skb; ++ unsigned int i; ++ unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; + +-#ifdef IEGBE_GBE_WORKAROUND +- if (cleaned_count > IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS) { +- adapter->stats.cc_gt_num_rx++; +- } +- while(cleaned_count-- && !buffer_info->skb) { +-#else +- while(!buffer_info->skb) { +-#endif +- skb = dev_alloc_skb(bufsz); ++ i = rx_ring->next_to_use; ++ buffer_info = &rx_ring->buffer_info[i]; + +- if(unlikely(!skb)) { +- /* Better luck next round */ +- break; +- } ++ while (cleaned_count--) { ++ skb = buffer_info->skb; ++ if (skb) { ++ skb_trim(skb, 0); ++ goto map_skb; ++ } ++ skb = netdev_alloc_skb(netdev, bufsz); ++ ++ if(unlikely(!skb)) { ++ /* Better luck next round */ ++ adapter->alloc_rx_buff_failed++; ++ break; ++ } + +- /* Fix for errata 23, can't cross 64kB boundary */ +- if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { +- struct sk_buff *oldskb = skb; +- DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " +- "at %p\n", bufsz, skb->data); +- /* Try again, without freeing the previous */ +- skb = dev_alloc_skb(bufsz); +- /* Failed allocation, critical failure */ +- if(!skb) { +- dev_kfree_skb(oldskb); +- break; +- } ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { ++ struct sk_buff *oldskb = skb; ++ DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " ++ "at %p\n", bufsz, skb->data); ++ /* Try again, without freeing the previous */ ++ skb = netdev_alloc_skb(netdev, bufsz); ++ /* Failed allocation, critical failure */ ++ if(!skb) { ++ dev_kfree_skb(oldskb); ++ break; ++ } + +- if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { +- /* give up */ +- dev_kfree_skb(skb); +- dev_kfree_skb(oldskb); +- break; /* while !buffer_info->skb */ +- } else { +- /* Use new allocation */ +- dev_kfree_skb(oldskb); ++ if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { ++ /* give up */ ++ dev_kfree_skb(skb); ++ dev_kfree_skb(oldskb); ++ break; /* while !buffer_info->skb */ + } +- } +- /* Make buffer alignment 2 beyond a 16 byte boundary +- * this will result in a 16 byte aligned IP header after +- * the 14 byte MAC header is removed +- */ +- skb_reserve(skb, NET_IP_ALIGN); +- +- skb->dev = netdev; +- +- buffer_info->skb = skb; +- buffer_info->length = adapter->rx_buffer_len; +- buffer_info->dma = pci_map_single(pdev, +- skb->data, +- adapter->rx_buffer_len, +- PCI_DMA_FROMDEVICE); +- +- /* Fix for errata 23, can't cross 64kB boundary */ +- if(!iegbe_check_64k_bound(adapter, +- (void *)(unsigned long)buffer_info->dma, +- adapter->rx_buffer_len)) { +- DPRINTK(RX_ERR, ERR, +- "dma align check failed: %u bytes at %p\n", +- adapter->rx_buffer_len, +- (void *)(unsigned long)buffer_info->dma); +- dev_kfree_skb(skb); +- buffer_info->skb = NULL; +- +- pci_unmap_single(pdev, buffer_info->dma, +- adapter->rx_buffer_len, +- PCI_DMA_FROMDEVICE); +- +- break; /* while !buffer_info->skb */ +- } +- rx_desc = E1000_RX_DESC(*rx_ring, i); +- rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); +- +-#ifdef IEGBE_GBE_WORKAROUND_DISABLED +- adapter->stats.num_rx_buf_alloc++; ++ /* Use new allocation */ ++ dev_kfree_skb(oldskb); ++ } ++ /* Make buffer alignment 2 beyond a 16 byte boundary ++ * this will result in a 16 byte aligned IP header after ++ * the 14 byte MAC header is removed ++ */ ++ skb_reserve(skb, NET_IP_ALIGN); ++ ++ ++ buffer_info->skb = skb; ++ buffer_info->length = adapter->rx_buffer_len; ++map_skb: ++ buffer_info->dma = pci_map_single(pdev, ++ skb->data, ++ adapter->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); ++ ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if(!iegbe_check_64k_bound(adapter, ++ (void *)(unsigned long)buffer_info->dma, ++ adapter->rx_buffer_len)) { ++ DPRINTK(RX_ERR, ERR, ++ "dma align check failed: %u bytes at %p\n", ++ adapter->rx_buffer_len, ++ (void *)(unsigned long)buffer_info->dma); ++ dev_kfree_skb(skb); ++ buffer_info->skb = NULL; ++ ++ pci_unmap_single(pdev, buffer_info->dma, ++ adapter->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); + +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); +- writel(i, adapter->hw.hw_addr + rx_ring->rdt); ++ break; /* while !buffer_info->skb */ ++ } ++ rx_desc = E1000_RX_DESC(*rx_ring, i); ++ rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + +-#endif +-#ifndef IEGBE_GBE_WORKAROUND +- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 0x1)) == i)) { +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); +- writel(i, adapter->hw.hw_addr + rx_ring->rdt); +- } +-#endif +- if(unlikely(++i == rx_ring->count)) { i = 0; } +- buffer_info = &rx_ring->buffer_info[i]; +- } ++ /* Force memory writes to complete before letting h/w ++ * know there are new descriptors to fetch. (Only ++ * applicable for weak-ordered memory model archs, ++ * such as IA-64). */ ++ if (unlikely(++i == rx_ring->count)) ++ i = 0; ++ buffer_info = &rx_ring->buffer_info[i]; ++ } + +-#ifdef IEGBE_GBE_WORKAROUND + if (likely(rx_ring->next_to_use != i)) { +- rx_ring->next_to_use = i; +- if (unlikely(i-- == 0)) { +- i = (rx_ring->count - 0x1); +- } ++ rx_ring->next_to_use = i; ++ if (unlikely(i-- == 0)) ++ i = (rx_ring->count - 1); ++ + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). */ + wmb(); +- writel(i, adapter->hw.hw_addr + rx_ring->rdt); ++ writel(i, hw->hw_addr + rx_ring->rdt); + } +-#else +- rx_ring->next_to_use = i; +-#endif + } + + /** +@@ -4412,49 +4154,41 @@ iegbe_alloc_rx_buffers(struct iegbe_adap + * @adapter: address of board private structure + **/ + +-#ifdef IEGBE_GBE_WORKAROUND +-static void +-iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, ++ ++static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count) +-#else +-static void +-iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- union iegbe_rx_desc_packet_split *rx_desc; +- struct iegbe_buffer *buffer_info; +- struct iegbe_ps_page *ps_page; +- struct iegbe_ps_page_dma *ps_page_dma; +- struct sk_buff *skb; +- unsigned int i, j; +- +- i = rx_ring->next_to_use; +- buffer_info = &rx_ring->buffer_info[i]; +- ps_page = &rx_ring->ps_page[i]; +- ps_page_dma = &rx_ring->ps_page_dma[i]; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ union iegbe_rx_desc_packet_split *rx_desc; ++ struct iegbe_buffer *buffer_info; ++ struct iegbe_ps_page *ps_page; ++ struct iegbe_ps_page_dma *ps_page_dma; ++ struct sk_buff *skb; ++ unsigned int i, j; ++ ++ i = rx_ring->next_to_use; ++ buffer_info = &rx_ring->buffer_info[i]; ++ ps_page = &rx_ring->ps_page[i]; ++ ps_page_dma = &rx_ring->ps_page_dma[i]; + +-#ifdef IEGBE_GBE_WORKAROUND +- while(cleaned_count-- && !buffer_info->skb) { +-#else +- while(!buffer_info->skb) { +-#endif +- rx_desc = E1000_RX_DESC_PS(*rx_ring, i); ++ while (cleaned_count--) { ++ rx_desc = E1000_RX_DESC_PS(*rx_ring, i); + + for (j = 0; j < PS_PAGE_BUFFERS; j++) { +- if (j < adapter->rx_ps_pages) { +- if (likely(!ps_page->ps_page[j])) { +- ps_page->ps_page[j] = +- alloc_page(GFP_ATOMIC); ++ if (j < adapter->rx_ps_pages) { ++ if (likely(!ps_page->ps_page[j])) { ++ ps_page->ps_page[j] = ++ alloc_page(GFP_ATOMIC); + if (unlikely(!ps_page->ps_page[j])) { +- goto no_buffers; ++ adapter->alloc_rx_buff_failed++; ++ goto no_buffers; + } +- ps_page_dma->ps_page_dma[j] = +- pci_map_page(pdev, +- ps_page->ps_page[j], ++ ps_page_dma->ps_page_dma[j] = ++ pci_map_page(pdev, ++ ps_page->ps_page[j], + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + } +@@ -4462,26 +4196,26 @@ iegbe_alloc_rx_buffers_ps(struct iegbe_a + * change because each write-back erases + * this info. + */ +- rx_desc->read.buffer_addr[j+0x1] = ++ rx_desc->read.buffer_addr[j+1] = + cpu_to_le64(ps_page_dma->ps_page_dma[j]); +- } else { +- rx_desc->read.buffer_addr[j+0x1] = ~0; +- } ++ } else ++ rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0); + } + +- skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN); ++ skb = netdev_alloc_skb(netdev, ++ adapter->rx_ps_bsize0 + NET_IP_ALIGN); + +- if (unlikely(!skb)) { ++ if (unlikely(!skb)) { ++ adapter->alloc_rx_buff_failed++; + break; +- } ++ } ++ + /* Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); + +- skb->dev = netdev; +- + buffer_info->skb = skb; + buffer_info->length = adapter->rx_ps_bsize0; + buffer_info->dma = pci_map_single(pdev, skb->data, +@@ -4490,27 +4224,28 @@ iegbe_alloc_rx_buffers_ps(struct iegbe_a + + rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); + +- if (unlikely((i & ~(E1000_RX_BUFFER_WRITE - 0x1)) == i)) { +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); +- /* Hardware increments by 16 bytes, but packet split +- * descriptors are 32 bytes...so we increment tail +- * twice as much. +- */ +- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt); +- } +- +- if (unlikely(++i == rx_ring->count)) { i = 0; } ++ if (unlikely(++i == rx_ring->count)) i = 0; + buffer_info = &rx_ring->buffer_info[i]; + ps_page = &rx_ring->ps_page[i]; + ps_page_dma = &rx_ring->ps_page_dma[i]; + } + + no_buffers: +- rx_ring->next_to_use = i; ++ if (likely(rx_ring->next_to_use != i)) { ++ rx_ring->next_to_use = i; ++ if (unlikely(i-- == 0)) i = (rx_ring->count - 1); ++ ++ /* Force memory writes to complete before letting h/w ++ * know there are new descriptors to fetch. (Only ++ * applicable for weak-ordered memory model archs, ++ * such as IA-64). */ ++ wmb(); ++ /* Hardware increments by 16 bytes, but packet split ++ * descriptors are 32 bytes...so we increment tail ++ * twice as much. ++ */ ++ writel(i<<1, hw->hw_addr + rx_ring->rdt); ++ } + } + + /** +@@ -4521,52 +4256,52 @@ no_buffers: + static void + iegbe_smartspeed(struct iegbe_adapter *adapter) + { +- uint16_t phy_status; +- uint16_t phy_ctrl; ++ uint16_t phy_status; ++ uint16_t phy_ctrl; + +- if((adapter->hw.phy_type != iegbe_phy_igp) || !adapter->hw.autoneg || ++ if((adapter->hw.phy_type != iegbe_phy_igp) || !adapter->hw.autoneg || + !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL)) { +- return; ++ return; + } +- if(adapter->smartspeed == 0) { +- /* If Master/Slave config fault is asserted twice, +- * we assume back-to-back */ +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); ++ if(adapter->smartspeed == 0x0) { ++ /* If Master/Slave config fault is asserted twice, ++ * we assume back-to-back */ ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); + if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) { return; } +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); + if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) { return; } +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); +- if(phy_ctrl & CR_1000T_MS_ENABLE) { +- phy_ctrl &= ~CR_1000T_MS_ENABLE; +- iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, +- phy_ctrl); +- adapter->smartspeed++; +- if(!iegbe_phy_setup_autoneg(&adapter->hw) && +- !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, +- &phy_ctrl)) { +- phy_ctrl |= (MII_CR_AUTO_NEG_EN | +- MII_CR_RESTART_AUTO_NEG); +- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, +- phy_ctrl); +- } +- } +- return; +- } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { +- /* If still no link, perhaps using 2/3 pair cable */ +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); +- phy_ctrl |= CR_1000T_MS_ENABLE; +- iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); +- if(!iegbe_phy_setup_autoneg(&adapter->hw) && +- !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { +- phy_ctrl |= (MII_CR_AUTO_NEG_EN | +- MII_CR_RESTART_AUTO_NEG); +- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl); +- } +- } +- /* Restart process after E1000_SMARTSPEED_MAX iterations */ ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); ++ if(phy_ctrl & CR_1000T_MS_ENABLE) { ++ phy_ctrl &= ~CR_1000T_MS_ENABLE; ++ iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, ++ phy_ctrl); ++ adapter->smartspeed++; ++ if(!iegbe_phy_setup_autoneg(&adapter->hw) && ++ !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, ++ &phy_ctrl)) { ++ phy_ctrl |= (MII_CR_AUTO_NEG_EN | ++ MII_CR_RESTART_AUTO_NEG); ++ iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, ++ phy_ctrl); ++ } ++ } ++ return; ++ } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { ++ /* If still no link, perhaps using 2/3 pair cable */ ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); ++ phy_ctrl |= CR_1000T_MS_ENABLE; ++ iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); ++ if(!iegbe_phy_setup_autoneg(&adapter->hw) && ++ !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { ++ phy_ctrl |= (MII_CR_AUTO_NEG_EN | ++ MII_CR_RESTART_AUTO_NEG); ++ iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl); ++ } ++ } ++ /* Restart process after E1000_SMARTSPEED_MAX iterations */ + if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX) { +- adapter->smartspeed = 0; +-} ++ adapter->smartspeed = 0x0; ++ } + } + + /** +@@ -4576,23 +4311,22 @@ iegbe_smartspeed(struct iegbe_adapter *a + * @cmd: + **/ + +-static int +-iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++static int iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + { +- switch (cmd) { ++ switch (cmd) { + #ifdef SIOCGMIIPHY +- case SIOCGMIIPHY: +- case SIOCGMIIREG: +- case SIOCSMIIREG: +- return iegbe_mii_ioctl(netdev, ifr, cmd); ++ case SIOCGMIIPHY: ++ case SIOCGMIIREG: ++ case SIOCSMIIREG: ++ return iegbe_mii_ioctl(netdev, ifr, cmd); + #endif + #ifdef ETHTOOL_OPS_COMPAT +- case SIOCETHTOOL: +- return ethtool_ioctl(ifr); ++ case SIOCETHTOOL: ++ return ethtool_ioctl(ifr); + #endif +- default: +- return -EOPNOTSUPP; +- } ++ default: ++ return -EOPNOTSUPP; ++ } + } + + #ifdef SIOCGMIIPHY +@@ -4603,534 +4337,510 @@ iegbe_ioctl(struct net_device *netdev, s + * @cmd: + **/ + +-static int +-iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++static int iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, ++ int cmd) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- struct mii_ioctl_data *data = if_mii(ifr); +- int retval; +- uint16_t mii_reg; +- uint16_t spddplx; +- unsigned long flags; +- +- if((adapter->hw.media_type == iegbe_media_type_oem && +- !iegbe_oem_phy_is_copper(&adapter->hw)) || +- adapter->hw.media_type == iegbe_media_type_fiber || +- adapter->hw.media_type == iegbe_media_type_internal_serdes ) { +- return -EOPNOTSUPP; +- } +- switch (cmd) { +- case SIOCGMIIPHY: +- data->phy_id = adapter->hw.phy_addr; +- break; +- case SIOCGMIIREG: ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct mii_ioctl_data *data = if_mii(ifr); ++ int retval; ++ uint16_t mii_reg; ++ uint16_t spddplx; ++ unsigned long flags = 0; ++ ++ if((adapter->hw.media_type == iegbe_media_type_oem ++ && !iegbe_oem_phy_is_copper(&adapter->hw)) ++ ||adapter->hw.media_type != iegbe_media_type_copper) { ++ return -EOPNOTSUPP; ++ } ++ switch (cmd) { ++ case SIOCGMIIPHY: ++ data->phy_id = adapter->hw.phy_addr; ++ break; ++ case SIOCGMIIREG: + if(!capable(CAP_NET_ADMIN)) { +- return -EPERM; ++ return -EPERM; + } +- spin_lock_irqsave(&adapter->stats_lock, flags); +- if(iegbe_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, +- &data->val_out)) { +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- return -EIO; +- } +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- break; +- case SIOCSMIIREG: ++ spin_lock_irqsave(&adapter->stats_lock, flags); ++ if(iegbe_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, ++ &data->val_out)) { ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ return -EIO; ++ } ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ break; ++ case SIOCSMIIREG: + if(!capable(CAP_NET_ADMIN)){ +- return -EPERM; ++ return -EPERM; + } + if(data->reg_num & ~(0x1F)) { +- return -EFAULT; ++ return -EFAULT; + } +- mii_reg = data->val_in; +- spin_lock_irqsave(&adapter->stats_lock, flags); +- if(iegbe_write_phy_reg(&adapter->hw, data->reg_num, +- mii_reg)) { +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- return -EIO; +- } +- switch(adapter->hw.phy_type) { +- case iegbe_phy_m88: +- switch (data->reg_num) { +- case PHY_CTRL: ++ mii_reg = data->val_in; ++ spin_lock_irqsave(&adapter->stats_lock, flags); ++ if(iegbe_write_phy_reg(&adapter->hw, data->reg_num, ++ mii_reg)) { ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ return -EIO; ++ } ++ switch(adapter->hw.phy_type) { ++ case iegbe_phy_m88: ++ switch (data->reg_num) { ++ case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +- break; ++ break; + } +- if(mii_reg & MII_CR_AUTO_NEG_EN) { +- adapter->hw.autoneg = 1; +- adapter->hw.autoneg_advertised = 0x2F; +- } else { ++ if(mii_reg & MII_CR_AUTO_NEG_EN) { ++ adapter->hw.autoneg = 1; ++ adapter->hw.autoneg_advertised = 0x2F; ++ } else { + if(mii_reg & 0x40){ +- spddplx = SPEED_1000; ++ spddplx = SPEED_1000; + } else if(mii_reg & 0x2000) { +- spddplx = SPEED_100; ++ spddplx = SPEED_100; + } else { +- spddplx = SPEED_10; ++ spddplx = SPEED_10; + } +- spddplx += (mii_reg & 0x100) +- ? FULL_DUPLEX : +- HALF_DUPLEX; +- retval = iegbe_set_spd_dplx(adapter, +- spddplx); +- if(retval) { +- spin_unlock_irqrestore( +- &adapter->stats_lock, +- flags); +- return retval; +- } +- } +- if(netif_running(adapter->netdev)) { +- iegbe_down(adapter); +- iegbe_up(adapter); ++ spddplx += (mii_reg & 0x100) ++ ? FULL_DUPLEX : ++ HALF_DUPLEX; ++ retval = iegbe_set_spd_dplx(adapter, ++ spddplx); ++ if(retval) { ++ spin_unlock_irqrestore( ++ &adapter->stats_lock, ++ flags); ++ return retval; ++ } ++ } ++ if(netif_running(adapter->netdev)) { ++ iegbe_down(adapter); ++ iegbe_up(adapter); + } else { +- iegbe_reset(adapter); ++ iegbe_reset(adapter); + } +- break; +- case M88E1000_PHY_SPEC_CTRL: +- case M88E1000_EXT_PHY_SPEC_CTRL: +- if(iegbe_phy_reset(&adapter->hw)) { +- spin_unlock_irqrestore( +- &adapter->stats_lock, flags); +- return -EIO; +- } +- break; +- } +- break; ++ break; ++ case M88E1000_PHY_SPEC_CTRL: ++ case M88E1000_EXT_PHY_SPEC_CTRL: ++ if(iegbe_phy_reset(&adapter->hw)) { ++ spin_unlock_irqrestore( ++ &adapter->stats_lock, flags); ++ return -EIO; ++ } ++ break; ++ } ++ break; + +- case iegbe_phy_oem: +- retval = iegbe_oem_mii_ioctl(adapter, flags, ifr, cmd); +- if(retval) { +- spin_unlock_irqrestore( +- &adapter->stats_lock, flags); +- return retval; +- } +- break; ++ case iegbe_phy_oem: ++ retval = iegbe_oem_mii_ioctl(adapter, flags, ifr, cmd); ++ if(retval) { ++ spin_unlock_irqrestore( ++ &adapter->stats_lock, flags); ++ return retval; ++ } ++ break; + +- default: +- switch (data->reg_num) { +- case PHY_CTRL: ++ default: ++ switch (data->reg_num) { ++ case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +- break; ++ break; + } +- if(netif_running(adapter->netdev)) { +- iegbe_down(adapter); +- iegbe_up(adapter); ++ if(netif_running(adapter->netdev)) { ++ iegbe_down(adapter); ++ iegbe_up(adapter); + } else { +- iegbe_reset(adapter); ++ iegbe_reset(adapter); + } +- break; +- } +- } +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- break; +- default: +- return -EOPNOTSUPP; +- } +- return E1000_SUCCESS; ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ return E1000_SUCCESS; + } + #endif + +-void +-iegbe_pci_set_mwi(struct iegbe_hw *hw) ++void iegbe_pci_set_mwi(struct iegbe_hw *hw) + { +- struct iegbe_adapter *adapter = hw->back; +-#ifdef HAVE_PCI_SET_MWI +- int ret_val = pci_set_mwi(adapter->pdev); +- +- if(ret_val) { +- DPRINTK(PROBE, ERR, "Error in setting MWI\n"); +- } +-#else +- pci_write_config_word(adapter->pdev, PCI_COMMAND, +- adapter->hw.pci_cmd_word | +- PCI_COMMAND_INVALIDATE); +-#endif ++ struct iegbe_adapter *adapter = hw->back; ++ int ret_val = pci_set_mwi(adapter->pdev); ++ ++ if (ret_val) ++ DPRINTK(PROBE, ERR, "Error in setting MWI\n"); + } + +-void +-iegbe_pci_clear_mwi(struct iegbe_hw *hw) ++void iegbe_pci_clear_mwi(struct iegbe_hw *hw) + { +- struct iegbe_adapter *adapter = hw->back; ++ struct iegbe_adapter *adapter = hw->back; + +-#ifdef HAVE_PCI_SET_MWI +- pci_clear_mwi(adapter->pdev); +-#else +- pci_write_config_word(adapter->pdev, PCI_COMMAND, +- adapter->hw.pci_cmd_word & +- ~PCI_COMMAND_INVALIDATE); +-#endif ++ pci_clear_mwi(adapter->pdev); + } + + void + iegbe_read_pci_cfg(struct iegbe_hw *hw, uint32_t reg, uint16_t *value) + { +- struct iegbe_adapter *adapter = hw->back; ++ struct iegbe_adapter *adapter = hw->back; + +- pci_read_config_word(adapter->pdev, reg, value); ++ pci_read_config_word(adapter->pdev, reg, value); + } + + void + iegbe_write_pci_cfg(struct iegbe_hw *hw, uint32_t reg, uint16_t *value) + { +- struct iegbe_adapter *adapter = hw->back; ++ struct iegbe_adapter *adapter = hw->back; + +- pci_write_config_word(adapter->pdev, reg, *value); ++ pci_write_config_word(adapter->pdev, reg, *value); + } + + uint32_t + iegbe_io_read(struct iegbe_hw *hw, unsigned long port) + { +- return inl(port); ++ return inl(port); + } + + void + iegbe_io_write(struct iegbe_hw *hw, unsigned long port, uint32_t value) + { +- outl(value, port); ++ outl(value, port); + } + +-#ifdef NETIF_F_HW_VLAN_TX +-static void +-iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ++static void iegbe_vlan_rx_register(struct net_device *netdev, ++ struct vlan_group *grp) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t ctrl, rctl; +- +- iegbe_irq_disable(adapter); +- adapter->vlgrp = grp; +- +- if(grp) { +- /* enable VLAN tag insert/strip */ +- ctrl = E1000_READ_REG(&adapter->hw, CTRL); +- ctrl |= E1000_CTRL_VME; +- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); +- +- /* enable VLAN receive filtering */ +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl |= E1000_RCTL_VFE; +- rctl &= ~E1000_RCTL_CFIEN; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- iegbe_update_mng_vlan(adapter); +- } else { +- /* disable VLAN tag insert/strip */ +- ctrl = E1000_READ_REG(&adapter->hw, CTRL); +- ctrl &= ~E1000_CTRL_VME; +- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t ctrl, rctl; + +- /* disable VLAN filtering */ +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl &= ~E1000_RCTL_VFE; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { +- iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); +- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- } +- } ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ iegbe_irq_disable(adapter); ++ adapter->vlgrp = grp; ++ ++ if(grp) { ++ /* enable VLAN tag insert/strip */ ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ ctrl |= E1000_CTRL_VME; ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ ++ /* enable VLAN receive filtering */ ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl |= E1000_RCTL_VFE; ++ rctl &= ~E1000_RCTL_CFIEN; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ iegbe_update_mng_vlan(adapter); ++ } else { ++ /* disable VLAN tag insert/strip */ ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ ctrl &= ~E1000_CTRL_VME; ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ ++ /* disable VLAN filtering */ ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl &= ~E1000_RCTL_VFE; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { ++ iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); ++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; ++ } ++ } + +- iegbe_irq_enable(adapter); ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ iegbe_irq_enable(adapter); + } + +-static void +-iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) ++static void iegbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t vfta, index; +- if((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t vfta, index; ++ if((adapter->hw.mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && + (vid == adapter->mng_vlan_id)) { +- return; ++ return; + } +- /* add VID to filter table */ ++ /* add VID to filter table */ + index = (vid >> 0x5) & 0x7F; +- vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); ++ vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); + vfta |= (0x1 << (vid & 0x1F)); +- iegbe_write_vfta(&adapter->hw, index, vfta); ++ iegbe_write_vfta(&adapter->hw, index, vfta); + } + +-static void +-iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) ++static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t vfta, index; ++ u32 vfta, index; + ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) + iegbe_irq_disable(adapter); +- +- if(adapter->vlgrp) { +- adapter->vlgrp->vlan_devices[vid] = NULL; +- } ++ vlan_group_set_device(adapter->vlgrp, vid, NULL); ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) + iegbe_irq_enable(adapter); + +- if((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && +- (vid == adapter->mng_vlan_id)) { +- return; +- } + /* remove VID from filter table */ +- index = (vid >> 0x5) & 0x7F; ++ index = (vid >> 0x5) & 0x7F; + vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); +- vfta &= ~(0x1 << (vid & 0x1F)); ++ vfta &= ~(0x1 << (vid & 0x1F)); + iegbe_write_vfta(&adapter->hw, index, vfta); + } + +-static void +-iegbe_restore_vlan(struct iegbe_adapter *adapter) ++static void iegbe_restore_vlan(struct iegbe_adapter *adapter) + { + iegbe_vlan_rx_register(adapter->netdev, adapter->vlgrp); + +- if(adapter->vlgrp) { +- uint16_t vid; +- for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { +- if(!adapter->vlgrp->vlan_devices[vid]) { ++ if (adapter->vlgrp) { ++ u16 vid; ++ for (vid = 0x0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { ++ if (!vlan_group_get_device(adapter->vlgrp, vid)) + continue; +- } + iegbe_vlan_rx_add_vid(adapter->netdev, vid); + } + } + } +-#endif + +-int +-iegbe_set_spd_dplx(struct iegbe_adapter *adapter, uint16_t spddplx) ++ ++int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, u16 spddplx) + { +- adapter->hw.autoneg = 0; ++ adapter->hw.autoneg = 0x0; + +- /* Fiber NICs only allow 1000 gbps Full duplex */ +- if((adapter->hw.media_type == iegbe_media_type_fiber ++ /* Fiber NICs only allow 1000 gbps Full duplex */ ++ if((adapter->hw.media_type == iegbe_media_type_fiber + || (adapter->hw.media_type == iegbe_media_type_oem + && !iegbe_oem_phy_is_copper(&adapter->hw))) +- && spddplx != (SPEED_1000 + FULL_DUPLEX)) { +- DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); +- return -EINVAL; +- } +- +- switch(spddplx) { +- case SPEED_10 + HALF_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_10_half; +- break; +- case SPEED_10 + FULL_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_10_full; +- break; +- case SPEED_100 + HALF_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_100_half; +- break; +- case SPEED_100 + FULL_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_100_full; +- break; +- case SPEED_1000 + FULL_DUPLEX: ++ && spddplx != (SPEED_1000 + DUPLEX_FULL)) { ++ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); ++ return -EINVAL; ++ } ++ ++ switch(spddplx) { ++ case SPEED_10 + DUPLEX_HALF: ++ adapter->hw.forced_speed_duplex = iegbe_10_half; ++ break; ++ case SPEED_10 + DUPLEX_FULL: ++ adapter->hw.forced_speed_duplex = iegbe_10_full; ++ break; ++ case SPEED_100 + DUPLEX_HALF: ++ adapter->hw.forced_speed_duplex = iegbe_100_half; ++ break; ++ case SPEED_100 + DUPLEX_FULL: ++ adapter->hw.forced_speed_duplex = iegbe_100_full; ++ break; ++ case SPEED_1000 + DUPLEX_FULL: + adapter->hw.autoneg = 0x1; +- adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; +- break; +- case SPEED_1000 + HALF_DUPLEX: /* not supported */ +- default: +- DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); +- return -EINVAL; +- } +- return 0; ++ adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; ++ break; ++ case SPEED_1000 + DUPLEX_HALF: /* not supported */ ++ default: ++ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); ++ return -EINVAL; ++ } ++ return 0x0; + } + + static int + iegbe_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) + { +- struct pci_dev *pdev = NULL; ++ struct pci_dev *pdev = NULL; + pm_message_t state = {0x3}; + + +- switch(event) { +- case SYS_DOWN: +- case SYS_HALT: +- case SYS_POWER_OFF: +- while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { ++ switch(event) { ++ case SYS_DOWN: ++ case SYS_HALT: ++ case SYS_POWER_OFF: ++ while((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { + if(pci_dev_driver(pdev) == &iegbe_driver) { +- iegbe_suspend(pdev, state); +- } +- } ++ iegbe_suspend(pdev, state); ++ } ++ } + } +- return NOTIFY_DONE; ++ return NOTIFY_DONE; + } + + static int + iegbe_suspend(struct pci_dev *pdev, pm_message_t state) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; +- uint32_t wufc = adapter->wol; +- uint16_t cmd_word; ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; ++ uint32_t wufc = adapter->wol; ++ uint16_t cmd_word; + +- netif_device_detach(netdev); ++ netif_device_detach(netdev); + + if(netif_running(netdev)) { +- iegbe_down(adapter); ++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); ++ iegbe_down(adapter); + } +- /* +- * ICP_XXXX style MACs do not have a link up bit in +- * the STATUS register, query the PHY directly +- */ +- if(adapter->hw.mac_type != iegbe_icp_xxxx) { +- status = E1000_READ_REG(&adapter->hw, STATUS); ++ /* ++ * ICP_XXXX style MACs do not have a link up bit in ++ * the STATUS register, query the PHY directly ++ */ ++ if(adapter->hw.mac_type != iegbe_icp_xxxx) { ++ status = E1000_READ_REG(&adapter->hw, STATUS); + if(status & E1000_STATUS_LU) { +- wufc &= ~E1000_WUFC_LNKC; ++ wufc &= ~E1000_WUFC_LNKC; + } +- } else { +- int isUp = 0; ++ } else { ++ int isUp = 0x0; + if(iegbe_oem_phy_is_link_up(&adapter->hw, &isUp) != E1000_SUCCESS) { +- isUp = 0; ++ isUp = 0x0; + } + if(isUp) { +- wufc &= ~E1000_WUFC_LNKC; +- } ++ wufc &= ~E1000_WUFC_LNKC; ++ } + } + +- if(wufc) { +- iegbe_setup_rctl(adapter); +- iegbe_set_multi(netdev); +- +- /* turn on all-multi mode if wake on multicast is enabled */ +- if(adapter->wol & E1000_WUFC_MC) { +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl |= E1000_RCTL_MPE; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- } ++ if(wufc) { ++ iegbe_setup_rctl(adapter); ++ iegbe_set_rx_mode(netdev); ++ ++ /* turn on all-multi mode if wake on multicast is enabled */ ++ if(adapter->wol & E1000_WUFC_MC) { ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl |= E1000_RCTL_MPE; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ } + +- if(adapter->hw.mac_type >= iegbe_82540) { +- ctrl = E1000_READ_REG(&adapter->hw, CTRL); +- /* advertise wake from D3Cold */ +- #define E1000_CTRL_ADVD3WUC 0x00100000 +- /* phy power management enable */ +- ctrl |= E1000_CTRL_ADVD3WUC | +- (adapter->hw.mac_type != iegbe_icp_xxxx +- ? E1000_CTRL_EN_PHY_PWR_MGMT : 0); ++ if(adapter->hw.mac_type >= iegbe_82540) { ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ /* advertise wake from D3Cold */ ++ #define E1000_CTRL_ADVD3WUC 0x00100000 ++ /* phy power management enable */ ++ #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 ++ ctrl |= E1000_CTRL_ADVD3WUC | ++ (adapter->hw.mac_type != iegbe_icp_xxxx ++ ? E1000_CTRL_EN_PHY_PWR_MGMT : 0x0); + +- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); +- } ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ } + +- if(adapter->hw.media_type == iegbe_media_type_fiber || +- adapter->hw.media_type == iegbe_media_type_internal_serdes) { +- /* keep the laser running in D3 */ +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); +- } ++ if(adapter->hw.media_type == iegbe_media_type_fiber || ++ adapter->hw.media_type == iegbe_media_type_internal_serdes) { ++ /* keep the laser running in D3 */ ++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ++ ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; ++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); ++ } + + /* Allow OEM PHYs (if any exist) to keep the laser + *running in D3 */ + iegbe_oem_fiber_live_in_suspend(&adapter->hw); + +- /* Allow time for pending master requests to run */ +- iegbe_disable_pciex_master(&adapter->hw); ++ /* Allow time for pending master requests to run */ ++ iegbe_disable_pciex_master(&adapter->hw); + +- E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); +- E1000_WRITE_REG(&adapter->hw, WUFC, wufc); ++ E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); ++ E1000_WRITE_REG(&adapter->hw, WUFC, wufc); + pci_enable_wake(pdev, 0x3, 0x1); + pci_enable_wake(pdev, 0x4, 0x1); /* 4 == D3 cold */ +- } else { +- E1000_WRITE_REG(&adapter->hw, WUC, 0); +- E1000_WRITE_REG(&adapter->hw, WUFC, 0); +- pci_enable_wake(pdev, 0x3, 0); +- pci_enable_wake(pdev, 0x4, 0); /* 4 == D3 cold */ +- } ++ } else { ++ E1000_WRITE_REG(&adapter->hw, WUC, 0x0); ++ E1000_WRITE_REG(&adapter->hw, WUFC, 0x0); ++ pci_enable_wake(pdev, 0x3, 0x0); ++ pci_enable_wake(pdev, 0x4, 0x0); /* 4 == D3 cold */ ++ } + +- pci_save_state(pdev); +- +- if(adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.mac_type != iegbe_icp_xxxx +- && adapter->hw.media_type == iegbe_media_type_copper) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- if(manc & E1000_MANC_SMBUS_EN) { +- manc |= E1000_MANC_ARP_EN; +- E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ pci_save_state(pdev); ++ ++ if(adapter->hw.mac_type >= iegbe_82540 ++ && adapter->hw.mac_type != iegbe_icp_xxxx ++ && adapter->hw.media_type == iegbe_media_type_copper) { ++ manc = E1000_READ_REG(&adapter->hw, MANC); ++ if(manc & E1000_MANC_SMBUS_EN) { ++ manc |= E1000_MANC_ARP_EN; ++ E1000_WRITE_REG(&adapter->hw, MANC, manc); + pci_enable_wake(pdev, 0x3, 0x1); + pci_enable_wake(pdev, 0x4, 0x1); /* 4 == D3 cold */ +- } +- } ++ } ++ } + +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm & ~E1000_SWSM_DRV_LOAD); +- break; +- default: +- break; +- } ++ switch(adapter->hw.mac_type) { ++ case iegbe_82571: ++ case iegbe_82572: ++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ++ ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); ++ break; ++ case iegbe_82573: ++ swsm = E1000_READ_REG(&adapter->hw, SWSM); ++ E1000_WRITE_REG(&adapter->hw, SWSM, ++ swsm & ~E1000_SWSM_DRV_LOAD); ++ break; ++ default: ++ break; ++ } + +- pci_disable_device(pdev); +- if(adapter->hw.mac_type == iegbe_icp_xxxx) { +- /* +- * ICP xxxx devices are not true PCI devices, in the context +- * of power management, disabling the bus mastership is not +- * sufficient to disable the device, it is also necessary to +- * disable IO, Memory, and Interrupts if they are enabled. +- */ +- pci_read_config_word(pdev, PCI_COMMAND, &cmd_word); ++ pci_disable_device(pdev); ++ if(adapter->hw.mac_type == iegbe_icp_xxxx) { ++ /* ++ * ICP xxxx devices are not true PCI devices, in the context ++ * of power management, disabling the bus mastership is not ++ * sufficient to disable the device, it is also necessary to ++ * disable IO, Memory, and Interrupts if they are enabled. ++ */ ++ pci_read_config_word(pdev, PCI_COMMAND, &cmd_word); + if(cmd_word & PCI_COMMAND_IO) { +- cmd_word &= ~PCI_COMMAND_IO; ++ cmd_word &= ~PCI_COMMAND_IO; + } + if(cmd_word & PCI_COMMAND_MEMORY) { +- cmd_word &= ~PCI_COMMAND_MEMORY; ++ cmd_word &= ~PCI_COMMAND_MEMORY; + } + if(cmd_word & PCI_COMMAND_INTX_DISABLE) { +- cmd_word &= ~PCI_COMMAND_INTX_DISABLE; ++ cmd_word &= ~PCI_COMMAND_INTX_DISABLE; + } +- pci_write_config_word(pdev, PCI_COMMAND, cmd_word); +- } ++ pci_write_config_word(pdev, PCI_COMMAND, cmd_word); ++ } + +- state.event = (state.event > 0) ? 0x3 : 0; +- pci_set_power_state(pdev, state.event); +- if(gcu_suspend == 0) ++ state.event = (state.event > 0x0) ? 0x3 : 0x0; ++ pci_set_power_state(pdev, state.event); ++ if(gcu_suspend == 0x0) + { + if(gcu == NULL) { +- gcu = pci_find_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); +- } ++ gcu = pci_get_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); ++ } + gcu_iegbe_suspend(gcu, 0x3); +- gcu_suspend = 1; +- gcu_resume = 0; ++ gcu_suspend = 0x1; ++ gcu_resume = 0x0; + } +- return 0; ++ return 0x0; + } + + #ifdef CONFIG_PM + static int + iegbe_resume(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t manc, ret_val, swsm; +- uint32_t ctrl_ext; ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t manc, ret_val, swsm; ++ uint32_t ctrl_ext; + int offset; + uint32_t vdid; + +- if(gcu_resume == 0) ++ if(gcu_resume == 0x0) + { + if(gcu == NULL) { +- gcu = pci_find_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); ++ gcu = pci_get_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); + pci_read_config_dword(gcu, 0x00, &vdid); +- } +- ++ } ++ + if(gcu) { + gcu_iegbe_resume(gcu); +- gcu_resume = 1; +- gcu_suspend = 0; ++ gcu_resume = 0x1; ++ gcu_suspend = 0x0; + } else { + printk("Unable to resume GCU!\n"); +- } ++ } + } + pci_set_power_state(pdev, 0x0); +- pci_restore_state(pdev); +- ret_val = pci_enable_device(pdev); +- pci_set_master(pdev); ++ pci_restore_state(pdev); ++ ret_val = pci_enable_device(pdev); ++ pci_set_master(pdev); + + pci_enable_wake(pdev, 0x3, 0x0); + pci_enable_wake(pdev, 0x4, 0x0); /* 4 == D3 cold */ + +- iegbe_reset(adapter); +- E1000_WRITE_REG(&adapter->hw, WUS, ~0); ++ iegbe_reset(adapter); ++ E1000_WRITE_REG(&adapter->hw, WUS, ~0); + offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_ST) + + PCI_ST_SMIA_OFFSET; + pci_write_config_dword(adapter->pdev, offset, 0x00000006); +@@ -5138,51 +4848,52 @@ iegbe_resume(struct pci_dev *pdev) + E1000_WRITE_REG(&adapter->hw, IMC2, ~0UL); + + if(netif_running(netdev)) { +- iegbe_up(adapter); ++ iegbe_up(adapter); + } +- netif_device_attach(netdev); +- +- if(adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.mac_type != iegbe_icp_xxxx +- && adapter->hw.media_type == iegbe_media_type_copper) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- manc &= ~(E1000_MANC_ARP_EN); +- E1000_WRITE_REG(&adapter->hw, MANC, manc); +- } ++ netif_device_attach(netdev); + +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm | E1000_SWSM_DRV_LOAD); +- break; +- default: +- break; +- } ++ if(adapter->hw.mac_type >= iegbe_82540 ++ && adapter->hw.mac_type != iegbe_icp_xxxx ++ && adapter->hw.media_type == iegbe_media_type_copper) { ++ manc = E1000_READ_REG(&adapter->hw, MANC); ++ manc &= ~(E1000_MANC_ARP_EN); ++ E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ } ++ ++ switch(adapter->hw.mac_type) { ++ case iegbe_82571: ++ case iegbe_82572: ++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ++ ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); ++ break; ++ case iegbe_82573: ++ swsm = E1000_READ_REG(&adapter->hw, SWSM); ++ E1000_WRITE_REG(&adapter->hw, SWSM, ++ swsm | E1000_SWSM_DRV_LOAD); ++ break; ++ default: ++ break; ++ } ++#endif + +- return 0; ++ return 0x0; + } +-#endif ++ + #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 +-iegbe_netpoll(struct net_device *netdev) ++static void iegbe_netpoll(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- disable_irq(adapter->pdev->irq); +- iegbe_intr(adapter->pdev->irq, netdev, NULL); +- enable_irq(adapter->pdev->irq); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ disable_irq(adapter->pdev->irq); ++ iegbe_intr(adapter->pdev->irq, netdev); ++ enable_irq(adapter->pdev->irq); + } + #endif + ++ + /* iegbe_main.c */ +--- a/Embedded/src/GbE/iegbe_oem_phy.c ++++ b/Embedded/src/GbE/iegbe_oem_phy.c +@@ -2,31 +2,31 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + +- This program is free software; you can redistribute it and/or modify ++ This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + +- This program is distributed in the hope that it will be useful, but +- WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ This program is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + +- You should have received a copy of the GNU General Public License +- along with this program; if not, write to the Free Software ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- The full GNU General Public License is included in this distribution ++ The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 ++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 + + *****************************************************************************/ + /************************************************************************** +@@ -65,11 +65,6 @@ static int32_t iegbe_oem_link_m88_setup( + static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw); + static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw); + +-/* Define specific BCM functions */ +-static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw); +-static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data); +-static int32_t oi_phy_setup (struct iegbe_hw *hw); +- + /** + * iegbe_oem_setup_link + * @hw: iegbe_hw struct containing device specific information +@@ -84,7 +79,7 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + { + #ifdef EXTERNAL_MDIO + +- /* ++ /* + * see iegbe_setup_copper_link() as the primary example. Look at both + * the M88 and IGP functions that are called for ideas, possibly for + * power management. +@@ -102,14 +97,14 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + } + /* AFU: add test to exit out if improper phy type + */ +- /* relevent parts of iegbe_copper_link_preconfig */ +- ctrl = E1000_READ_REG(hw, CTRL); +- ctrl |= E1000_CTRL_SLU; +- ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); +- E1000_WRITE_REG(hw, CTRL, ctrl); +- ++ /* relevent parts of iegbe_copper_link_preconfig */ ++ ctrl = E1000_READ_REG(hw, CTRL); ++ ctrl |= E1000_CTRL_SLU; ++ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ++ E1000_WRITE_REG(hw, CTRL, ctrl); ++ + /* this is required for *hw init */ +- ret_val = iegbe_oem_detect_phy(hw); ++ ret_val = iegbe_oem_detect_phy(hw); + if(ret_val) { + return ret_val; + } +@@ -119,23 +114,13 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + } + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- return E1000_SUCCESS; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_link_m88_setup(hw); +- if(ret_val) { +- return ret_val; +- } +- break; +- case BCM5481_PHY_ID: +- ret_val = iegbe_oem_link_bcm5481_setup(hw); +- if(ret_val) { +- return ret_val; ++ if(ret_val) { ++ return ret_val; + } +- break; ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -143,16 +128,16 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + + if(hw->autoneg) { + ret_val = iegbe_copper_link_autoneg(hw); +- if(ret_val) { +- return ret_val; +- } ++ if(ret_val) { ++ return ret_val; + } ++ } + else { + DEBUGOUT("Forcing speed and duplex\n"); + ret_val = iegbe_phy_force_speed_duplex(hw); + } +- +- /* ++ ++ /* + * Check link status. Wait up to 100 microseconds for link to become + * valid. + */ +@@ -194,51 +179,6 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + #endif /* ifdef EXTERNAL_MDIO */ + } + +-/** +- * iegbe_oem_link_bcm5481_setup +- * @hw: iegbe_hw struct containing device specific information +- * +- * Returns E1000_SUCCESS, negative E1000 error code on failure +- * +- * copied verbatim from iegbe_oem_link_m88_setup +- **/ +-static int32_t +-iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw) +-{ +- int32_t ret_val; +- uint16_t phy_data; +- +- //DEBUGFUNC(__func__); +- +- if(!hw) +- return -1; +- +- /* phy_reset_disable is set in iegbe_oem_set_phy_mode */ +- if(hw->phy_reset_disable) +- return E1000_SUCCESS; +- +- // Enable MDIX in extended control reg. +- ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data); +- if(ret_val) +- { +- DEBUGOUT("Unable to read BCM5481_ECTRL register\n"); +- return ret_val; +- } +- +- phy_data &= ~BCM5481_ECTRL_DISMDIX; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data); +- if(ret_val) +- { +- DEBUGOUT("Unable to write BCM5481_ECTRL register\n"); +- return ret_val; +- } +- +- ret_val = oi_phy_setup (hw); +- if (ret_val) +- return ret_val; +- +- return E1000_SUCCESS; +-} + + /** + * iegbe_oem_link_m88_setup +@@ -253,7 +193,7 @@ static int32_t + iegbe_oem_link_m88_setup(struct iegbe_hw *hw) + { + int32_t ret_val; +- uint16_t phy_data; ++ uint16_t phy_data = 0; + + DEBUGFUNC1("%s",__func__); + +@@ -261,7 +201,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + return -1; + } + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data); + phy_data |= 0x00000008; + ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, phy_data); +@@ -279,7 +219,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + + phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX; + +- /* ++ /* + * Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds +@@ -305,7 +245,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + break; + } + +- /* ++ /* + * Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity +@@ -316,25 +256,25 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + + if(hw->disable_polarity_correction == 1) { + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; +- } ++ } + ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if(ret_val) { + DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n"); + return ret_val; + } + +- /* ++ /* + * Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_EXT_PHY_SPEC_CTRL register\n"); + return ret_val; + } + +- /* ++ /* + * For Truxton, it is necessary to add RGMII tx and rx + * timing delay though the EXT_PHY_SPEC_CTRL register + */ +@@ -350,13 +290,13 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + } +- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_EXT_PHY_SPEC_CTRL register\n"); + return ret_val; + } +- ++ + + /* SW Reset the PHY so all changes take effect */ + ret_val = iegbe_phy_hw_reset(hw); +@@ -371,7 +311,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + /** + * iegbe_oem_force_mdi + * @hw: iegbe_hw struct containing device specific information +- * @resetPhy: returns true if after calling this function the ++ * @resetPhy: returns true if after calling this function the + * PHY requires a reset + * + * Returns E1000_SUCCESS, negative E1000 error code on failure +@@ -379,7 +319,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + * This is called from iegbe_phy_force_speed_duplex, which is + * called from iegbe_oem_setup_link. + **/ +-int32_t ++int32_t + iegbe_oem_force_mdi(struct iegbe_hw *hw, int *resetPhy) + { + #ifdef EXTERNAL_MDIO +@@ -393,35 +333,30 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw, + return -1; + } + +- /* ++ /* + * a boolean to indicate if the phy needs to be reset +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ M88E1000_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_PHY_SPEC_CTRL register\n"); + return ret_val; + } +- ++ + /* +- * Clear Auto-Crossover to force MDI manually. M88E1000 requires ++ * Clear Auto-Crossover to force MDI manually. M88E1000 requires + * MDI forced whenever speed are duplex are forced. + */ +- ++ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { + DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n"); +@@ -458,7 +393,7 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw, + * This is called from iegbe_phy_force_speed_duplex, which is + * called from iegbe_oem_setup_link. + **/ +-int32_t ++int32_t + iegbe_oem_phy_reset_dsp(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -478,10 +413,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw + * no-op. + */ + switch (hw->phy_id) { +- case M88E1000_I_PHY_ID: +- case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: ++ case M88E1000_I_PHY_ID: ++ case M88E1141_E_PHY_ID: + DEBUGOUT("No DSP to reset on OEM PHY\n"); + break; + default: +@@ -508,7 +441,7 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw + * This is called from iegbe_phy_force_speed_duplex, which is + * called from iegbe_oem_setup_link. + **/ +-int32_t ++int32_t + iegbe_oem_cleanup_after_phy_reset(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -520,29 +453,24 @@ iegbe_oem_cleanup_after_phy_reset(struct + + if(!hw) { + return -1; +- } ++ } + +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton. + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* +- * Because we reset the PHY above, we need to re-force ++ * Because we reset the PHY above, we need to re-force + * TX_CLK in the Extended PHY Specific Control Register to + * 25MHz clock. This value defaults back to a 2.5MHz clock + * when the PHY is reset. + */ + + ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_EXT_PHY_SPEC_CTRL, ++ M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_EXT_SPEC_CTRL register\n"); +@@ -550,22 +478,23 @@ iegbe_oem_cleanup_after_phy_reset(struct + } + + phy_data |= M88E1000_EPSCR_TX_CLK_25; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, +- M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, ++ M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { +- DEBUGOUT("Unable to write M88E1000_EXT_PHY_SPEC_CTRL register\n"); ++ DEBUGOUT("Unable to write M88E1000_EXT_PHY_SPEC_CTRL " ++ "register\n"); + return ret_val; + } + + /* + * In addition, because of the s/w reset above, we need to enable +- * CRX on TX. This must be set for both full and half duplex ++ * CRX on TX. This must be set for both full and half duplex + * operation. + */ + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ M88E1000_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_PHY_SPEC_CTRL register\n"); +@@ -573,12 +502,12 @@ iegbe_oem_cleanup_after_phy_reset(struct + } + + phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { + DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n"); + return ret_val; +- } ++ } + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -604,12 +533,12 @@ iegbe_oem_cleanup_after_phy_reset(struct + * This is called from iegbe_oem_setup_link which is + * called from iegbe_setup_link. + **/ +-static int32_t ++static int32_t + iegbe_oem_set_phy_mode(struct iegbe_hw *hw) + { + /* + * it is unclear if it is necessary to set the phy mode. Right now only +- * one MAC 82545 Rev 3 does it, but the other MACs like Tolapai do not. ++ * one MAC 82545 Rev 3 does it, but the other MACs like tola do not. + * Leave the functionality off for now until it is determined that Tolapai + * needs it as well. + */ +@@ -638,41 +567,37 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + #ifndef skip_set_mode + DEBUGOUT("No need to call oem_set_phy_mode on Truxton\n"); + #else +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton. + * + * use iegbe_set_phy_mode as example + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_read_eeprom(hw, +- EEPROM_PHY_CLASS_WORD, +- 1, ++ ret_val = iegbe_read_eeprom(hw, ++ EEPROM_PHY_CLASS_WORD, ++ 1, + &eeprom_data); + if(ret_val) { + return ret_val; + } + +- if((eeprom_data != EEPROM_RESERVED_WORD) && +- (eeprom_data & EEPROM_PHY_CLASS_A)) ++ if((eeprom_data != EEPROM_RESERVED_WORD) && ++ (eeprom_data & EEPROM_PHY_CLASS_A)) + { +- ret_val = iegbe_oem_write_phy_reg_ex(hw, +- M88E1000_PHY_PAGE_SELECT, +- 0x000B); ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, ++ M88E1000_PHY_PAGE_SELECT, ++ 0x000B); + if(ret_val) { +- DEBUGOUT("Unable to write to M88E1000_PHY_PAGE_SELECT register on PHY\n"); ++ DEBUGOUT("Unable to write to M88E1000_PHY_PAGE_SELECT " ++ "register on PHY\n"); + return ret_val; + } + +- ret_val = iegbe_oem_write_phy_reg_ex(hw, +- M88E1000_PHY_GEN_CONTROL, +- 0x8104); ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, ++ M88E1000_PHY_GEN_CONTROL, ++ 0x8104); + if(ret_val) { + DEBUGOUT("Unable to write to M88E1000_PHY_GEN_CONTROL" + "register on PHY\n"); +@@ -687,11 +612,12 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + return -E1000_ERR_PHY_TYPE; + } + #endif +- ++ + return E1000_SUCCESS; + + } + ++ + /** + * iegbe_oem_detect_phy + * @hw: iegbe_hw struct containing device specific information +@@ -702,7 +628,7 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + * + * This borrows heavily from iegbe_detect_gig_phy + **/ +-static int32_t ++static int32_t + iegbe_oem_detect_phy(struct iegbe_hw *hw) + { + int32_t ret_val; +@@ -715,33 +641,20 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw + } + hw->phy_type = iegbe_phy_oem; + +-{ +- // If MAC2 (BCM5395 switch), manually detect the phy +- struct iegbe_adapter *adapter; +- uint32_t device_number; +- adapter = (struct iegbe_adapter *) hw->back; +- device_number = PCI_SLOT(adapter->pdev->devfn); +- if (device_number == ICP_XXXX_MAC_2) { +- hw->phy_id = BCM5395S_PHY_ID; +- hw->phy_revision = 0; +- return E1000_SUCCESS; +- } +-} +- +- + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high); + if(ret_val) { + DEBUGOUT("Unable to read PHY register PHY_ID1\n"); + return ret_val; + } +- ++ + usec_delay(0x14); + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID2, &phy_id_low); + if(ret_val) { + DEBUGOUT("Unable to read PHY register PHY_ID2\n"); + return ret_val; + } +- hw->phy_id = (uint32_t) ((phy_id_high << 0x10) + phy_id_low); ++ hw->phy_id = (uint32_t) ((phy_id_high << 0x10) + ++ (phy_id_low & PHY_REVISION_MASK)); + hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK; + + return E1000_SUCCESS; +@@ -753,15 +666,15 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw + * @hw: iegbe_hw struct containing device specific information + * + * Returns the value of the Inter Packet Gap (IPG) Transmit Time (IPGT) in the +- * Transmit IPG register appropriate for the given PHY. This field is only 10 ++ * Transmit IPG register appropriate for the given PHY. This field is only 10 + * bits wide. + * + * In the original iegbe code, only the IPGT field varied between media types. +- * If the OEM phy requires setting IPG Receive Time 1 & 2 Registers, it would ++ * If the OEM phy requires setting IPG Receive Time 1 & 2 Registers, it would + * be required to modify the iegbe_config_tx() function to accomdate the change + * + **/ +-uint32_t ++uint32_t + iegbe_oem_get_tipg(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -777,15 +690,13 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw) + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT; + break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return DEFAULT_ICP_XXXX_TIPG_IPGT; + } +- ++ + return phy_num; + + #else /* ifdef EXTERNAL_MDIO */ +@@ -803,15 +714,15 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw) + * iegbe_oem_phy_is_copper + * @hw: iegbe_hw struct containing device specific information + * +- * Test for media type within the iegbe driver is common, so this is a simple +- * test for copper PHYs. The ICP_XXXX family of controllers initially only +- * supported copper interconnects (no TBI (ten bit interface) for Fiber +- * existed). If future revs support either Fiber or an internal SERDES, it +- * may become necessary to evaluate where this function is used to go beyond ++ * Test for media type within the iegbe driver is common, so this is a simple ++ * test for copper PHYs. The ICP_XXXX family of controllers initially only ++ * supported copper interconnects (no TBI (ten bit interface) for Fiber ++ * existed). If future revs support either Fiber or an internal SERDES, it ++ * may become necessary to evaluate where this function is used to go beyond + * determining whether or not media type is just copper. + * + **/ +-int ++int + iegbe_oem_phy_is_copper(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -827,23 +738,21 @@ iegbe_oem_phy_is_copper(struct iegbe_hw + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + isCopper = TRUE; + break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; + } +- ++ + return isCopper; + + #else /* ifdef EXTERNAL_MDIO */ + +- /* ++ /* + * caught between returning true or false. True allows it to + * be entered into && statements w/o ill effect, but false +- * would make more sense ++ * would make more sense + */ + DEBUGOUT("Invalid value for transceiver type, return FALSE\n"); + return FALSE; +@@ -856,19 +765,19 @@ iegbe_oem_phy_is_copper(struct iegbe_hw + * iegbe_oem_get_phy_dev_number + * @hw: iegbe_hw struct containing device specific information + * +- * For ICP_XXXX family of devices, there are 3 MACs, each of which may +- * have a different PHY (and indeed a different media interface). This +- * function is used to indicate which of the MAC/PHY pairs we are interested ++ * For ICP_XXXX family of devices, there are 3 MACs, each of which may ++ * have a different PHY (and indeed a different media interface). This ++ * function is used to indicate which of the MAC/PHY pairs we are interested + * in. +- * ++ * + **/ +-uint32_t ++uint32_t + iegbe_oem_get_phy_dev_number(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO + +- /* +- * for ICP_XXXX family of devices, the three network interfaces are ++ /* ++ * for ICP_XXXX family of devices, the three network interfaces are + * differentiated by their PCI device number, where the three share + * the same PCI bus + */ +@@ -886,15 +795,15 @@ iegbe_oem_get_phy_dev_number(struct iegb + + switch(device_number) + { +- case ICP_XXXX_MAC_0: ++ case ICP_XXXX_MAC_0: ++ hw->phy_addr = 0x00; ++ break; ++ case ICP_XXXX_MAC_1: + hw->phy_addr = 0x01; + break; +- case ICP_XXXX_MAC_1: ++ case ICP_XXXX_MAC_2: + hw->phy_addr = 0x02; + break; +- case ICP_XXXX_MAC_2: +- hw->phy_addr = 0x00; +- break; + default: hw->phy_addr = 0x00; + } + return hw->phy_addr; +@@ -915,7 +824,7 @@ iegbe_oem_get_phy_dev_number(struct iegb + * @cmd: the original IOCTL command that instigated the call chain. + * + * This function abstracts out the code necessary to service the +- * SIOCSMIIREG case within the iegbe_mii_ioctl() for oem PHYs. ++ * SIOCSMIIREG case within the iegbe_mii_ioctl() for oem PHYs. + * iegbe_mii_ioctl() was implemented for copper phy's only and this + * function will only be called if iegbe_oem_phy_is_copper() returns true for + * a given MAC. Note that iegbe_mii_ioctl() has a compile flag +@@ -924,14 +833,14 @@ iegbe_oem_get_phy_dev_number(struct iegb + * NOTE: a spinlock is in effect for the duration of this call. It is + * imperative that a negative value be returned on any error, so + * the spinlock can be released properly. +- * ++ * + **/ + int + iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags, + struct ifreq *ifr, int cmd) + { + #ifdef EXTERNAL_MDIO +- ++ + struct mii_ioctl_data *data = if_mii(ifr); + uint16_t mii_reg = data->val_in; + uint16_t spddplx; +@@ -942,12 +851,6 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(!adapter || !ifr) { + return -1; + } +- +- // If MAC2 (BCM5395 switch) then leave now +- if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) { +- return -1; +- } +- + switch (data->reg_num) { + case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +@@ -956,7 +859,7 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(mii_reg & MII_CR_AUTO_NEG_EN) { + adapter->hw.autoneg = 1; + adapter->hw.autoneg_advertised = ICP_XXXX_AUTONEG_ADV_DEFAULT; +- } ++ } + else { + if(mii_reg & 0x40) { + spddplx = SPEED_1000; +@@ -976,7 +879,7 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(netif_running(adapter->netdev)) { + iegbe_down(adapter); + iegbe_up(adapter); +- } ++ } + else { + iegbe_reset(adapter); + } +@@ -1043,10 +946,10 @@ void iegbe_oem_fiber_live_in_suspend(str + * Note: The call to iegbe_get_regs() assumed an array of 24 elements + * where the last 11 are passed to this function. If the array + * that is passed to the calling function has its size or element +- * defintions changed, this function becomes broken. ++ * defintions changed, this function becomes broken. + * + **/ +-void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, ++void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, + uint32_t data_len) + { + #define EXPECTED_ARRAY_LEN 11 +@@ -1062,13 +965,13 @@ void iegbe_oem_get_phy_regs(struct iegbe + * Use the corrected_length variable to make sure we don't exceed that + * length + */ +- corrected_len = data_len>EXPECTED_ARRAY_LEN ++ corrected_len = data_len>EXPECTED_ARRAY_LEN + ? EXPECTED_ARRAY_LEN : data_len; + memset(data, 0, corrected_len*sizeof(uint32_t)); + + #ifdef EXTERNAL_MDIO + +- /* ++ /* + * Fill data[] with... + * + * [0] = cable length +@@ -1084,16 +987,11 @@ void iegbe_oem_get_phy_regs(struct iegbe + * [10] = mdix mode + */ + switch (adapter->hw.phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + if(corrected_len > 0) { +- iegbe_oem_read_phy_reg_ex(&adapter->hw, +- M88E1000_PHY_SPEC_STATUS, ++ iegbe_oem_read_phy_reg_ex(&adapter->hw, ++ M88E1000_PHY_SPEC_STATUS, + (uint16_t *) &data[0]); + } + if(corrected_len > 0x1){ +@@ -1106,7 +1004,7 @@ void iegbe_oem_get_phy_regs(struct iegbe + data[0x3] = 0x0; /* Dummy (to align w/ IGP phy reg dump) */ + } + if(corrected_len > 0x4) { +- iegbe_oem_read_phy_reg_ex(&adapter->hw, M88E1000_PHY_SPEC_CTRL, ++ iegbe_oem_read_phy_reg_ex(&adapter->hw, M88E1000_PHY_SPEC_CTRL, + (uint16_t *) &data[0x4]); + } + if(corrected_len > 0x5) { +@@ -1144,7 +1042,7 @@ void iegbe_oem_get_phy_regs(struct iegbe + * This is called from iegbe_set_phy_loopback in response from call from + * ethtool to place the PHY into loopback mode. + **/ +-int ++int + iegbe_oem_phy_loopback(struct iegbe_adapter *adapter) + { + #ifdef EXTERNAL_MDIO +@@ -1165,23 +1063,18 @@ iegbe_oem_phy_loopback(struct iegbe_adap + * was that nonintegrated called iegbe_phy_reset_clk_and_crs(), + * hopefully this won't matter as CRS required for half-duplex + * operation and this is set to full duplex. +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton + * Loopback configuration is the same for each of the supported PHYs. + */ + switch (adapter->hw.phy_id) { +- case BCM5395S_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: + + adapter->hw.autoneg = FALSE; + + /* turn off Auto-MDI/MDIX */ +- /*ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, ++ /*ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, + M88E1000_PHY_SPEC_CTRL, 0x0808); + if(ret_val) + { +@@ -1206,10 +1099,10 @@ iegbe_oem_phy_loopback(struct iegbe_adap + DEBUGOUT("Unable to write to register PHY_CTRL\n"); + return ret_val; + } +- +- ++ ++ + /* force 1000, set loopback */ +- /*ret_val = ++ /*ret_val = + iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, 0x4140); */ + ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, 0x6100); + if(ret_val) { +@@ -1228,21 +1121,21 @@ iegbe_oem_phy_loopback(struct iegbe_adap + E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg); + + /* +- * Write out to PHY registers 29 and 30 to disable the Receiver. ++ * Write out to PHY registers 29 and 30 to disable the Receiver. + * This directly lifted from iegbe_phy_disable_receiver(). +- * ++ * + * The code is currently commented out as for the M88 used in + * Truxton, registers 29 and 30 are unutilized. Leave in, just +- * in case we are on the receiving end of an 'undocumented' ++ * in case we are on the receiving end of an 'undocumented' + * feature + */ +- /* ++ /* + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 29, 0x001F); + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 30, 0x8FFC); + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 29, 0x001A); + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 30, 0x8FF0); + */ +- ++ + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -1268,15 +1161,15 @@ iegbe_oem_phy_loopback(struct iegbe_adap + * ethtool to place the PHY out of loopback mode. This handles the OEM + * specific part of loopback cleanup. + **/ +-void ++void + iegbe_oem_loopback_cleanup(struct iegbe_adapter *adapter) + { + #ifdef EXTERNAL_MDIO + +- /* +- * This borrows liberally from iegbe_loopback_cleanup(). ++ /* ++ * This borrows liberally from iegbe_loopback_cleanup(). + * making note that the M88 phy is what'll be used on Truxton +- * ++ * + * Loopback cleanup is the same for all supported PHYs. + */ + int32_t ret_val; +@@ -1289,38 +1182,32 @@ iegbe_oem_loopback_cleanup(struct iegbe_ + } + + switch (adapter->hw.phy_id) { +- case BCM5395S_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n"); +- return; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: + default: + adapter->hw.autoneg = TRUE; +- +- ret_val = iegbe_oem_read_phy_reg_ex(&adapter->hw, PHY_CTRL, ++ ++ ret_val = iegbe_oem_read_phy_reg_ex(&adapter->hw, PHY_CTRL, + &phy_reg); + if(ret_val) { + DEBUGOUT("Unable to read to register PHY_CTRL\n"); + return; + } +- ++ + if(phy_reg & MII_CR_LOOPBACK) { + phy_reg &= ~MII_CR_LOOPBACK; +- +- ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, ++ ++ ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, + phy_reg); + if(ret_val) { + DEBUGOUT("Unable to write to register PHY_CTRL\n"); + return; + } +- ++ + iegbe_phy_reset(&adapter->hw); + } + } +- ++ + #endif /* ifdef EXTERNAL_MDIO */ + return; + +@@ -1336,7 +1223,7 @@ iegbe_oem_loopback_cleanup(struct iegbe_ + * Called by iegbe_check_downshift(), checks the PHY to see if it running + * at as speed slower than its maximum. + **/ +-uint32_t ++uint32_t + iegbe_oem_phy_speed_downgraded(struct iegbe_hw *hw, uint16_t *isDowngraded) + { + #ifdef EXTERNAL_MDIO +@@ -1356,24 +1243,19 @@ iegbe_oem_phy_speed_downgraded(struct ie + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- *isDowngraded = 0; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); + return ret_val; + } +- +- *isDowngraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) ++ ++ *isDowngraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) + >> M88E1000_PSSR_DOWNSHIFT_SHIFT; +- +- break; ++ ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return 1; +@@ -1388,7 +1270,7 @@ iegbe_oem_phy_speed_downgraded(struct ie + } + + *isDowngraded = 0; +- return 0; ++ return 0; + + #endif /* ifdef EXTERNAL_MDIO */ + } +@@ -1403,7 +1285,7 @@ iegbe_oem_phy_speed_downgraded(struct ie + * Called by iegbe_check_downshift(), checks the PHY to see if it running + * at as speed slower than its maximum. + **/ +-int32_t ++int32_t + iegbe_oem_check_polarity(struct iegbe_hw *hw, uint16_t *polarity) + { + #ifdef EXTERNAL_MDIO +@@ -1417,33 +1299,27 @@ iegbe_oem_check_polarity(struct iegbe_hw + return -1; + } + +- /* ++ /* + * borrow liberally from iegbe_check_polarity. + * Make note that the M88 phy is what'll be used on Truxton + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- *polarity = 0; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* return the Polarity bit in the Status register. */ +- ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_PHY_SPEC_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); + return ret_val; + } + +- *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) ++ *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) + >> M88E1000_PSSR_REV_POLARITY_SHIFT; +- +- break; +- ++ ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -1472,7 +1348,7 @@ iegbe_oem_check_polarity(struct iegbe_hw + * the MAC with the PHY. It turns out on ICP_XXXX, this is not + * done automagically. + **/ +-int32_t ++int32_t + iegbe_oem_phy_is_full_duplex(struct iegbe_hw *hw, int *isFD) + { + #ifdef EXTERNAL_MDIO +@@ -1485,40 +1361,22 @@ iegbe_oem_phy_is_full_duplex(struct iegb + if(!hw || !isFD) { + return -1; + } +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton + * see iegbe_config_mac_to_phy + */ +- ++ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Always full duplex */ +- *isFD = 1; +- break; +- +- case BCM5481_PHY_ID: +- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); +- if(ret_val) return ret_val; +- +- switch (BCM5481_ASTAT_HCD(phy_data)) { +- case BCM5481_ASTAT_1KBTFD: +- case BCM5481_ASTAT_100BTXFD: +- *isFD = 1; +- break; +- default: +- *isFD = 0; +- } +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +- if(ret_val) { +- DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); +- return ret_val; +- } ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ &phy_data); ++ if(ret_val) { ++ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); ++ return ret_val; ++ } + *isFD = (phy_data & M88E1000_PSSR_DPLX) != 0; +- ++ + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -1546,7 +1404,7 @@ iegbe_oem_phy_is_full_duplex(struct iegb + * the MAC with the PHY. It turns out on ICP_XXXX, this is not + * done automagically. + **/ +-int32_t ++int32_t + iegbe_oem_phy_is_speed_1000(struct iegbe_hw *hw, int *is1000) + { + #ifdef EXTERNAL_MDIO +@@ -1565,28 +1423,10 @@ iegbe_oem_phy_is_speed_1000(struct iegbe + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Always 1000mb */ +- *is1000 = 1; +- break; +- +- case BCM5481_PHY_ID: +- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); +- if(ret_val) return ret_val; +- +- switch (BCM5481_ASTAT_HCD(phy_data)) { +- case BCM5481_ASTAT_1KBTFD: +- case BCM5481_ASTAT_1KBTHD: +- *is1000 = 1; +- break; +- default: +- *is1000 = 0; +- } +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); + return ret_val; +@@ -1638,28 +1478,9 @@ iegbe_oem_phy_is_speed_100(struct iegbe_ + * see iegbe_config_mac_to_phy + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Always 1000Mb, never 100mb */ +- *is100 = 0; +- break; +- +- case BCM5481_PHY_ID: +- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); +- if(ret_val) return ret_val; +- +- switch (BCM5481_ASTAT_HCD(phy_data)) { +- case BCM5481_ASTAT_100BTXFD: +- case BCM5481_ASTAT_100BTXHD: +- *is100 = 1; +- break; +- default: +- *is100 = 0; +- } +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, + M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { +@@ -1714,29 +1535,24 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + * see iegbe_phy_m88_get_info + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- /* The downshift status is checked only once, after link is +- * established and it stored in the hw->speed_downgraded parameter.*/ ++ /* The downshift status is checked only once, after link is ++ * established and it stored in the hw->speed_downgraded parameter.*/ + phy_info->downshift = (iegbe_downshift)hw->speed_downgraded; +- +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_CTRL\n"); + return ret_val; + } + +- phy_info->extended_10bt_distance = +- (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) ++ phy_info->extended_10bt_distance = ++ (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) + >> M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT; + phy_info->polarity_correction = +- (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) ++ (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) + >> M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; + + /* Check polarity status */ +@@ -1747,11 +1563,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + + phy_info->cable_polarity = polarity; + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { +- DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); +- return ret_val; ++ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); ++ return ret_val; + } + + phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) +@@ -1761,24 +1577,24 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + /* Cable Length Estimation and Local/Remote Receiver Information + * are only valid at 1000 Mbps. + */ +- phy_info->cable_length = ++ phy_info->cable_length = + (phy_data & M88E1000_PSSR_CABLE_LENGTH) + >> M88E1000_PSSR_CABLE_LENGTH_SHIFT; + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_1000T_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_1000T_STATUS, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register PHY_1000T_STATUS\n"); + return ret_val; + } + +- phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) ++ phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) + >> SR_1000T_LOCAL_RX_STATUS_SHIFT; +- +- phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) ++ ++ phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) + >> SR_1000T_REMOTE_RX_STATUS_SHIFT; + } +- ++ + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -1801,7 +1617,7 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + * This function will perform a software initiated reset of + * the PHY + **/ +-int32_t ++int32_t + iegbe_oem_phy_hw_reset(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -1815,18 +1631,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw * + return -1; + } + /* +- * This code pretty much copies the default case from ++ * This code pretty much copies the default case from + * iegbe_phy_reset() as that is what is appropriate for +- * the M88 used in truxton. ++ * the M88 used in truxton. + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register PHY_CTRL\n"); +@@ -1864,7 +1675,7 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw * + * to perform and post reset initialiation. Not all PHYs require + * this, which is why it was split off as a seperate function. + **/ +-void ++void + iegbe_oem_phy_init_script(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -1877,19 +1688,17 @@ iegbe_oem_phy_init_script(struct iegbe_h + + /* call the GCU func that can do any phy specific init + * functions after a reset +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton + * +- * The closest thing is in iegbe_phy_init_script, however this is ++ * The closest thing is in iegbe_phy_init_script, however this is + * for the IGP style of phy. This is probably a no-op for truxton + * but may be needed by OEM's later on +- * ++ * + */ + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + DEBUGOUT("Nothing to do for OEM PHY Init"); + break; + default: +@@ -1926,13 +1735,8 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + return -1; + } + +- if (hw->phy_id == BCM5395S_PHY_ID) { +- DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n"); +- return -1; +- } +- + /* call the GCU func that will read the phy +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton. + * + * The closest thing is in iegbe_read_phy_reg_ex. +@@ -1940,7 +1744,7 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + * NOTE: this is 1 (of 2) functions that is truly dependant on the + * gcu module + */ +- ++ + ret_val = gcu_read_eth_phy(iegbe_oem_get_phy_dev_number(hw), + reg_addr, phy_data); + if(ret_val) { +@@ -1962,10 +1766,10 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + * + * Returns E1000_SUCCESS, negative E1000 error code on failure + * +- * This is called from iegbe_config_mac_to_phy. Various supported ++ * This is called from iegbe_config_mac_to_phy. Various supported + * Phys may require the RGMII/RMII Translation gasket be set to RMII. + **/ +-int32_t ++int32_t + iegbe_oem_set_trans_gasket(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -1978,17 +1782,12 @@ iegbe_oem_set_trans_gasket(struct iegbe_ + } + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* Gasket set correctly for Marvell Phys, so nothing to do */ + break; + /* Add your PHY_ID here if your device requires an RMII interface +- case YOUR_PHY_ID: ++ case YOUR_PHY_ID: + ctrl_aux_reg = E1000_READ_REG(hw, CTRL_AUX); + ctrl_aux_reg |= E1000_CTRL_AUX_ICP_xxxx_MII_TGS; // Set the RGMII_RMII bit + */ +@@ -2032,7 +1831,7 @@ iegbe_oem_write_phy_reg_ex(struct iegbe_ + return -1; + } + /* call the GCU func that will write to the phy +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton. + * + * The closest thing is in iegbe_write_phy_reg_ex +@@ -2062,11 +1861,11 @@ iegbe_oem_write_phy_reg_ex(struct iegbe_ + * @hw struct iegbe_hw hardware specific data + * + * iegbe_reset_hw is called to reset the MAC. If, for +- * some reason the PHY needs to be reset as well, this ++ * some reason the PHY needs to be reset as well, this + * should return TRUE and then iegbe_oem_phy_hw_reset() + * will be called. + **/ +-int ++int + iegbe_oem_phy_needs_reset_with_mac(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -2079,16 +1878,14 @@ iegbe_oem_phy_needs_reset_with_mac(struc + return FALSE; + } + +- /* ++ /* + * From the original iegbe driver, the M88 +- * PHYs did not seem to need this reset, ++ * PHYs did not seem to need this reset, + * so returning FALSE. + */ + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + ret_val = FALSE; + break; + default: +@@ -2116,7 +1913,7 @@ iegbe_oem_phy_needs_reset_with_mac(struc + * tweaking of the PHY, for PHYs that support a DSP. + * + **/ +-int32_t ++int32_t + iegbe_oem_config_dsp_after_link_change(struct iegbe_hw *hw, + int link_up) + { +@@ -2138,8 +1935,6 @@ iegbe_oem_config_dsp_after_link_change(s + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + DEBUGOUT("No DSP to configure on OEM PHY"); + break; + default: +@@ -2165,7 +1960,7 @@ iegbe_oem_config_dsp_after_link_change(s + * + * + **/ +-int32_t ++int32_t + iegbe_oem_get_cable_length(struct iegbe_hw *hw, + uint16_t *min_length, + uint16_t *max_length) +@@ -2177,21 +1972,15 @@ iegbe_oem_get_cable_length(struct iegbe_ + uint16_t phy_data; + + DEBUGFUNC1("%s",__func__); +- ++ + if(!hw || !min_length || !max_length) { + return -1; + } + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- *min_length = 0; +- *max_length = iegbe_igp_cable_length_150; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, + M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { +@@ -2246,13 +2035,13 @@ iegbe_oem_get_cable_length(struct iegbe_ + /** + * iegbe_oem_phy_is_link_up + * @hw iegbe_hw struct containing device specific information +- * @isUp a boolean returning true if link is up ++ * @isUp a boolean returning true if link is up + * + * This is called as part of iegbe_config_mac_to_phy() to align + * the MAC with the PHY. It turns out on ICP_XXXX, this is not + * done automagically. + **/ +-int32_t ++int32_t + iegbe_oem_phy_is_link_up(struct iegbe_hw *hw, int *isUp) + { + #ifdef EXTERNAL_MDIO +@@ -2266,35 +2055,19 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + if(!hw || !isUp) { + return -1; + } +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton + * see iegbe_config_mac_to_phy + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Link always up */ +- *isUp = TRUE; +- return E1000_SUCCESS; +- break; +- +- case BCM5481_PHY_ID: +- iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); +- ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); +- if(ret_val) +- { +- DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n"); +- return ret_val; +- } +- statusMask = BCM5481_ESTAT_LINK; +- break; +- +- case M88E1000_I_PHY_ID: ++ case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ &phy_data); + statusMask = M88E1000_PSSR_LINK; +- break; ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -2319,213 +2092,3 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + #endif /* ifdef EXTERNAL_MDIO */ + } + +- +- +-//----- +-// Read BCM5481 expansion register +-// +-int32_t +-bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data) +-{ +- int ret; +- uint16_t selector; +- uint16_t reg_data; +- +- // Get the current value of bits 15:12 +- ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector); +- if (ret) +- return ret; +- +- // Select the expansion register +- selector &= 0xf000; +- selector |= (0xf << 8) | (reg); +- iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); +- +- // Read the expansion register +- ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, ®_data); +- +- // De-select the expansion registers. +- selector &= 0xf000; +- iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); +- +- if (ret) +- return ret; +- +- *data = reg_data; +- return ret; +-} +- +-//----- +-// Read reg 0x18 sub-register +-// +-static int32_t +-bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data) +-{ +- int ret; +- uint16_t tmp_data; +- +- // Select reg 0x18, sv +- tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL; +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data); +- if(ret) +- return ret; +- +- // Read reg 0x18, sv +- ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data); +- if(ret) +- return ret; +- +- *data = tmp_data; +- return ret; +-} +- +-//----- +-// Read reg 0x1C sub-register +-// +-int32_t +-bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data) +-{ +- int ret; +- uint16_t tmp_data; +- +- // Select reg 0x1c, sv +- tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data); +- if(ret) +- return ret; +- +- // Read reg 0x1c, sv +- ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data); +- if(ret) +- return ret; +- +- *data = tmp_data; +- return ret; +-} +- +-//----- +-// Read-modify-write a 0x1C register. +-// +-// hw - hardware access info. +-// reg - 0x1C register to modify. +-// data - bits which should be set. +-// mask - the '1' bits in this argument will be cleared in the data +-// read from 'reg' then 'data' will be or'd in and the result +-// will be written to 'reg'. +- +-int32_t +-bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask) +-{ +- int32_t ret; +- uint16_t reg_data; +- +- ret = 0; +- +- ret = bcm5481_read_1csv (hw, reg, ®_data); +- if (ret) +- { +- DEBUGOUT("Unable to read BCM5481 1CH register\n"); +- printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg); +- return ret; +- } +- +- reg_data &= ~mask; +- reg_data |= (BCM5481_R1CH_WE | data); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481 1CH register\n"); +- printk (KERN_ERR "Unable to write BCM5481 1CH register\n"); +- return ret; +- } +- +- return ret; +-} +- +-int32_t +-oi_phy_setup (struct iegbe_hw *hw) +-{ +- int ret; +- uint16_t pmii_data; +- uint16_t mctrl_data; +- uint16_t cacr_data; +- uint16_t sc1_data; +- uint16_t lctl_data; +- +- ret = 0; +- +- // Set low power mode via reg 0x18, sv010, bit 6 +- // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits. +- ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data); +- if (ret) +- { +- DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n"); +- printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n"); +- return ret; +- } +- +- // Set the LPM bit in the data just read and write back to sv010 +- // The shadow register select bits [2:0] are set by reading the sv010 +- // register. +- pmii_data |= BCM5481_R18H_SV010_LPM; +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481_R18H register\n"); +- printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); +- return ret; +- } +- +- +- // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111 +- +- if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data)) +- { +- DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n"); +- printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n"); +- return ret; +- } +- mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481_R18H register\n"); +- printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); +- return ret; +- } +- +- +- // Enable RGMII transmit clock delay in reg 0x1c, sv00011 +- ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data); +- if (ret) +- { +- DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n"); +- printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n"); +- return ret; +- } +- +- cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481_R1CH register\n"); +- printk (KERN_ERR "Unable to write BCM5481_R1CH register\n"); +- return ret; +- } +- +- // Enable dual link speed indication (0x1c, sv 00010, bit 2) +- ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK); +- if (ret) +- return ret; +- +- // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0) +- ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN); +- if (ret) +- return ret; +- +- return ret; +-} +--- a/Embedded/src/GbE/iegbe_oem_phy.h ++++ b/Embedded/src/GbE/iegbe_oem_phy.h +@@ -2,31 +2,31 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + +- This program is free software; you can redistribute it and/or modify ++ This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + +- This program is distributed in the hope that it will be useful, but +- WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ This program is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + +- You should have received a copy of the GNU General Public License +- along with this program; if not, write to the Free Software ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- The full GNU General Public License is included in this distribution ++ The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: +- +- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 ++ ++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 + + *******************************************************************************/ + #ifndef _IEGBE_OEM_PHY_H_ +@@ -45,10 +45,10 @@ int32_t iegbe_oem_set_trans_gasket(struc + uint32_t iegbe_oem_get_tipg(struct iegbe_hw *hw); + int iegbe_oem_phy_is_copper(struct iegbe_hw *hw); + uint32_t iegbe_oem_get_phy_dev_number(struct iegbe_hw *hw); +-int iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags, ++int iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags, + struct ifreq *ifr, int cmd); + void iegbe_oem_fiber_live_in_suspend(struct iegbe_hw *hw); +-void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, ++void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, + uint32_t data_length); + int iegbe_oem_phy_loopback(struct iegbe_adapter *adapter); + void iegbe_oem_loopback_cleanup(struct iegbe_adapter *adapter); +@@ -94,81 +94,14 @@ int32_t iegbe_oem_phy_is_link_up(struct + #define ICP_XXXX_MAC_2 2 + + #define DEFAULT_ICP_XXXX_TIPG_IPGT 8 /* Inter Packet Gap Transmit Time */ +-#define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL +-#define BCM5481_PHY_ID 0x0143BCA2 +-#define BCM5395S_PHY_ID 0x0143BCF0 ++#define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL + + /* Miscellaneous defines */ + #ifdef IEGBE_10_100_ONLY +- #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x0F ++ #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x0F + #else + #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x2F + #endif + +-//----- +-// BCM5481 specifics +- +-#define BCM5481_ECTRL (0x10) +-#define BCM5481_ESTAT (0x11) +-#define BCM5481_RXERR (0x12) +-#define BCM5481_EXPRW (0x15) +-#define BCM5481_EXPACC (0x17) +-#define BCM5481_ASTAT (0x19) +-#define BCM5481_R18H (0x18) +-#define BCM5481_R1CH (0x1c) +- +-//----- +-// indirect register access via register 18h +- +-#define BCM5481_R18H_SV_MASK (7) // Mask for SV bits. +-#define BCM5481_R18H_SV_ACTRL (0) // SV000 Aux. control +-#define BCM5481_R18H_SV_10BT (1) // SV001 10Base-T +-#define BCM5481_R18H_SV_PMII (2) // SV010 Power/MII control +-#define BCM5481_R18H_SV_MTEST (4) // SV100 Misc. test +-#define BCM5481_R18H_SV_MCTRL (7) // SV111 Misc. control +- +-#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity +-#define BCM5481_R18H_SV010_LPM (1 << 6) +-#define BCM5481_R18H_SV111_SKEW (1 << 8) +-#define BCM5481_R18H_WE (1 << 15) // Write enable +- +-// 0x1c registers +-#define BCM5481_R1CH_SV_SHIFT (10) +-#define BCM5481_R1CH_SV_MASK (0x1f) +-#define BCM5481_R1CH_SC1 (0x02) // sv00010 Spare control 1 +-#define BCM5481_R1CH_CACR (0x03) // sv00011 Clock alignment control +-#define BCM5481_R1CH_LCTRL (0x09) // sv01001 LED control +-#define BCM5481_R1CH_LEDS1 (0x0d) // sv01101 LED selector 1 +- +-// 0x1c common +-#define BCM5481_R1CH_WE (1 << 15) // Write enable +- +-// 0x1c, sv 00010 +-#define BCM5481_R1CH_SC1_LINK (1 << 2) // sv00010 Linkspeed +- +-// 0x1c, sv 00011 +-#define BCM5481_R1CH_CACR_TCD (1 << 9) // sv00011 RGMII tx clock delay +- +-// 0x1c, sv 01001 +-#define BCM5481_R1CH_LCTRL_ALEN (1 << 4) // Activity/Link enable on ACTIVITY LED +-#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED +- +- +-#define BCM5481_ECTRL_DISMDIX (1 <<14) +- +-#define BCM5481_MCTRL_AUTOMDIX (1 <<9) +- +-#define BCM5481_ESTAT_LINK (1 << 8) +- +-#define BCM5481_ASTAT_ANC (1 << 15) +-#define BCM5481_ASTAT_ANHCD (7 << 8) +-#define BCM5481_ASTAT_HCD(x) ((x >> 8) & 7) +-#define BCM5481_ASTAT_1KBTFD (0x7) +-#define BCM5481_ASTAT_1KBTHD (0x6) +-#define BCM5481_ASTAT_100BTXFD (0x5) +-#define BCM5481_ASTAT_100BTXHD (0x3) +- +-// end BCM5481 specifics +- + #endif /* ifndef _IEGBE_OEM_PHY_H_ */ +- ++ +--- a/Embedded/src/GbE/iegbe_osdep.h ++++ b/Embedded/src/GbE/iegbe_osdep.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/iegbe_param.c ++++ b/Embedded/src/GbE/iegbe_param.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -239,11 +239,7 @@ E1000_PARAM(InterruptThrottleRate, "Inte + #define MAX_TXABSDELAY 0xFFFF + #define MIN_TXABSDELAY 0 + +-#ifdef IEGBE_GBE_WORKAROUND +-#define DEFAULT_ITR 0 +-#else + #define DEFAULT_ITR 8000 +-#endif + + + #define MAX_ITR 100000 +@@ -373,7 +369,7 @@ iegbe_check_options(struct iegbe_adapter + tx_ring->count = opt.def; + } + #endif +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_tx_queues; i++) + tx_ring[i].count = tx_ring->count; + } + { /* Receive Descriptor Count */ +@@ -403,7 +399,7 @@ iegbe_check_options(struct iegbe_adapter + rx_ring->count = opt.def; + } + #endif +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_rx_queues; i++) + rx_ring[i].count = rx_ring->count; + } + { /* Checksum Offload Enable/Disable */ +--- a/Embedded/src/GbE/kcompat.c ++++ b/Embedded/src/GbE/kcompat.c +@@ -1,8 +1,8 @@ +-/************************************************************ +- ++/************************************************************ ++ + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,183 +22,192 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 +- +- Contact Information: +- +- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 +- +-**************************************************************/ +-/************************************************************************** +- * @ingroup KCOMPAT_GENERAL +- * +- * @file kcompat.c +- * +- * @description +- * +- * +- **************************************************************************/ +-#include "kcompat.h" +- +-/*************************************************************/ +-/* 2.4.13 => 2.4.3 */ +-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0xd) ) +- +-/**************************************/ +-/* PCI DMA MAPPING */ +- +-#if defined(CONFIG_HIGHMEM) +- +-#ifndef PCI_DRAM_OFFSET +-#define PCI_DRAM_OFFSET 0 +-#endif +- +-u64 _kc_pci_map_page(struct pci_dev *dev, +- struct page *page, +- unsigned long offset, +- size_t size, +- int direction) +-{ +- u64 ret_val; +- ret_val = (((u64)(page - mem_map) << PAGE_SHIFT) + offset + +- PCI_DRAM_OFFSET); +- return ret_val; +-} +- +-#else /* CONFIG_HIGHMEM */ +- +-u64 _kc_pci_map_page(struct pci_dev *dev, +- struct page *page, +- unsigned long offset, +- size_t size, +- int direction) +-{ +- return pci_map_single(dev, (void *)page_address(page) + offset, +- size, direction); +-} +- +-#endif /* CONFIG_HIGHMEM */ +- +-void _kc_pci_unmap_page(struct pci_dev *dev, +- u64 dma_addr, +- size_t size, +- int direction) +-{ +- return pci_unmap_single(dev, dma_addr, size, direction); +-} +- +-#endif /* 2.4.13 => 2.4.3 */ +- +- +-/*****************************************************************************/ +-/* 2.4.3 => 2.4.0 */ +-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x3) ) +- +-/**************************************/ +-/* PCI DRIVER API */ +- +-int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) +-{ +- if(!pci_dma_supported(dev, mask)) { +- return -EIO; +- } +- dev->dma_mask = mask; +- return 0; +-} +- +-int _kc_pci_request_regions(struct pci_dev *dev, char *res_name) +-{ +- int i; +- +- for (i = 0; i < 0x6; i++) { +- if (pci_resource_len(dev, i) == 0) { +- continue; +- } +- if (pci_resource_flags(dev, i) & IORESOURCE_IO) { +- if (!request_region(pci_resource_start(dev, i), +- pci_resource_len(dev, i), res_name)) { +- pci_release_regions(dev); +- return -EBUSY; +- } +- } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { +- if (!request_mem_region(pci_resource_start(dev, i), +- pci_resource_len(dev, i), +- res_name)) { +- pci_release_regions(dev); +- return -EBUSY; +- } +- } +- } +- return 0; +-} +- +-void _kc_pci_release_regions(struct pci_dev *dev) +-{ +- int i; +- +- for (i = 0; i < 0x6; i++) { +- if (pci_resource_len(dev, i) == 0) { +- continue; +- } +- if (pci_resource_flags(dev, i) & IORESOURCE_IO){ +- release_region(pci_resource_start(dev, i), +- pci_resource_len(dev, i)); +- } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { +- release_mem_region(pci_resource_start(dev, i), +- pci_resource_len(dev, i)); +- } +- } +-} +- +-/**************************************/ +-/* NETWORK DRIVER API */ +- +-struct net_device * _kc_alloc_etherdev(int sizeof_priv) +-{ +- struct net_device *dev; +- int alloc_size; +- +- alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 0x1f; +- +- dev = kmalloc(alloc_size, GFP_KERNEL); +- +- if (!dev) { return NULL; } +- +- memset(dev, 0, alloc_size); +- +- if (sizeof_priv) { +- dev->priv = (void *) (((unsigned long)(dev + 1) + 0x1f) & ~0x1f); +- } +- dev->name[0] = '\0'; +- +- ether_setup(dev); +- +- return dev; +-} +- +-int _kc_is_valid_ether_addr(u8 *addr) +-{ +- const char zaddr[0x6] = {0,}; +- +- return !(addr[0]&1) && memcmp( addr, zaddr, 0x6); +-} +- +-#endif /* 2.4.3 => 2.4.0 */ +- +- +-/*****************************************************************/ +-/* 2.4.6 => 2.4.3 */ +-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x6) ) +- +-int _kc_pci_set_power_state(struct pci_dev *dev, int state) +-{ return 0; } +-int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer) +-{ return 0; } +-int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer) +-{ return 0; } +-int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) +-{ return 0; } +- +-#endif /* 2.4.6 => 2.4.3 */ +- +- ++ version: Embedded.Release.Patch.L.1.0.7-5 ++ ++ Contact Information: ++ ++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 ++ ++**************************************************************/ ++/************************************************************************** ++ * @ingroup KCOMPAT_GENERAL ++ * ++ * @file kcompat.c ++ * ++ * @description ++ * ++ * ++ **************************************************************************/ ++#include "kcompat.h" ++ ++/*************************************************************/ ++/* 2.4.13 => 2.4.3 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0xd) ) ++ ++/**************************************/ ++/* PCI DMA MAPPING */ ++ ++#if defined(CONFIG_HIGHMEM) ++ ++#ifndef PCI_DRAM_OFFSET ++#define PCI_DRAM_OFFSET 0 ++#endif ++ ++u64 _kc_pci_map_page(struct pci_dev *dev, ++ struct page *page, ++ unsigned long offset, ++ size_t size, ++ int direction) ++{ ++ u64 ret_val; ++ ret_val = (((u64)(page - mem_map) << PAGE_SHIFT) + offset + ++ PCI_DRAM_OFFSET); ++ return ret_val; ++} ++ ++#else /* CONFIG_HIGHMEM */ ++ ++u64 _kc_pci_map_page(struct pci_dev *dev, ++ struct page *page, ++ unsigned long offset, ++ size_t size, ++ int direction) ++{ ++ return pci_map_single(dev, (void *)page_address(page) + offset, ++ size, direction); ++} ++ ++#endif /* CONFIG_HIGHMEM */ ++ ++void _kc_pci_unmap_page(struct pci_dev *dev, ++ u64 dma_addr, ++ size_t size, ++ int direction) ++{ ++ return pci_unmap_single(dev, dma_addr, size, direction); ++} ++ ++#endif /* 2.4.13 => 2.4.3 */ ++ ++ ++/*****************************************************************************/ ++/* 2.4.3 => 2.4.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x3) ) ++ ++/**************************************/ ++/* PCI DRIVER API */ ++ ++int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) ++{ ++ if(!pci_dma_supported(dev, mask)) { ++ return -EIO; ++ } ++ dev->dma_mask = mask; ++ return 0; ++} ++ ++int _kc_pci_request_regions(struct pci_dev *dev, char *res_name) ++{ ++ int i; ++ ++ for (i = 0; i < 0x6; i++) { ++ if (pci_resource_len(dev, i) == 0) { ++ continue; ++ } ++ if (pci_resource_flags(dev, i) & IORESOURCE_IO) { ++ if (!request_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i), res_name)) { ++ pci_release_regions(dev); ++ return -EBUSY; ++ } ++ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { ++ if (!request_mem_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i), ++ res_name)) { ++ pci_release_regions(dev); ++ return -EBUSY; ++ } ++ } ++ } ++ return 0; ++} ++ ++void _kc_pci_release_regions(struct pci_dev *dev) ++{ ++ int i; ++ ++ for (i = 0; i < 0x6; i++) { ++ if (pci_resource_len(dev, i) == 0) { ++ continue; ++ } ++ if (pci_resource_flags(dev, i) & IORESOURCE_IO){ ++ release_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i)); ++ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { ++ release_mem_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i)); ++ } ++ } ++} ++ ++/**************************************/ ++/* NETWORK DRIVER API */ ++ ++struct net_device * _kc_alloc_etherdev(int sizeof_priv) ++{ ++ struct net_device *dev; ++ int alloc_size; ++ ++ alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 0x1f; ++ ++ dev = kmalloc(alloc_size, GFP_KERNEL); ++ ++ if (!dev) { return NULL; } ++ ++ memset(dev, 0, alloc_size); ++ ++ if (sizeof_priv) { ++ dev->priv = (void *) (((unsigned long)(dev + 1) + 0x1f) & ~0x1f); ++ } ++ dev->name[0] = '\0'; ++ ++ ether_setup(dev); ++ ++ return dev; ++} ++ ++int _kc_is_valid_ether_addr(u8 *addr) ++{ ++ const char zaddr[0x6] = {0,}; ++ ++ return !(addr[0]&1) && memcmp( addr, zaddr, 0x6); ++} ++ ++#endif /* 2.4.3 => 2.4.0 */ ++ ++ ++/*****************************************************************/ ++/* 2.4.6 => 2.4.3 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x6) ) ++ ++int _kc_pci_set_power_state(struct pci_dev *dev, int state) ++{ return 0; } ++int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer) ++{ return 0; } ++int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer) ++{ return 0; } ++int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) ++{ return 0; } ++ ++#endif /* 2.4.6 => 2.4.3 */ ++ ++ ++ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,24) ) ++ ++void dump_stack(void) ++{ ++} ++ ++#endif /* 2.4.24 */ ++ +--- a/Embedded/src/GbE/kcompat_ethtool.c ++++ b/Embedded/src/GbE/kcompat_ethtool.c +@@ -2,7 +2,7 @@ + /* + * GPL LICENSE SUMMARY + * +- * Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ + * Contact Information: + * Intel Corporation + * +- * version: Embedded.L.1.0.34 ++ * version: Embedded.Release.Patch.L.1.0.7-5 + */ + + /************************************************************************** +@@ -779,6 +779,7 @@ static int ethtool_get_stats(struct net_ + } + + /* The main entry point in this file. Called from net/core/dev.c */ ++ + #define ETHTOOL_OPS_COMPAT + int ethtool_ioctl(struct ifreq *ifr) + { +--- a/Embedded/src/GbE/kcompat.h ++++ b/Embedded/src/GbE/kcompat.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -69,15 +69,6 @@ GPL LICENSE SUMMARY + #define CONFIG_NET_POLL_CONTROLLER + #endif + +-#ifdef E1000_NAPI +-#undef CONFIG_E1000_NAPI +-#define CONFIG_E1000_NAPI +-#endif +- +-#ifdef E1000_NO_NAPI +-#undef CONFIG_E1000_NAPI +-#endif +- + #ifndef module_param + #define module_param(v,t,p) MODULE_PARM(v, "i"); + #endif +@@ -554,35 +545,14 @@ extern void _kc_pci_unmap_page(struct pc + #endif + + /*****************************************************************************/ +-/* 2.4.23 => 2.4.22 */ +-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) +-#ifdef CONFIG_E1000_NAPI +-#ifndef netif_poll_disable +-#define netif_poll_disable(x) _kc_netif_poll_disable(x) +-static inline void _kc_netif_poll_disable(struct net_device *netdev) +-{ +- while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) { +- /* No hurry */ +- current->state = TASK_INTERRUPTIBLE; +- schedule_timeout(1); +- } +-} +-#endif +-#ifndef netif_poll_enable +-#define netif_poll_enable(x) _kc_netif_poll_enable(x) +-static inline void _kc_netif_poll_enable(struct net_device *netdev) +-{ +- clear_bit(__LINK_STATE_RX_SCHED, &netdev->state); +-} +-#endif +-#endif +-#endif +- +-/*****************************************************************************/ + /* 2.5.28 => 2.4.23 */ + #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) + ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) ++static inline void _kc_synchronize_irq(void) { barrier(); } ++#else + static inline void _kc_synchronize_irq() { synchronize_irq(); } ++#endif /* 2.4.23 */ + #undef synchronize_irq + #define synchronize_irq(X) _kc_synchronize_irq() + +@@ -747,6 +717,37 @@ static inline struct mii_ioctl_data *_kc + #define skb_header_cloned(x) 0 + #endif /* SKB_DATAREF_SHIFT not defined */ + ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ++ ++#define ioread32(addr) readl(addr) ++#define iowrite32(val,addr) writel(val,addr) ++ ++#endif /* 2.6.10 */ ++ ++#ifndef DEFINE_SPINLOCK ++#define DEFINE_SPINLOCK(s) spinlock_t s = SPIN_LOCK_UNLOCKED ++#endif /* DEFINE_SPINLOCK */ ++ ++#ifndef PCI_COMMAND_INTX_DISABLE ++#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ ++#endif /* PCI_COMMAND_INTX_DISABLE */ ++ ++#ifndef ETH_GSTRING_LEN ++#define ETH_GSTRING_LEN 32 ++#endif /* ETH_GSTRING_LEN */ ++ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,24) ) ++ ++extern void dump_stack(void); ++ ++#undef register_reboot_notifier ++#define register_reboot_notifier(a) ++ ++#undef unregister_reboot_notifier ++#define unregister_reboot_notifier(a) ++ ++#endif /* 2.4.24 */ ++ + #endif /* _KCOMPAT_H_ */ + + +--- a/Embedded/src/GbE/Makefile ++++ b/Embedded/src/GbE/Makefile +@@ -1,6 +1,6 @@ + # GPL LICENSE SUMMARY + # +-# Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++# Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of version 2 of the GNU General Public License as +@@ -20,7 +20,7 @@ + # Contact Information: + # Intel Corporation + # +-# version: Embedded.L.1.0.34 ++# version: Embedded.Release.Patch.L.1.0.7-5 + + ########################################################################### + # Driver files +@@ -35,6 +35,8 @@ MDIO_PHONY_CFILES = gcu.c + MDIO_CFILES = gcu_main.c gcu_if.c + MDIO_HFILES = gcu.h gcu_if.h gcu_reg.h kcompat.h + ++KVER=$(shell uname -r) ++ + # + # Variables: + # KSRC (path to kernel source to build against) +@@ -50,45 +52,16 @@ MDIO_HFILES = gcu.h gcu_if.h gcu_reg.h k + + # set KSRC, KOBJ, and EXTERNAL_MDIO to default values of not already set + # +-KOBJ ?= /usr/src/kernels/linux +-KSRC ?= /usr/src/kernels/linux ++#KOBJ=/usr/src/kernels/linux ++#KSRC=/usr/src/kernels/linux ++#KSRC=$(KOBJ) + EXTERNAL_MDIO ?= 1 + GBE_NAME = iegbe + GCU_NAME = gcu + +-# By default the workaround for the IEGBE writeback issue is enabled +-# +-IEGBE_GBE_WORKAROUND ?= 0 +- +-# If the platform only supports 10/100 this variable needs to be set +-# so the default advertisement is set appropriately. +-# By default, this variable will be disabled. +-# +-IEGBE_10_100_ONLY ?= 0 +- +-# check for version.h and autoconf.h for running kernel in /boot (SUSE) +-ifneq (,$(wildcard /boot/vmlinuz.version.h)) +- VERSION_FILE := /boot/vmlinuz.version.h +- CONFIG_FILE := /boot/vmlinuz.autoconf.h +- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | \ +- grep UTS_RELEASE | awk '{ print $$3 }' | sed 's/\"//g') +- ifeq ($(KVER),$(shell uname -r)) +- # set up include path to override headers from kernel source +- x:=$(shell rm -rf include) +- x:=$(shell mkdir -p include/linux) +- x:=$(shell cp /boot/vmlinuz.version.h include/linux/version.h) +- x:=$(shell cp /boot/vmlinuz.autoconf.h include/linux/autoconf.h) +- CFLAGS += -I./include +- else +- VERSION_FILE := $(KOBJ)/include/linux/version.h +- UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +- CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h +- endif +-else +- VERSION_FILE := $(KOBJ)/include/linux/version.h +- UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +- CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h +-endif ++VERSION_FILE := $(KSRC)/include/linux/version.h ++UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h ++CONFIG_FILE := $(KSRC)/include/linux/autoconf.h + + ifeq (,$(wildcard $(VERSION_FILE))) + $(error Linux kernel source not configured - missing version.h) +@@ -98,83 +71,8 @@ ifeq (,$(wildcard $(CONFIG_FILE))) + $(error Linux kernel source not configured - missing autoconf.h) + endif + +-# as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h +-# so check that file for kernel version string instead of version.h +-USE_UTS_REL := $(shell [ -f $(UTS_REL_FILE) ] && echo "1") +- +-# pick a compiler +-ifneq (,$(findstring egcs-2.91.66, $(shell cat /proc/version))) +- CC := kgcc gcc cc +-else +- CC := gcc cc +-endif +-test_cc = $(shell $(cc) --version > /dev/null 2>&1 && echo $(cc)) +-CC := $(foreach cc, $(CC), $(test_cc)) +-CC := $(firstword $(CC)) +-ifeq (,$(CC)) +- $(error Compiler not found) +-endif +- +-# we need to know what platform the driver is being built on +-# some additional features are only built on Intel platforms +-ARCH := $(shell uname -m | sed 's/i.86/i386/') +-ifeq ($(ARCH),alpha) +- CFLAGS += -ffixed-8 -mno-fp-regs +-endif +-ifeq ($(ARCH),x86_64) +- CFLAGS += -mcmodel=kernel -mno-red-zone +-endif +-ifeq ($(ARCH),ppc) +- CFLAGS += -msoft-float +-endif +-ifeq ($(ARCH),ppc64) +- CFLAGS += -m64 -msoft-float +- LDFLAGS += -melf64ppc +-endif +- +-# standard flags for module builds +-CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall +-CFLAGS += -I$(KSRC)/include -I. +-CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \ +- echo "-DMODVERSIONS -DEXPORT_SYMTAB \ +- -include $(KSRC)/include/linux/modversions.h") +- +-ifeq ($(IEGBE_GBE_WORKAROUND), 1) +-CFLAGS += -DIEGBE_GBE_WORKAROUND -DE1000_NO_NAPI +-endif +- +-ifeq ($(IEGBE_10_100_ONLY), 1) +-CFLAGS += -DIEGBE_10_100_ONLY +-endif +- +-CFLAGS += $(CFLAGS_EXTRA) +-#ifeq (,$(shell echo $(CFLAGS_EXTRA) | grep NAPI)) +-#CFLAGS += -DE1000_NO_NAPI +-#CFLAGS_EXTRA += -DE1000_NO_NAPI +-#endif +- +-RHC := $(KSRC)/include/linux/rhconfig.h +-ifneq (,$(wildcard $(RHC))) +- # 7.3 typo in rhconfig.h +- ifneq (,$(shell $(CC) $(CFLAGS) -E -dM $(RHC) | grep __module__bigmem)) +- CFLAGS += -D__module_bigmem +- endif +-endif +- +-# get the kernel version - we use this to find the correct install path +-ifeq ($(USE_UTS_REL), 1) +- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(UTS_REL_FILE) | grep UTS_RELEASE | \ +- awk '{ print $$3 }' | sed 's/\"//g') +-else +- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | grep UTS_RELEASE | \ +- awk '{ print $$3 }' | sed 's/\"//g') +-endif +- +-KKVER := $(shell echo $(KVER) | \ +- awk '{ if ($$0 ~ /2\.[6-9]\./) print "1"; else print "0"}') +-ifeq ($(KKVER), 0) +- $(error *** Aborting the build. \ +- *** This driver is not supported on kernel versions older than 2.6.18) ++ifeq (,$(wildcard $(UTS_REL_FILE))) ++ $(error Linux kernel source not configured - missing utsrelease.h) + endif + + # set the install path +@@ -202,11 +100,11 @@ ifneq ($(SMP),$(shell uname -a | grep SM + endif + + ifeq ($(SMP),1) +- CFLAGS += -D__SMP__ ++ EXTRA_CFLAGS += -D__SMP__ + endif + + ifeq ($(EXTERNAL_MDIO), 1) +- CFLAGS += -DEXTERNAL_MDIO ++ EXTRA_CFLAGS += -DEXTERNAL_MDIO + endif + + ########################################################################### +@@ -223,7 +121,6 @@ MANSECTION = 7 + MANFILE = $(TARGET:.ko=.$(MANSECTION)) + + ifneq ($(PATCHLEVEL),) +- EXTRA_CFLAGS += $(CFLAGS_EXTRA) + obj-m += $(TARGET:.ko=.o) + iegbe-objs := $(CFILES:.c=.o) + ifeq ($(EXTERNAL_MDIO),1) +--- a/filelist ++++ b/filelist +@@ -1,41 +1,3 @@ +-Embedded/Makefile +-Embedded/environment.mk +-Embedded/src/1588/1588.c +-Embedded/src/1588/1588.h +-Embedded/src/1588/IxTimeSyncAcc_p.h +-Embedded/src/1588/Makefile +-Embedded/src/1588/ixtimesyncacc.c +-Embedded/src/1588/ixtimesyncacc.h +-Embedded/src/1588/linux_ioctls.h +-Embedded/src/CAN/Makefile +-Embedded/src/CAN/can_fifo.c +-Embedded/src/CAN/can_fifo.h +-Embedded/src/CAN/can_ioctl.h +-Embedded/src/CAN/can_main.c +-Embedded/src/CAN/can_main.h +-Embedded/src/CAN/can_port.h +-Embedded/src/CAN/icp_can.c +-Embedded/src/CAN/icp_can.h +-Embedded/src/CAN/icp_can_regs.h +-Embedded/src/CAN/icp_can_types.h +-Embedded/src/CAN/icp_can_user.h +-Embedded/src/EDMA/Makefile +-Embedded/src/EDMA/dma.h +-Embedded/src/EDMA/dma_api.h +-Embedded/src/EDMA/dma_client_api.c +-Embedded/src/EDMA/dma_common.c +-Embedded/src/EDMA/dma_internals.h +-Embedded/src/EDMA/dma_linux.c +-Embedded/src/EDMA/os/os.c +-Embedded/src/EDMA/os/os.h +-Embedded/src/EDMA/os/os_list.c +-Embedded/src/EDMA/os/os_list.h +-Embedded/src/EDMA/os/os_types.h +-Embedded/src/GPIO/Makefile +-Embedded/src/GPIO/common.h +-Embedded/src/GPIO/gpio.h +-Embedded/src/GPIO/gpio_ref.c +-Embedded/src/GPIO/linux_ioctls.h + Embedded/src/GbE/Makefile + Embedded/src/GbE/gcu.h + Embedded/src/GbE/gcu_if.c +@@ -55,16 +17,6 @@ Embedded/src/GbE/iegbe_param.c + Embedded/src/GbE/kcompat.c + Embedded/src/GbE/kcompat.h + Embedded/src/GbE/kcompat_ethtool.c +-Embedded/src/WDT/Makefile +-Embedded/src/WDT/iwdt.c +-Embedded/src/WDT/iwdt.h +-Embedded/src/patches/Intel_EP80579_RHEL5.patch +-Embedded/src/patches/pci.ids_RHEL5.patch + LICENSE.GPL +-build_system/build_files/Core/ia.mk +-build_system/build_files/OS/linux_2.6.mk +-build_system/build_files/OS/linux_2.6_kernel_space_rules.mk +-build_system/build_files/common.mk +-build_system/build_files/rules.mk + filelist + versionfile +--- a/versionfile ++++ b/versionfile +@@ -1,4 +1,4 @@ +-PACKAGE_TYPE=Embedded ++PACKAGE_TYPE=Embedded.Release.Patch + + PACKAGE_OS=L + +@@ -6,4 +6,6 @@ PACKAGE_VERSION_MAJOR_NUMBER=1 + + PACKAGE_VERSION_MINOR_NUMBER=0 + +-PACKAGE_VERSION_PATCH_NUMBER=34 ++PACKAGE_VERSION_PATCH_NUMBER=7 ++ ++PACKAGE_VERSION_BUILD_NUMBER=5 diff --git a/package/ep80579-drivers/patches/002-cflags_cleanup.patch b/package/ep80579-drivers/patches/002-cflags_cleanup.patch new file mode 100644 index 000000000..f89752795 --- /dev/null +++ b/package/ep80579-drivers/patches/002-cflags_cleanup.patch @@ -0,0 +1,22 @@ +--- a/build_system/build_files/common.mk ++++ b/build_system/build_files/common.mk +@@ -122,7 +122,7 @@ CC=$(COMPILER) + LD=$(LINKER) + AR=$(ARCHIVER) + +-CFLAGS+=-O2 ++#CFLAGS+=-O2 + + + PWD= $(shell pwd) +--- a/build_system/build_files/OS/linux_2.6.mk ++++ b/build_system/build_files/OS/linux_2.6.mk +@@ -80,7 +80,7 @@ endif + + + ifeq ($(OS_LEVEL), kernel_space) +-CFLAGS+= ++#CFLAGS+= + endif + + diff --git a/package/ep80579-drivers/patches/003-new_irqf_constants.patch b/package/ep80579-drivers/patches/003-new_irqf_constants.patch new file mode 100644 index 000000000..af231f218 --- /dev/null +++ b/package/ep80579-drivers/patches/003-new_irqf_constants.patch @@ -0,0 +1,53 @@ +--- a/Embedded/src/1588/1588.c ++++ b/Embedded/src/1588/1588.c +@@ -291,7 +291,7 @@ int pci_probe(struct pci_dev *dev, const + + } + +- if ( request_irq(dev->irq, ×ync_isr, SA_SHIRQ, DRIVERNAME, ++ if ( request_irq(dev->irq, ×ync_isr, IRQF_SHARED, DRIVERNAME, + &g_drvr_data) ) + { + printk("%s-pci_probe: irq\n", DRIVERNAME); +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -424,7 +424,7 @@ int can_open(struct inode *inode, struct + err = request_irq( + can_os->irq, + can_irq_handler, +- SA_SHIRQ, ++ IRQF_SHARED, + iminor(can_os->inode) ? CAN_PROC_1 : CAN_PROC_0, + &(g_can_os[iminor(can_os->inode)]) + ); +--- a/Embedded/src/EDMA/dma_linux.c ++++ b/Embedded/src/EDMA/dma_linux.c +@@ -367,7 +367,7 @@ int32_t edma_resume(struct pci_dev *dev) + return -ENODEV; + } + +- if (request_irq(dev->irq, &edma_irq_handler, SA_SHIRQ, ++ if (request_irq(dev->irq, &edma_irq_handler, IRQF_SHARED, + g_char_drvr_name, dev) ) + { + +@@ -829,7 +829,7 @@ int32_t edma_probe(struct pci_dev * dev, + /* + * Obtain a (shared) Interrupt Request (IRQ) Line from the OS. + */ +- if (request_irq(dev->irq, &edma_irq_handler, SA_SHIRQ, ++ if (request_irq(dev->irq, &edma_irq_handler, IRQF_SHARED, + g_char_drvr_name, dev) ) + { + +--- a/Embedded/src/WDT/iwdt.c ++++ b/Embedded/src/WDT/iwdt.c +@@ -1461,7 +1461,7 @@ static int __init wdt_init_one(struct pc + + /* Request irq only if wdt_irq is other than 0 */ + if (wdt_irq) { +- if (request_irq(wdt_irq, wdt_isr, SA_INTERRUPT | SA_SHIRQ, ++ if (request_irq(wdt_irq, wdt_isr, IRQF_DISABLED | IRQF_SHARED, + "iwdt", &wdt_miscdev)) { + printk("IRQ %d is not free.\n", wdt_irq); + return -EIO; diff --git a/package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch b/package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch new file mode 100644 index 000000000..ab23da63f --- /dev/null +++ b/package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch @@ -0,0 +1,56 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -724,6 +724,26 @@ static void iegbe_dump_eeprom(struct ieg + kfree(data); + } + ++static const struct net_device_ops iegbe_netdev_ops = { ++ .ndo_open = iegbe_open, ++ .ndo_stop = iegbe_close, ++ .ndo_start_xmit = iegbe_xmit_frame, ++ .ndo_get_stats = iegbe_get_stats, ++ .ndo_set_rx_mode = iegbe_set_rx_mode, ++ .ndo_set_mac_address = iegbe_set_mac, ++ .ndo_tx_timeout = iegbe_tx_timeout, ++ .ndo_change_mtu = iegbe_change_mtu, ++ .ndo_do_ioctl = iegbe_ioctl, ++ .ndo_validate_addr = eth_validate_addr, ++ ++ .ndo_vlan_rx_register = iegbe_vlan_rx_register, ++ .ndo_vlan_rx_add_vid = iegbe_vlan_rx_add_vid, ++ .ndo_vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = iegbe_netpoll, ++#endif ++}; ++ + /** + * iegbe_probe - Device Initialization Routine + * @pdev: PCI device information struct +@@ -800,24 +820,11 @@ static int __devinit iegbe_probe(struct + if (!hw->hw_addr) + goto err_ioremap; + +- netdev->open = &iegbe_open; +- netdev->stop = &iegbe_close; +- netdev->hard_start_xmit = &iegbe_xmit_frame; +- netdev->get_stats = &iegbe_get_stats; +- netdev->set_rx_mode = &iegbe_set_rx_mode; +- netdev->set_mac_address = &iegbe_set_mac; +- netdev->change_mtu = &iegbe_change_mtu; +- netdev->do_ioctl = &iegbe_ioctl; ++ netdev->netdev_ops = &iegbe_netdev_ops; + set_ethtool_ops(netdev); +- netdev->tx_timeout = &iegbe_tx_timeout; + netdev->watchdog_timeo = 5 * HZ; + netif_napi_add(netdev, &adapter->napi, iegbe_clean, 64); +- netdev->vlan_rx_register = iegbe_vlan_rx_register; +- netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid; +- netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid; +-#ifdef CONFIG_NET_POLL_CONTROLLER +- netdev->poll_controller = iegbe_netpoll; +-#endif ++ + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + + diff --git a/package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch b/package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch new file mode 100644 index 000000000..921d464ba --- /dev/null +++ b/package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch @@ -0,0 +1,41 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -3465,12 +3465,12 @@ static irqreturn_t iegbe_intr_msi(int ir + printk("Critical error! ICR = 0x%x\n", icr); + return IRQ_HANDLED; + } +- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ if (likely(napi_schedule_prep(&adapter->napi))) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; +- __netif_rx_schedule(netdev, &adapter->napi); ++ __napi_schedule(&adapter->napi); + } else + iegbe_irq_enable(adapter); + +@@ -3527,12 +3527,12 @@ iegbe_intr(int irq, void *data) + E1000_WRITE_REG(&adapter->hw, IMC, ~0); + E1000_WRITE_FLUSH(&adapter->hw); + } +- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ if (likely(napi_schedule_prep(&adapter->napi))) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; +- __netif_rx_schedule(netdev, &adapter->napi); ++ __napi_schedule(&adapter->napi); + } else + /* this really should not happen! if it does it is basically a + * bug, but not a hard error, so enable ints and continue */ +@@ -3574,7 +3574,7 @@ static int iegbe_clean(struct napi_struc + if (work_done < budget) { + if (likely(adapter->itr_setting & 3)) + iegbe_set_itr(adapter); +- netif_rx_complete(poll_dev, napi); ++ napi_complete(napi); + iegbe_irq_enable(adapter); + } + diff --git a/package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch b/package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch new file mode 100644 index 000000000..7147449c2 --- /dev/null +++ b/package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch @@ -0,0 +1,103 @@ +--- a/Embedded/src/GbE/iegbe.h ++++ b/Embedded/src/GbE/iegbe.h +@@ -316,7 +316,6 @@ struct iegbe_adapter { + int cleaned_count); + struct iegbe_rx_ring *rx_ring; /* One per active queue */ + struct napi_struct napi; +- struct net_device *polling_netdev; /* One per active queue */ + + int num_tx_queues; + int num_rx_queues; +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -763,7 +763,7 @@ static int __devinit iegbe_probe(struct + struct iegbe_hw *hw; + + static int cards_found = 0; +- int i, err, pci_using_dac; ++ int err, pci_using_dac; + u16 eeprom_data = 0; + u16 eeprom_apme_mask = E1000_EEPROM_APME; + int bars; +@@ -984,11 +984,8 @@ err_eeprom: + iegbe_phy_hw_reset(hw); + if (hw->flash_address) + iounmap(hw->flash_address); +- for (i = 0; i < adapter->num_rx_queues; i++) +- dev_put(&adapter->polling_netdev[i]); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); +- kfree(adapter->polling_netdev); + err_sw_init: + iounmap(hw->hw_addr); + err_ioremap: +@@ -1017,7 +1014,6 @@ iegbe_remove(struct pci_dev *pdev) + struct net_device *netdev = pci_get_drvdata(pdev); + struct iegbe_adapter *adapter = netdev_priv(netdev); + uint32_t manc; +- int i; + + if(adapter->hw.mac_type >= iegbe_82540 + && adapter->hw.mac_type != iegbe_icp_xxxx +@@ -1030,15 +1026,11 @@ iegbe_remove(struct pci_dev *pdev) + } + + unregister_netdev(netdev); +- for (i = 0x0; i < adapter->num_rx_queues; i++) +- dev_put(&adapter->polling_netdev[i]); +- + if(!iegbe_check_phy_reset_block(&adapter->hw)) { + iegbe_phy_hw_reset(&adapter->hw); + } + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); +- kfree(adapter->polling_netdev); + + iounmap(adapter->hw.hw_addr); + pci_release_regions(pdev); +@@ -1061,7 +1053,6 @@ iegbe_sw_init(struct iegbe_adapter *adap + struct iegbe_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; +- int i; + + /* PCI config space info */ + +@@ -1111,11 +1102,6 @@ iegbe_sw_init(struct iegbe_adapter *adap + return -ENOMEM; + } + +- for (i = 0; i < adapter->num_rx_queues; i++) { +- adapter->polling_netdev[i].priv = adapter; +- dev_hold(&adapter->polling_netdev[i]); +- set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state); +- } + spin_lock_init(&adapter->tx_queue_lock); + + /* +@@ -1137,8 +1123,7 @@ iegbe_sw_init(struct iegbe_adapter *adap + * @adapter: board private structure to initialize + * + * We allocate one ring per queue at run-time since we don't know the +- * number of queues at compile-time. The polling_netdev array is +- * intended for Multiqueue, but should work fine with a single queue. ++ * number of queues at compile-time. + **/ + + static int __devinit +@@ -1158,15 +1143,6 @@ iegbe_alloc_queues(struct iegbe_adapter + return -ENOMEM; + } + +- adapter->polling_netdev = kcalloc(adapter->num_rx_queues, +- sizeof(struct net_device), +- GFP_KERNEL); +- if (!adapter->polling_netdev) { +- kfree(adapter->tx_ring); +- kfree(adapter->rx_ring); +- return -ENOMEM; +- } +- + return E1000_SUCCESS; + } + diff --git a/package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch b/package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch new file mode 100644 index 000000000..71d2d54e6 --- /dev/null +++ b/package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch @@ -0,0 +1,60 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -2161,7 +2161,8 @@ static void iegbe_set_rx_mode(struct net + { + struct iegbe_adapter *adapter = netdev_priv(netdev); + struct iegbe_hw *hw = &adapter->hw; +- struct dev_addr_list *uc_ptr; ++ struct netdev_hw_addr *ha; ++ bool use_uc = false; + struct dev_addr_list *mc_ptr; + u32 rctl; + u32 hash_value; +@@ -2187,12 +2188,11 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + } + } + +- uc_ptr = NULL; + if (netdev->uc_count > rar_entries - 1) { + rctl |= E1000_RCTL_UPE; + } else if (!(netdev->flags & IFF_PROMISC)) { + rctl &= ~E1000_RCTL_UPE; +- uc_ptr = netdev->uc_list; ++ use_uc = true; + } + + E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +@@ -2210,13 +2210,20 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + * if there are not 14 addresses, go ahead and clear the filters + * -- with 82571 controllers only 0-13 entries are filled here + */ ++ i = 1; ++ if (use_uc) ++ list_for_each_entry(ha, &netdev->uc_list, list) { ++ if (i == rar_entries) ++ break; ++ iegbe_rar_set(hw, ha->addr, i++); ++ } ++ ++ WARN_ON(i == rar_entries); ++ + mc_ptr = netdev->mc_list; + +- for (i = 1; i < rar_entries; i++) { +- if (uc_ptr) { +- iegbe_rar_set(hw, uc_ptr->da_addr, i); +- uc_ptr = uc_ptr->next; +- } else if (mc_ptr) { ++ for (; i < rar_entries; i++) { ++ if (mc_ptr) { + iegbe_rar_set(hw, mc_ptr->da_addr, i); + mc_ptr = mc_ptr->next; + } else { +@@ -2226,7 +2233,6 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + E1000_WRITE_FLUSH(&adapter->hw); + } + } +- WARN_ON(uc_ptr != NULL); + + /* clear the old settings from the multicast hash table */ + diff --git a/package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch b/package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch new file mode 100644 index 000000000..c6eced6a5 --- /dev/null +++ b/package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch @@ -0,0 +1,20 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -2188,7 +2188,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + } + } + +- if (netdev->uc_count > rar_entries - 1) { ++ if (netdev->uc.count > rar_entries - 1) { + rctl |= E1000_RCTL_UPE; + } else if (!(netdev->flags & IFF_PROMISC)) { + rctl &= ~E1000_RCTL_UPE; +@@ -2212,7 +2212,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + */ + i = 1; + if (use_uc) +- list_for_each_entry(ha, &netdev->uc_list, list) { ++ list_for_each_entry(ha, &netdev->uc.list, list) { + if (i == rar_entries) + break; + iegbe_rar_set(hw, ha->addr, i++); diff --git a/package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch b/package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch new file mode 100644 index 000000000..c7a103b44 --- /dev/null +++ b/package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch @@ -0,0 +1,20 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -775,13 +775,13 @@ static int __devinit iegbe_probe(struct + if (err) + return err; + +- if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && +- !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { ++ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && ++ !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { + pci_using_dac = 1; + } else { +- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { +- err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + E1000_ERR("No usable DMA configuration, " + "aborting\n"); diff --git a/package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch b/package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch new file mode 100644 index 000000000..a08e8c769 --- /dev/null +++ b/package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch @@ -0,0 +1,12 @@ +--- a/Embedded/src/GbE/iegbe_ethtool.c ++++ b/Embedded/src/GbE/iegbe_ethtool.c +@@ -944,7 +944,8 @@ iegbe_intr_test(struct iegbe_adapter *ad + *data = 0; + + /* Hook up test interrupt handler just for this test */ +- if(!request_irq(irq, &iegbe_test_intr, 0, netdev->name, netdev)) { ++ if(!request_irq(irq, &iegbe_test_intr, IRQF_PROBE_SHARED, netdev->name, ++ netdev)) { + shared_int = FALSE; + } else if(request_irq(irq, &iegbe_test_intr, IRQF_SHARED, + netdev->name, netdev)){ diff --git a/package/ep80579-drivers/patches/150-ocracoke_island.patch b/package/ep80579-drivers/patches/150-ocracoke_island.patch new file mode 100644 index 000000000..34c11daac --- /dev/null +++ b/package/ep80579-drivers/patches/150-ocracoke_island.patch @@ -0,0 +1,747 @@ +--- a/Embedded/src/GbE/iegbe_oem_phy.c ++++ b/Embedded/src/GbE/iegbe_oem_phy.c +@@ -65,6 +65,10 @@ static int32_t iegbe_oem_link_m88_setup( + static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw); + static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw); + ++static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw); ++static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data); ++static int32_t oi_phy_setup (struct iegbe_hw *hw); ++ + /** + * iegbe_oem_setup_link + * @hw: iegbe_hw struct containing device specific information +@@ -114,6 +118,10 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + } + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ return E1000_SUCCESS; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_link_m88_setup(hw); +@@ -121,6 +129,12 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + return ret_val; + } + break; ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_oem_link_bcm5481_setup(hw); ++ if(ret_val) { ++ return ret_val; ++ } ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -179,6 +193,51 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + #endif /* ifdef EXTERNAL_MDIO */ + } + ++/** ++ * iegbe_oem_link_bcm5481_setup ++ * @hw: iegbe_hw struct containing device specific information ++ * ++ * Returns E1000_SUCCESS, negative E1000 error code on failure ++ * ++ * copied verbatim from iegbe_oem_link_m88_setup ++ **/ ++static int32_t ++iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw) ++{ ++ int32_t ret_val; ++ uint16_t phy_data; ++ ++ //DEBUGFUNC(__func__); ++ ++ if(!hw) ++ return -1; ++ ++ /* phy_reset_disable is set in iegbe_oem_set_phy_mode */ ++ if(hw->phy_reset_disable) ++ return E1000_SUCCESS; ++ ++ // Enable MDIX in extended control reg. ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data); ++ if(ret_val) ++ { ++ DEBUGOUT("Unable to read BCM5481_ECTRL register\n"); ++ return ret_val; ++ } ++ ++ phy_data &= ~BCM5481_ECTRL_DISMDIX; ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data); ++ if(ret_val) ++ { ++ DEBUGOUT("Unable to write BCM5481_ECTRL register\n"); ++ return ret_val; ++ } ++ ++ ret_val = oi_phy_setup (hw); ++ if (ret_val) ++ return ret_val; ++ ++ return E1000_SUCCESS; ++} + + /** + * iegbe_oem_link_m88_setup +@@ -340,6 +399,11 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw, + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, +@@ -415,6 +479,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + DEBUGOUT("No DSP to reset on OEM PHY\n"); + break; + default: +@@ -460,6 +526,11 @@ iegbe_oem_cleanup_after_phy_reset(struct + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* +@@ -573,6 +644,11 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + * use iegbe_set_phy_mode as example + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_read_eeprom(hw, +@@ -641,6 +717,19 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw + } + hw->phy_type = iegbe_phy_oem; + ++{ ++ // If MAC2 (BCM5395 switch), manually detect the phy ++ struct iegbe_adapter *adapter; ++ uint32_t device_number; ++ adapter = (struct iegbe_adapter *) hw->back; ++ device_number = PCI_SLOT(adapter->pdev->devfn); ++ if (device_number == ICP_XXXX_MAC_2) { ++ hw->phy_id = BCM5395S_PHY_ID; ++ hw->phy_revision = 0; ++ return E1000_SUCCESS; ++ } ++} ++ + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high); + if(ret_val) { + DEBUGOUT("Unable to read PHY register PHY_ID1\n"); +@@ -690,6 +779,8 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw) + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT; + break; + default: +@@ -738,6 +829,8 @@ iegbe_oem_phy_is_copper(struct iegbe_hw + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + isCopper = TRUE; + break; + default: +@@ -796,13 +889,13 @@ iegbe_oem_get_phy_dev_number(struct iegb + switch(device_number) + { + case ICP_XXXX_MAC_0: +- hw->phy_addr = 0x00; ++ hw->phy_addr = 0x01; + break; + case ICP_XXXX_MAC_1: +- hw->phy_addr = 0x01; ++ hw->phy_addr = 0x02; + break; + case ICP_XXXX_MAC_2: +- hw->phy_addr = 0x02; ++ hw->phy_addr = 0x00; + break; + default: hw->phy_addr = 0x00; + } +@@ -851,6 +944,12 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(!adapter || !ifr) { + return -1; + } ++ ++ // If MAC2 (BCM5395 switch) then leave now ++ if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) { ++ return -1; ++ } ++ + switch (data->reg_num) { + case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +@@ -987,6 +1086,11 @@ void iegbe_oem_get_phy_regs(struct iegbe + * [10] = mdix mode + */ + switch (adapter->hw.phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + if(corrected_len > 0) { +@@ -1068,8 +1172,13 @@ iegbe_oem_phy_loopback(struct iegbe_adap + * Loopback configuration is the same for each of the supported PHYs. + */ + switch (adapter->hw.phy_id) { ++ case BCM5395S_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: + + adapter->hw.autoneg = FALSE; + +@@ -1182,8 +1291,14 @@ iegbe_oem_loopback_cleanup(struct iegbe_ + } + + switch (adapter->hw.phy_id) { ++ case BCM5395S_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n"); ++ return; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: + default: + adapter->hw.autoneg = TRUE; + +@@ -1243,6 +1358,11 @@ iegbe_oem_phy_speed_downgraded(struct ie + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ *isDowngraded = 0; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, +@@ -1305,6 +1425,11 @@ iegbe_oem_check_polarity(struct iegbe_hw + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ *polarity = 0; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* return the Polarity bit in the Status register. */ +@@ -1367,6 +1492,25 @@ iegbe_oem_phy_is_full_duplex(struct iegb + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Always full duplex */ ++ *isFD = 1; ++ break; ++ ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); ++ if(ret_val) return ret_val; ++ ++ switch (BCM5481_ASTAT_HCD(phy_data)) { ++ case BCM5481_ASTAT_1KBTFD: ++ case BCM5481_ASTAT_100BTXFD: ++ *isFD = 1; ++ break; ++ default: ++ *isFD = 0; ++ } ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, +@@ -1423,6 +1567,25 @@ iegbe_oem_phy_is_speed_1000(struct iegbe + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Always 1000mb */ ++ *is1000 = 1; ++ break; ++ ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); ++ if(ret_val) return ret_val; ++ ++ switch (BCM5481_ASTAT_HCD(phy_data)) { ++ case BCM5481_ASTAT_1KBTFD: ++ case BCM5481_ASTAT_1KBTHD: ++ *is1000 = 1; ++ break; ++ default: ++ *is1000 = 0; ++ } ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, +@@ -1478,6 +1641,25 @@ iegbe_oem_phy_is_speed_100(struct iegbe_ + * see iegbe_config_mac_to_phy + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Always 1000Mb, never 100mb */ ++ *is100 = 0; ++ break; ++ ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); ++ if(ret_val) return ret_val; ++ ++ switch (BCM5481_ASTAT_HCD(phy_data)) { ++ case BCM5481_ASTAT_100BTXFD: ++ case BCM5481_ASTAT_100BTXHD: ++ *is100 = 1; ++ break; ++ default: ++ *is100 = 0; ++ } ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, +@@ -1535,6 +1717,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + * see iegbe_phy_m88_get_info + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* The downshift status is checked only once, after link is +@@ -1636,8 +1823,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw * + * the M88 used in truxton. + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register PHY_CTRL\n"); +@@ -1699,6 +1891,8 @@ iegbe_oem_phy_init_script(struct iegbe_h + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + DEBUGOUT("Nothing to do for OEM PHY Init"); + break; + default: +@@ -1735,6 +1929,11 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + return -1; + } + ++ if (hw->phy_id == BCM5395S_PHY_ID) { ++ DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n"); ++ return -1; ++ } ++ + /* call the GCU func that will read the phy + * + * Make note that the M88 phy is what'll be used on Truxton. +@@ -1782,6 +1981,11 @@ iegbe_oem_set_trans_gasket(struct iegbe_ + } + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* Gasket set correctly for Marvell Phys, so nothing to do */ +@@ -1886,6 +2090,8 @@ iegbe_oem_phy_needs_reset_with_mac(struc + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + ret_val = FALSE; + break; + default: +@@ -1935,6 +2141,8 @@ iegbe_oem_config_dsp_after_link_change(s + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + DEBUGOUT("No DSP to configure on OEM PHY"); + break; + default: +@@ -1978,6 +2186,12 @@ iegbe_oem_get_cable_length(struct iegbe_ + } + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ *min_length = 0; ++ *max_length = iegbe_igp_cable_length_150; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, +@@ -2061,6 +2275,23 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Link always up */ ++ *isUp = TRUE; ++ return E1000_SUCCESS; ++ break; ++ ++ case BCM5481_PHY_ID: ++ iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); ++ if(ret_val) ++ { ++ DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n"); ++ return ret_val; ++ } ++ statusMask = BCM5481_ESTAT_LINK; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +@@ -2092,3 +2323,210 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + #endif /* ifdef EXTERNAL_MDIO */ + } + ++ ++ ++//----- ++// Read BCM5481 expansion register ++// ++int32_t ++bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data) ++{ ++ int ret; ++ uint16_t selector; ++ uint16_t reg_data; ++ ++ // Get the current value of bits 15:12 ++ ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector); ++ if (ret) ++ return ret; ++ ++ // Select the expansion register ++ selector &= 0xf000; ++ selector |= (0xf << 8) | (reg); ++ iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); ++ ++ // Read the expansion register ++ ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, ®_data); ++ ++ // De-select the expansion registers. ++ selector &= 0xf000; ++ iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); ++ ++ if (ret) ++ return ret; ++ ++ *data = reg_data; ++ return ret; ++} ++ ++//----- ++// Read reg 0x18 sub-register ++// ++static int32_t ++bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data) ++{ ++ int ret; ++ uint16_t tmp_data; ++ ++ // Select reg 0x18, sv ++ tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL; ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data); ++ if(ret) ++ return ret; ++ ++ // Read reg 0x18, sv ++ ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data); ++ if(ret) ++ return ret; ++ ++ *data = tmp_data; ++ return ret; ++} ++ ++//----- ++// Read reg 0x1C sub-register ++// ++int32_t ++bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data) ++{ ++ int ret; ++ uint16_t tmp_data; ++ ++ // Select reg 0x1c, sv ++ tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data); ++ if(ret) ++ return ret; ++ ++ // Read reg 0x1c, sv ++ ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data); ++ if(ret) ++ return ret; ++ ++ *data = tmp_data; ++ return ret; ++} ++ ++//----- ++// Read-modify-write a 0x1C register. ++// ++// hw - hardware access info. ++// reg - 0x1C register to modify. ++// data - bits which should be set. ++// mask - the '1' bits in this argument will be cleared in the data ++// read from 'reg' then 'data' will be or'd in and the result ++// will be written to 'reg'. ++ ++int32_t ++bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask) ++{ ++ int32_t ret; ++ uint16_t reg_data; ++ ++ ret = 0; ++ ++ ret = bcm5481_read_1csv (hw, reg, ®_data); ++ if (ret) ++ { ++ DEBUGOUT("Unable to read BCM5481 1CH register\n"); ++ printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg); ++ return ret; ++ } ++ ++ reg_data &= ~mask; ++ reg_data |= (BCM5481_R1CH_WE | data); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481 1CH register\n"); ++ printk (KERN_ERR "Unable to write BCM5481 1CH register\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int32_t ++oi_phy_setup (struct iegbe_hw *hw) ++{ ++ int ret; ++ uint16_t pmii_data; ++ uint16_t mctrl_data; ++ uint16_t cacr_data; ++ ++ ret = 0; ++ ++ // Set low power mode via reg 0x18, sv010, bit 6 ++ // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits. ++ ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data); ++ if (ret) ++ { ++ DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n"); ++ printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n"); ++ return ret; ++ } ++ ++ // Set the LPM bit in the data just read and write back to sv010 ++ // The shadow register select bits [2:0] are set by reading the sv010 ++ // register. ++ pmii_data |= BCM5481_R18H_SV010_LPM; ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481_R18H register\n"); ++ printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); ++ return ret; ++ } ++ ++ ++ // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111 ++ ++ if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data)) ++ { ++ DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n"); ++ printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n"); ++ return ret; ++ } ++ mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481_R18H register\n"); ++ printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); ++ return ret; ++ } ++ ++ // Enable RGMII transmit clock delay in reg 0x1c, sv00011 ++ ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data); ++ if (ret) ++ { ++ DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n"); ++ printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n"); ++ return ret; ++ } ++ ++ cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481_R1CH register\n"); ++ printk (KERN_ERR "Unable to write BCM5481_R1CH register\n"); ++ return ret; ++ } ++ ++ // Enable dual link speed indication (0x1c, sv 00010, bit 2) ++ ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK); ++ if (ret) ++ return ret; ++ ++ // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0) ++ ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN); ++ if (ret) ++ return ret; ++ ++ return ret; ++} +--- a/Embedded/src/GbE/iegbe_oem_phy.h ++++ b/Embedded/src/GbE/iegbe_oem_phy.h +@@ -95,6 +95,8 @@ int32_t iegbe_oem_phy_is_link_up(struct + + #define DEFAULT_ICP_XXXX_TIPG_IPGT 8 /* Inter Packet Gap Transmit Time */ + #define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL ++#define BCM5481_PHY_ID 0x0143BCA0 ++#define BCM5395S_PHY_ID 0x0143BCF0 + + /* Miscellaneous defines */ + #ifdef IEGBE_10_100_ONLY +@@ -103,5 +105,65 @@ int32_t iegbe_oem_phy_is_link_up(struct + #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x2F + #endif + ++/* BCM5481 specifics */ ++ ++#define BCM5481_ECTRL (0x10) ++#define BCM5481_ESTAT (0x11) ++#define BCM5481_RXERR (0x12) ++#define BCM5481_EXPRW (0x15) ++#define BCM5481_EXPACC (0x17) ++#define BCM5481_ASTAT (0x19) ++#define BCM5481_R18H (0x18) ++#define BCM5481_R1CH (0x1c) ++ ++/* indirect register access via register 18h */ ++ ++#define BCM5481_R18H_SV_MASK (7) // Mask for SV bits. ++#define BCM5481_R18H_SV_ACTRL (0) // SV000 Aux. control ++#define BCM5481_R18H_SV_10BT (1) // SV001 10Base-T ++#define BCM5481_R18H_SV_PMII (2) // SV010 Power/MII control ++#define BCM5481_R18H_SV_MTEST (4) // SV100 Misc. test ++#define BCM5481_R18H_SV_MCTRL (7) // SV111 Misc. control ++ ++#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity ++#define BCM5481_R18H_SV010_LPM (1 << 6) ++#define BCM5481_R18H_SV111_SKEW (1 << 8) ++#define BCM5481_R18H_WE (1 << 15) // Write enable ++ ++// 0x1c registers ++#define BCM5481_R1CH_SV_SHIFT (10) ++#define BCM5481_R1CH_SV_MASK (0x1f) ++#define BCM5481_R1CH_SC1 (0x02) // sv00010 Spare control 1 ++#define BCM5481_R1CH_CACR (0x03) // sv00011 Clock alignment control ++#define BCM5481_R1CH_LCTRL (0x09) // sv01001 LED control ++#define BCM5481_R1CH_LEDS1 (0x0d) // sv01101 LED selector 1 ++ ++// 0x1c common ++#define BCM5481_R1CH_WE (1 << 15) // Write enable ++ ++// 0x1c, sv 00010 ++#define BCM5481_R1CH_SC1_LINK (1 << 2) // sv00010 Linkspeed ++ ++// 0x1c, sv 00011 ++#define BCM5481_R1CH_CACR_TCD (1 << 9) // sv00011 RGMII tx clock delay ++ ++// 0x1c, sv 01001 ++#define BCM5481_R1CH_LCTRL_ALEN (1 << 4) // Activity/Link enable on ACTIVITY LED ++#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED ++ ++#define BCM5481_ECTRL_DISMDIX (1 <<14) ++ ++#define BCM5481_MCTRL_AUTOMDIX (1 <<9) ++ ++#define BCM5481_ESTAT_LINK (1 << 8) ++ ++#define BCM5481_ASTAT_ANC (1 << 15) ++#define BCM5481_ASTAT_ANHCD (7 << 8) ++#define BCM5481_ASTAT_HCD(x) ((x >> 8) & 7) ++#define BCM5481_ASTAT_1KBTFD (0x7) ++#define BCM5481_ASTAT_1KBTHD (0x6) ++#define BCM5481_ASTAT_100BTXFD (0x5) ++#define BCM5481_ASTAT_100BTXHD (0x3) ++ + #endif /* ifndef _IEGBE_OEM_PHY_H_ */ + diff --git a/package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch b/package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch new file mode 100644 index 000000000..291946625 --- /dev/null +++ b/package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch @@ -0,0 +1,11 @@ +--- a/Embedded/src/CAN/icp_can_user.h ++++ b/Embedded/src/CAN/icp_can_user.h +@@ -63,6 +63,8 @@ + #ifndef __ICP_CAN_USER_H__ + #define __ICP_CAN_USER_H__ + ++#include ++ + /***************************************************************************** + * Device IO control codes. + *****************************************************************************/ diff --git a/package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch b/package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch new file mode 100644 index 000000000..26c53dcea --- /dev/null +++ b/package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch @@ -0,0 +1,11 @@ +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -70,6 +70,8 @@ + + #include "can_main.h" + #include "can_ioctl.h" ++#include ++ + + MODULE_AUTHOR("Intel(R) Corporation"); + MODULE_DESCRIPTION("Controller Area Network Driver"); diff --git a/package/ep80579-drivers/patches/220-can_fix_irq_request.patch b/package/ep80579-drivers/patches/220-can_fix_irq_request.patch new file mode 100644 index 000000000..2950cc79e --- /dev/null +++ b/package/ep80579-drivers/patches/220-can_fix_irq_request.patch @@ -0,0 +1,23 @@ +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -654,7 +654,7 @@ int can_dev_io(struct inode *inode, stru + /***************************************************************************** + * Interrupt handler. + *****************************************************************************/ +-irqreturn_t can_irq_handler(int irq, void *dev_id, struct pt_regs *regs) ++irqreturn_t can_irq_handler(int irq, void *dev_id) + { + can_os_t *can_os = (can_os_t *) dev_id; + unsigned int int_status; +--- a/Embedded/src/CAN/can_main.h ++++ b/Embedded/src/CAN/can_main.h +@@ -165,8 +165,7 @@ int can_dev_io( + + irqreturn_t can_irq_handler( + int irq, +- void *dev_id, +- struct pt_regs *regs); ++ void *dev_id); + + void can_tasklet( + unsigned long arg diff --git a/package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch b/package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch new file mode 100644 index 000000000..57e9c8fc0 --- /dev/null +++ b/package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch @@ -0,0 +1,41 @@ +diff -Nur a/Embedded/src/CAN/can_main.c b/Embedded/src/CAN/can_main.c +--- a/Embedded/src/CAN/can_main.c 2009-11-30 10:44:39.044269751 +0100 ++++ b/Embedded/src/CAN/can_main.c 2009-11-30 10:54:41.434355642 +0100 +@@ -213,8 +213,8 @@ + spin_lock_init(&(g_can_os[can_num].int_spinlock)); + spin_lock_init(&(g_can_os[can_num].open_spinlock)); + +- dev->dev.driver_data = (void *) &(g_can_os[can_num]); +- if (!dev->dev.driver_data) ++ dev_set_drvdata(&dev->dev, (void *) &(g_can_os[can_num])); ++ if (!dev_get_drvdata(&dev->dev)) + { + printk("Couldn't create CAN device %d. Exiting.\n", + dev->device); +@@ -236,7 +236,7 @@ + *****************************************************************************/ + void can_pci_remove(struct pci_dev *dev) + { +- can_os_t *can_os = dev->dev.driver_data; ++ can_os_t *can_os = dev_get_drvdata(&dev->dev); + + iounmap(can_os->pci_remap); + icp_can_destroy(can_os->can); +@@ -250,7 +250,7 @@ + { + unsigned int i; + unsigned int int_status; +- can_os_t *can_os = dev->dev.driver_data; ++ can_os_t *can_os = dev_get_drvdata(&dev->dev); + int err; + + /* Indicate that we are suspending */ +@@ -321,7 +321,7 @@ + int can_pci_resume(struct pci_dev *dev) + { + unsigned int i; +- can_os_t *can_os = dev->dev.driver_data; ++ can_os_t *can_os = dev_get_drvdata(&dev->dev); + + /* Restore PCI CFG space */ + pci_restore_state(dev); diff --git a/package/ep80579-drivers/patches/300-wdt_compile_fix.patch b/package/ep80579-drivers/patches/300-wdt_compile_fix.patch new file mode 100644 index 000000000..59242b80b --- /dev/null +++ b/package/ep80579-drivers/patches/300-wdt_compile_fix.patch @@ -0,0 +1,59 @@ +--- a/Embedded/src/WDT/iwdt.c ++++ b/Embedded/src/WDT/iwdt.c +@@ -180,19 +180,19 @@ MODULE_PARM_DESC(wdt_scale, "Intel WDT s + module_param(wdt_intr_type, byte, WDT_INT_TYPE_IRQ); + MODULE_PARM_DESC(wdt_intr_type, "Intel WDT interrupt type (default SERIRQ)."); + +-module_param(wdt_margin1, uint, TIMER_MARGIN); ++module_param(wdt_margin1, uint, 0); + MODULE_PARM_DESC(wdt_margin1, "First stage Intel WDT timeout in steps of 1 ms by default."); + +-module_param(wdt_margin2, uint, TIMER_MARGIN); ++module_param(wdt_margin2, uint, 0); + MODULE_PARM_DESC(wdt_margin2, "Second stage Intel WDT timeout in steps of 1 ms by default."); + + module_param(nowayout, int, 0); + MODULE_PARM_DESC(nowayout, "Intel WDT can't be stopped once started (default=0)"); + +-module_param(wdt_index_port, int, 0x4E); ++module_param(wdt_index_port, int, 0); + MODULE_PARM_DESC(wdt_index_port, "WDT Index Port (default 0x4e)"); + +-module_param(wdt_data_port, int, 0x4E); ++module_param(wdt_data_port, int, 0); + MODULE_PARM_DESC(wdt_data_port, "WDT Data Port (default 0x4f)"); + + static int wdt_get_iobase(struct pci_dev *dev, u16 *iobase, int *irq); +@@ -218,7 +218,7 @@ static ssize_t wdt_write(struct file *fi + size_t count, loff_t * pos); + static int wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +-static irqreturn_t wdt_isr(int irq, void *dev_id, struct pt_regs *regs); ++static irqreturn_t wdt_isr(int irq, void *dev_id); + static void __exit wdt_cleanup(void); + static int __init wdt_init(void); + static int __init wdt_init_one(struct pci_dev *dev, +@@ -255,7 +255,7 @@ static struct pci_driver wdt_driver = { + name: "iwdt", + id_table: lpc_pci_tbl, + probe: wdt_init_one, +- remove: __devexit(wdt_remove_one), ++ remove: __devexit_p(wdt_remove_one), + suspend: wdt_pci_suspend, + resume: wdt_pci_resume, + }; +@@ -1393,12 +1393,12 @@ static int wdt_ioctl(struct inode *inode + + /* + * Function Name: wdt_isr() +- * Parameter: int irq - irq number, void *dev_id, struct pt_regs *regs ++ * Parameter: int irq - irq number, void *dev_id + * Return Value:: IRQ_NONE - if the interrupt is not for wdt. + * IRQ_HANDLED - if it is for wdt. + * Description: This is the interrupt service routine of the WDT. + */ +-static irqreturn_t wdt_isr(int irq, void *dev_id, struct pt_regs *regs) ++static irqreturn_t wdt_isr(int irq, void *dev_id) + { + u8 val; + diff --git a/package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch b/package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch new file mode 100644 index 000000000..d858aff1f --- /dev/null +++ b/package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch @@ -0,0 +1,22 @@ +--- a/Embedded/src/EDMA/dma_linux.c ++++ b/Embedded/src/EDMA/dma_linux.c +@@ -149,8 +149,7 @@ int32_t edma_suspend (struct pci_dev *de + int32_t edma_resume(struct pci_dev *dev); + int32_t initialize_edma_device(struct edma_device *device); + +-static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id, +- struct pt_regs * regs); ++static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id); + + /* Prototypes - Misc. */ + +@@ -429,8 +428,7 @@ int32_t edma_release(struct inode * inod + * Return Values: HANDLED = 1, NOT_HANDLED = 0 + *****************************************************************************/ + +-static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id, +- struct pt_regs * regs) ++static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id) + { + + uint32_t clear_bits; diff --git a/package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch b/package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch new file mode 100644 index 000000000..f3f9acb1e --- /dev/null +++ b/package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch @@ -0,0 +1,22 @@ +--- a/Embedded/src/1588/1588.c ++++ b/Embedded/src/1588/1588.c +@@ -631,7 +631,7 @@ int restore_interrupts(void) + IRQ_NONE => this device did not interrupt + + ******************************************************************************/ +-irqreturn_t timesync_isr(int irq, void *dev_id, struct pt_regs *regs) ++irqreturn_t timesync_isr(int irq, void *dev_id) + { + if ( !ixTimeSyncAccEventAmmsFlagGet() && !ixTimeSyncAccEventAsmsFlagGet()&& + !ixTimeSyncAccEventAtmFlagGet() && !ixTimeSyncAccEventPpsmFlagGet()&& +--- a/Embedded/src/1588/1588.h ++++ b/Embedded/src/1588/1588.h +@@ -128,7 +128,7 @@ int pci_suspend(struct pci_dev *dev, pm_ + int pci_resume(struct pci_dev *dev); + int pci_probe(struct pci_dev *dev, const struct pci_device_id *id); + void pci_remove(struct pci_dev *dev); +-irqreturn_t timesync_isr(int irq, void *dev_id, struct pt_regs *regs); ++irqreturn_t timesync_isr(int irq, void *dev_id); + + // private functions + int save_reg_state(void); diff --git a/package/ep80579-drivers/patches/600-2.6.27_includes.patch b/package/ep80579-drivers/patches/600-2.6.27_includes.patch new file mode 100644 index 000000000..c11275ece --- /dev/null +++ b/package/ep80579-drivers/patches/600-2.6.27_includes.patch @@ -0,0 +1,22 @@ +--- a/Embedded/src/CAN/can_main.h ++++ b/Embedded/src/CAN/can_main.h +@@ -65,7 +65,7 @@ + + #include + #include +-#include ++#include + #include + #include + #include +--- a/Embedded/src/EDMA/dma_linux.c ++++ b/Embedded/src/EDMA/dma_linux.c +@@ -87,7 +87,7 @@ + #include /* O_ACCMODE */ + #include /* cli, *_flags */ + #include /* copy_to_user */ +-#include ++#include + #include /* inb(), outb() */ + #include + #include /* request_region */ diff --git a/package/ep80579-drivers/patches/601-2.6.32_includes.patch b/package/ep80579-drivers/patches/601-2.6.32_includes.patch new file mode 100644 index 000000000..680bbf11b --- /dev/null +++ b/package/ep80579-drivers/patches/601-2.6.32_includes.patch @@ -0,0 +1,33 @@ +diff -Nur a/Embedded/src/1588/1588.c b/Embedded/src/1588/1588.c +--- a/Embedded/src/1588/1588.c 2009-11-10 14:20:46.563322192 +0100 ++++ b/Embedded/src/1588/1588.c 2009-11-30 10:44:22.144270452 +0100 +@@ -72,6 +72,7 @@ + * + ****************************************************************************/ + ++#include + #include "1588.h" + + MODULE_AUTHOR("Intel(R) Corporation"); +diff -Nur a/Embedded/src/CAN/can_main.c b/Embedded/src/CAN/can_main.c +--- a/Embedded/src/CAN/can_main.c 2009-11-10 14:20:46.563322192 +0100 ++++ b/Embedded/src/CAN/can_main.c 2009-11-30 10:44:39.044269751 +0100 +@@ -68,6 +68,7 @@ + * + **************************************************************************/ + ++#include + #include "can_main.h" + #include "can_ioctl.h" + +diff -Nur a/Embedded/src/WDT/iwdt.c b/Embedded/src/WDT/iwdt.c +--- a/Embedded/src/WDT/iwdt.c 2009-11-10 14:20:46.563322192 +0100 ++++ b/Embedded/src/WDT/iwdt.c 2009-11-30 10:44:54.024262744 +0100 +@@ -137,6 +137,7 @@ + #include + #include + #include ++#include + #include "iwdt.h" + + MODULE_AUTHOR("Intel(R) Corporation"); diff --git a/package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch b/package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch new file mode 100644 index 000000000..ca8c1bb9e --- /dev/null +++ b/package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch @@ -0,0 +1,31 @@ +--- a/Embedded/src/GbE/kcompat.h ++++ b/Embedded/src/GbE/kcompat.h +@@ -46,12 +46,6 @@ GPL LICENSE SUMMARY + #include + #include + +-#ifndef IRQ_HANDLED +-#define irqreturn_t void +-#define IRQ_HANDLED +-#define IRQ_NONE +-#endif +- + #ifndef SET_NETDEV_DEV + #define SET_NETDEV_DEV(net, pdev) + #endif +@@ -748,6 +742,15 @@ extern void dump_stack(void); + + #endif /* 2.4.24 */ + ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ) ++#ifndef IRQ_HANDLED ++#define irqreturn_t void ++#define IRQ_HANDLED ++#define IRQ_NONE ++#endif ++#endif /* < 2.6.30 */ ++ + #endif /* _KCOMPAT_H_ */ + + diff --git a/package/ep80579-drivers/patches/701-iegbe_poll_dev.patch b/package/ep80579-drivers/patches/701-iegbe_poll_dev.patch new file mode 100644 index 000000000..63a132685 --- /dev/null +++ b/package/ep80579-drivers/patches/701-iegbe_poll_dev.patch @@ -0,0 +1,11 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -3534,7 +3534,7 @@ static int iegbe_clean(struct napi_struc + int tx_cleaned = 0, work_done = 0; + + /* Must NOT use netdev_priv macro here. */ +- adapter = poll_dev->priv; ++ adapter = netdev_priv(poll_dev); + + /* iegbe_clean is called per-cpu. This lock protects + * tx_ring[0] from being cleaned by multiple cpus diff --git a/target/linux/generic-2.6/config-2.6.32 b/target/linux/generic-2.6/config-2.6.32 index a9c4bfb82..b869c9ae9 100644 --- a/target/linux/generic-2.6/config-2.6.32 +++ b/target/linux/generic-2.6/config-2.6.32 @@ -550,6 +550,7 @@ CONFIG_EXPERIMENTAL=y # CONFIG_EXT4_DEBUG is not set # CONFIG_EXT4DEV_FS is not set # CONFIG_EXT4_FS is not set +# CONFIG_EXT4_FS_XATTR is not set CONFIG_EXTRA_FIRMWARE="" CONFIG_EXTRA_TARGETS="" # CONFIG_EZX_PCAP is not set diff --git a/target/linux/x86/Makefile b/target/linux/x86/Makefile index cd7c1b5c0..4cf011af7 100644 --- a/target/linux/x86/Makefile +++ b/target/linux/x86/Makefile @@ -10,7 +10,7 @@ ARCH:=i386 BOARD:=x86 BOARDNAME:=x86 FEATURES:=squashfs jffs2 ext2 vdi vmdk pcmcia tgz -SUBTARGETS=generic olpc xen_domu +SUBTARGETS=generic olpc xen_domu ep80579 LINUX_VERSION:=2.6.32.10 diff --git a/target/linux/x86/ep80579/config-default b/target/linux/x86/ep80579/config-default new file mode 100644 index 000000000..2a89b4fe6 --- /dev/null +++ b/target/linux/x86/ep80579/config-default @@ -0,0 +1,12 @@ +CONFIG_ATA=y +CONFIG_BLK_DEV_SD=y +# CONFIG_MTD_BLOCK2MTD is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHPTE is not set +# CONFIG_MTD is not set +# CONFIG_NOHIGHMEM is not set +CONFIG_SATA_AHCI=y +# CONFIG_SQUASHFS is not set +CONFIG_ITCO_WDT=y +# CONFIG_ITCO_VENDOR_SUPPORT is not set +CONFIG_LOG_BUF_SHIFT=17 diff --git a/target/linux/x86/ep80579/target.mk b/target/linux/x86/ep80579/target.mk new file mode 100644 index 000000000..00fe1abc3 --- /dev/null +++ b/target/linux/x86/ep80579/target.mk @@ -0,0 +1,9 @@ +BOARDNAME:=Intel EP80579 +DEFAULT_PACKAGES += kmod-ep80579-can kmod-ep80579-eth kmod-ep80579-misc \ + kmod-usb-core kmod-usb2 kmod-usb-hid kmod-usb-uhci + +define Target/Description + Build firmware images for Intel EP80579 based boards + (e.g : ADI Engineering Ocracoke Island) +endef + From a9e78431f4bfa9ee3767f6eb75e8b069f7487a11 Mon Sep 17 00:00:00 2001 From: acinonyx Date: Thu, 1 Apr 2010 15:22:13 +0000 Subject: [PATCH 41/45] [package] base-files: Cancel firmware loading if file doesn't exist git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20649 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/base-files/files/sbin/hotplug-call | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/base-files/files/sbin/hotplug-call b/package/base-files/files/sbin/hotplug-call index c5a76a76c..e56460de9 100755 --- a/package/base-files/files/sbin/hotplug-call +++ b/package/base-files/files/sbin/hotplug-call @@ -10,7 +10,7 @@ export HOTPLUG_TYPE="$1" echo 1 > "/sys$DEVPATH/loading" dd if="/lib/firmware/$FIRMWARE" of="/sys$DEVPATH/data" bs=64k echo 0 > "/sys$DEVPATH/loading" - } + } || echo -1 > "/sys$DEVPATH/loading" exit 0 } From 9e05e4b52ac9dafa60d40c4af9ff2043bfa07ca8 Mon Sep 17 00:00:00 2001 From: juhosg Date: Thu, 1 Apr 2010 15:39:23 +0000 Subject: [PATCH 42/45] mac80211: remove MCU requests for SoC platforms in the rt2x00 driver The ralink SoC platforms do not have an MCU. Signed-off-by: Luis Correia git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20650 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/mac80211/Makefile | 2 +- ...2-rt2x00-remove-mcu-requests-for-soc.patch | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 package/mac80211/patches/602-rt2x00-remove-mcu-requests-for-soc.patch diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index d7fde6b25..d93c982f6 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 PKG_VERSION:=2010-03-24 -PKG_RELEASE:=4 +PKG_RELEASE:=5 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources # http://www.orbit-lab.org/kernel/compat-wireless-2.6/2010/11 \ # http://wireless.kernel.org/download/compat-wireless-2.6 diff --git a/package/mac80211/patches/602-rt2x00-remove-mcu-requests-for-soc.patch b/package/mac80211/patches/602-rt2x00-remove-mcu-requests-for-soc.patch new file mode 100644 index 000000000..9cecf3a03 --- /dev/null +++ b/package/mac80211/patches/602-rt2x00-remove-mcu-requests-for-soc.patch @@ -0,0 +1,59 @@ +The ralink SoC platforms do not have an MCU. + +Signed-off-by: Luis Correia +--- + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -221,9 +221,9 @@ void rt2800_mcu_request(struct rt2x00_de + u32 reg; + + /* +- * SOC devices don't support MCU requests. ++ * some devices don't support MCU requests. + */ +- if (rt2x00_is_soc(rt2x00dev)) ++ if (!test_bit(DRIVER_REQUIRE_MCU, &rt2x00dev->flags)) + return; + + mutex_lock(&rt2x00dev->csr_mutex); +--- a/drivers/net/wireless/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -60,6 +60,12 @@ static void rt2800pci_mcu_status(struct + unsigned int i; + u32 reg; + ++ /* ++ * some devices don't support MCU requests. ++ */ ++ if (!test_bit(DRIVER_REQUIRE_MCU, &rt2x00dev->flags)) ++ return; ++ + for (i = 0; i < 200; i++) { + rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); + +@@ -1098,10 +1104,12 @@ static int rt2800pci_probe_hw(struct rt2 + __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); + + /* +- * This device requires firmware. ++ * This device requires firmware and MCU access. + */ +- if (!rt2x00_is_soc(rt2x00dev)) ++ if (!rt2x00_is_soc(rt2x00dev)){ + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); ++ __set_bit(DRIVER_REQUIRE_MCU, &rt2x00dev->flags); ++ } + __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); + if (!modparam_nohwcrypt) +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -631,6 +631,7 @@ enum rt2x00_flags { + * Driver requirements + */ + DRIVER_REQUIRE_FIRMWARE, ++ DRIVER_REQUIRE_MCU, + DRIVER_REQUIRE_BEACON_GUARD, + DRIVER_REQUIRE_ATIM_QUEUE, + DRIVER_REQUIRE_DMA, From 7a7089f7e394f1d8e4a81e417333f5543c1b4ab8 Mon Sep 17 00:00:00 2001 From: hauke Date: Thu, 1 Apr 2010 17:27:59 +0000 Subject: [PATCH 43/45] brcm-2.4: fix commit r18413 "128MB ram problem" This was missing in commit r20072 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20651 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../brcm-2.4/files/arch/mips/bcm947xx/prom.c | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/prom.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/prom.c index f635b4a6c..c9745746c 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/prom.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/prom.c @@ -21,25 +21,32 @@ void __init prom_init(int argc, const char **argv) { unsigned long mem; + unsigned long max; mips_machgroup = MACH_GROUP_BRCM; mips_machtype = MACH_BCM947XX; - /* Figure out memory size by finding aliases */ + /* Figure out memory size by finding aliases + * + * BCM47XX uses 128MB for addressing the ram, if the system contains + * less that that amount of ram it remaps the ram more often into the + * available space. + * Accessing memory after 128MB will cause an exception. + * max contains the biggest possible address supported by the platform. + * If the method wants to try something above we assume 128MB ram. + */ + max = ((unsigned long)(prom_init) | ((128 << 20) - 1)); for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { + if (((unsigned long)(prom_init) + mem) > max) { + mem = (128 << 20); + printk("assume 128MB RAM\n"); + break; + } if (*(unsigned long *)((unsigned long)(prom_init) + mem) == *(unsigned long *)(prom_init)) break; } - /* Ignoring the last page when ddr size is 128M. Cached - * accesses to last page is causing the processor to prefetch - * using address above 128M stepping out of the ddr address - * space. - */ - if (mem == 0x8000000) - mem -= 0x1000; - add_memory_region(0, mem, BOOT_MEM_RAM); } From 58dcac852ce0140f7f7134a2d7d2dddaae2bdc80 Mon Sep 17 00:00:00 2001 From: florian Date: Thu, 1 Apr 2010 21:20:43 +0000 Subject: [PATCH 44/45] [brcm63xx] flashmap and image generation: reduced union bcm_tag to a single struct combining the elements so that it is no longer necessary to create an openwrt-only tagid and tagcrc, and elimate the tagid detection and switch statements which made dealing with imagetags overly complicated, especially since the logic would need analogs in all code that touched the imagetag. Patch from cshore. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20652 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../mips/include/asm/mach-bcm63xx/bcm_tag.h | 219 +++--------- target/linux/brcm63xx/image/Makefile | 98 +++--- .../brcm63xx/image/README.images-bcm63xx | 91 +++-- .../040-bcm963xx_flashmap.patch | 211 +++--------- tools/firmware-utils/src/imagetag.c | 320 +++++------------- 5 files changed, 263 insertions(+), 676 deletions(-) diff --git a/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h b/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h index c06f66894..d79256272 100644 --- a/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h +++ b/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h @@ -1,178 +1,69 @@ #ifndef __BCM63XX_TAG_H #define __BCM63XX_TAG_H -#define IMAGE_LEN 10 /* Length of Length Field */ -#define ADDRESS_LEN 12 /* Length of Address field */ -#define TAGID_LEN 6 /* Length of tag ID */ -#define TAGINFO_LEN 20 /* Length of vendor information field in tag */ #define TAGVER_LEN 4 /* Length of Tag Version */ #define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */ +#define SIG1_LEN 20 /* Company Signature 1 Length */ +#define SIG2_LEN 14 /* Company Signature 2 Lenght */ +#define BOARDID_LEN 16 /* Length of BoardId */ +#define ENDIANFLAG_LEN 2 /* Endian Flag Length */ +#define CHIPID_LEN 6 /* Chip Id Length */ +#define IMAGE_LEN 10 /* Length of Length Field */ +#define ADDRESS_LEN 12 /* Length of Address field */ +#define DUALFLAG_LEN 2 /* Dual Image flag Length */ +#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */ +#define RSASIG_LEN 20 /* Length of RSA Signature in tag */ +#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */ +#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */ +#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */ +#define CRC_LEN 4 /* Length of CRC in bytes */ +#define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */ -#define NUM_TAGID 5 +#define NUM_PIRELLI 2 #define IMAGETAG_CRC_START 0xFFFFFFFF -struct tagiddesc_t { - char tagid[TAGID_LEN + 1]; - char tagiddesc[80]; -}; - - // bc221 is used by BT Voyager and should be right - // bc310 should be right, and may apply to 3.08 code as well -#define TAGID_DEFINITIONS { \ - { "bccfe", "Broadcom CFE flash image" }, \ - { "bc300", "Broadcom code version 3.00-3.06 and all ftp/tftp flash" }, \ - { "ag306", "Alice Gate (Pirelli, based on Broadcom 3.06)" }, \ - { "bc221", "Broadcom code version 2.21" }, \ - { "bc310", "Broadcom code version 3.10-3.12" }, \ +#define PIRELLI_BOARDS { \ + "AGPF_S0", \ + "DWV_SO", \ } -struct bcm_tag_bccfe { - unsigned char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char rootAddress[ADDRESS_LEN]; // 94-105: Address in memory of rootfs - unsigned char rootLength[IMAGE_LEN]; // 106-115: Size of rootfs - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present - unsigned char tagId[TAGID_LEN]; // 162-167: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced - unsigned char tagIdCRC[4]; // 168-171: CRC32 of tagId - unsigned char reserved1[44]; // 172-215: Reserved area not in use - unsigned char imageCRC[4]; // 216-219: CRC32 of images - unsigned char reserved2[16]; // 220-235: Unused at present - unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion - unsigned char reserved3[16]; // 240-255: Unused at present -}; +/* + * The broadcom firmware assumes the rootfs starts the image, + * therefore uses the rootfs start (flashImageAddress) + * to determine where to flash the image. Since we have the kernel first + * we have to give it the kernel address, but the crc uses the length + * associated with this address (rootLength), which is added to the kernel + * length (kernelLength) to determine the length of image to flash and thus + * needs to be rootfs + deadcode (jffs2 EOF marker) +*/ -struct bcm_tag_bc300 { - unsigned char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image) - unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image) - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present - unsigned char tagId[TAGID_LEN]; // 162-167: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced - unsigned char tagIdCRC[4]; // 168-173: CRC32 to ensure validity of tagId - unsigned char rootAddress[ADDRESS_LEN]; // 174-183: Address in memory of rootfs partition - unsigned char rootLength[IMAGE_LEN]; // 184-193: Size of rootfs partition - unsigned char reserved1[22]; // 194-215: Reserved area not in use - unsigned char imageCRC[4]; // 216-219: CRC32 of images - unsigned char reserved2[16]; // 220-235: Unused at present - unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion - unsigned char reserved3[16]; // 240-255: Unused at present -}; - -struct bcm_tag_ag306 { - unsigned char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image) - unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image) - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present - unsigned char information2[54]; // 162-215: Compilation and related information (not generated/used by OpenWRT) - unsigned char kernelCRC[4] ; // 216-219: CRC32 of images - unsigned char rootAddress[ADDRESS_LEN]; // 220-231: Address in memory of rootfs partition - unsigned char tagIdCRC[4]; // 232-235: Checksum to ensure validity of tagId - unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion - unsigned char rootLength[IMAGE_LEN]; // 240-249: Size of rootfs - unsigned char tagId[TAGID_LEN]; // 250-255: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced -}; - -struct bcm_tag_bc221 { - unsigned char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image) - unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image) - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char rsa_signature[TAGINFO_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this) - unsigned char reserved5[2]; // 162-163: Unused at present - unsigned char tagId[TAGID_LEN]; // 164-169: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced - unsigned char rootAddress[ADDRESS_LEN]; // 170-181: Address in memory of rootfs partition - unsigned char rootLength[IMAGE_LEN]; // 182-191: Size of rootfs partition - unsigned char flashLayoutVer[4]; // 192-195: Version flash layout - unsigned char fskernelCRC[4]; // 196-199: Guessed to be kernel CRC - unsigned char reserved4[16]; // 200-215: Reserved area; unused at present - unsigned char imageCRC[4]; // 216-219: CRC32 of images - unsigned char reserved2[12]; // 220-231: Unused at present - unsigned char tagIdCRC[4]; // 232-235: CRC32 to ensure validity of tagId - unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion - unsigned char reserved3[16]; // 240-255: Unused at present -}; - -struct bcm_tag_bc310 { - unsigned char tagVersion[4]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image) - unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image) - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present; Some vendors use this for optional information - unsigned char tagId[6]; // 162-167: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced - unsigned char tagIdCRC[4]; // 168-171: CRC32 to ensure validity of tagId - unsigned char rootAddress[ADDRESS_LEN]; // 172-183: Address in memory of rootfs partition - unsigned char rootLength[IMAGE_LEN]; // 184-193: Size of rootfs partition - unsigned char reserved1[22]; // 193-215: Reserved area not in use - unsigned char imageCRC[4]; // 216-219: CRC32 of images - unsigned char rootfsCRC[4]; // 220-227: CRC32 of rootfs partition - unsigned char kernelCRC[4]; // 224-227: CRC32 of kernel partition - unsigned char reserved2[8]; // 228-235: Unused at present - unsigned char headerCRC[4]; // 235-239: CRC32 of header excluding tagVersion - unsigned char reserved3[16]; // 240-255: Unused at present -}; - -union bcm_tag { - struct bcm_tag_bccfe bccfe; - struct bcm_tag_bc300 bc300; - struct bcm_tag_ag306 ag306; - struct bcm_tag_bc221 bc221; - struct bcm_tag_bc310 bc310; +struct bcm_tag { + char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag + char sig_1[SIG1_LEN]; // 4-23: Company Line 1 + char sig_2[SIG2_LEN]; // 24-37: Company Line 2 + char chipid[CHIPID_LEN]; // 38-43: Chip this image is for + char boardid[BOARDID_LEN]; // 44-59: Board name + char big_endian[ENDIANFLAG_LEN]; // 60-61: Map endianness -- 1 BE 0 LE + char totalLength[IMAGE_LEN]; // 62-71: Total length of image + char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE + char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE + char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of image start (kernel for OpenWRT, rootfs for stock firmware) + char rootLength[IMAGE_LEN]; // 106-115: Size of rootfs + char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel + char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel + char dualImage[DUALFLAG_LEN]; // 138-139: Unused at present + char inactiveFlag[INACTIVEFLAG_LEN]; // 140-141: Unused at present + char rsa_signature[RSASIG_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this) + char information1[TAGINFO1_LEN]; // 162-191: Compilation and related information (not generated/used by OpenWRT) + char flashLayoutVer[FLASHLAYOUTVER_LEN];// 192-195: Version flash layout + char fskernelCRC[CRC_LEN]; // 196-199: kernel+rootfs CRC32 + char information2[TAGINFO2_LEN]; // 200-215: Unused at present except Alice Gate where is is information + char imageCRC[CRC_LEN]; // 216-219: CRC32 of image less imagetag (kernel for Alice Gate) + char rootfsCRC[CRC_LEN]; // 220-223: CRC32 of rootfs partition + char kernelCRC[CRC_LEN]; // 224-227: CRC32 of kernel partition + char reserved1[8]; // 228-235: Unused at present + char headerCRC[CRC_LEN]; // 236-239: CRC32 of header excluding tagVersion + char reserved2[16]; // 240-255: Unused at present }; #endif /* __BCM63XX_TAG_H */ diff --git a/target/linux/brcm63xx/image/Makefile b/target/linux/brcm63xx/image/Makefile index 5d17c2baf..f7d1473ad 100644 --- a/target/linux/brcm63xx/image/Makefile +++ b/target/linux/brcm63xx/image/Makefile @@ -30,9 +30,9 @@ endef define Image/Build/CFE # Generate the tagged image $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \ - -o $(BIN_DIR)/openwrt-$(2)-$(1)-$(6)-cfe.bin \ + -o $(BIN_DIR)/openwrt-$(4)-$(1)-cfe.bin \ -b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \ - -t $(4) -d "$(5)" $(7) + -r "$(5)" $(6) # -b $(2) -c $(3) -e $(KERNEL_ENTRY) -l $(LOADADDR) endef @@ -40,17 +40,17 @@ endef define Image/Build/CFEAGPF # Generate the tagged image $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \ - -o $(BIN_DIR)/openwrt-$(2)-$(1)-$(7)-cfe.bin \ + -o $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \ -b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \ - -v 8 -m IMAGE -k 0x20000 -n $(4) -t $(5) + -v 8 -m IMAGE -k 0x20000 -n $(4) endef define Image/Build/RG100A # Generate the tagged image $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \ - -o $(BIN_DIR)/openwrt-$(6)-$(1)-$(7)-cfe.bin \ + -o $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \ -b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \ - -k 0x20000 -n $(4) -t $(5) + -k 0x20000 -n $(4) endef @@ -105,84 +105,70 @@ endef define Image/Build dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/openwrt-$(BOARD)-root.$(1) bs=128k conv=sync # Various routers - $(call Image/Build/CFE,$(1),96345GW2,6345,bccfe,,bccfe,) - $(call Image/Build/CFE,$(1),96345GW2,6345,bc221,,bc221,-y 5) - $(call Image/Build/CFE,$(1),96345GW2,6345,bc300,,bc300,) - $(call Image/Build/CFE,$(1),96345GW2,6345,bc310,OpenWRT-$(REVISION),bc310,) - $(call Image/Build/CFE,$(1),96348GW,6348,bccfe,,bccfe,) - $(call Image/Build/CFE,$(1),96348GW,6348,bc221,,bc221,-y 5) + $(call Image/Build/CFE,$(1),96345GW2,6345,96345GW2-generic) + $(call Image/Build/CFE,$(1),96345GW2,6345,96348GW2-bc221,,-y 5) + $(call Image/Build/CFE,$(1),96345GW2,6345,92345GW2-revision,OpenWRT-$(REVISION)) + $(call Image/Build/CFE,$(1),96348GW,6348,96348GW-generic,,) + $(call Image/Build/CFE,$(1),96348GW,6348,96348GW-bc221,,-y 5) + $(call Image/Build/CFE,$(1),6338GW,6338,6338GW-generic,,) + $(call Image/Build/CFE,$(1),6338W,6338,6338W-generic,,) + # BT Voyager V210_BTR - $(call Image/Build/CFE,$(1),V210_BB,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V210_BB,6348,BTV210_BTR,,-y 5) # BT Voyager V210_ROI, V210_WB - $(call Image/Build/CFE,$(1),V210,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V210,6348,BTV210_ROI_WB,,-y 5) # BT Voyager V2091_BTR - $(call Image/Build/CFE,$(1),V2091_BB,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V2091_BB,6348,BTV2091_BTR,,y 5) # BT Voyager V2091_ROI, V2091_WB - $(call Image/Build/CFE,$(1),V2091,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V2091,6348,BTV2091_ROI_WB,,-y 5) # BT Voyager V220V, V220V_MGCP_BTR - $(call Image/Build/CFE,$(1),RTA1052V,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),RTA1052V,6348,BTV220V_MGCP_BTR,,-y 5) # BT Voyager V2110, V2110_AA, V2110_ROI - $(call Image/Build/CFE,$(1),V2110,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V2110,6348,BTV2110,,-y 5) # BT Voyager V2500V, V2500V_SIP_CLUB, V2500V_AA - $(call Image/Build/CFE,$(1),V2500V_BB,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V2500V_BB,6348,BTV2500V,,-y 5) # RTA1025W_16 (numerous routers) - $(call Image/Build/CFE,$(1),RTA1025W_16,6348,bc221,,btrta,-y 5) + $(call Image/Build/CFE,$(1),RTA1025W_16,6348,RTA1025W_16,,-y 5) # Tecom GW6000 - $(call Image/Build/CFE,$(1),96348GW,6348,bc300,,bc300,) + $(call Image/Build/CFE,$(1),96348GW,6348,GW6000) # Tecom GW6200 - $(call Image/Build/CFE,$(1),96348GW,6348,bc310,$(shell printf '\x99'),gw6200) + $(call Image/Build/CFE,$(1),96348GW,6348,GW6200,$(shell printf '\x99')) # Neufbox4 - $(call Image/Build/CFE,$(1),96358VW,6358,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),96358VW,6358,bc310,OpenWRT-$(REVISION),nb4) + $(call Image/Build/CFE,$(1),96358VW,6358,NEUFBOX4,OpenWRT-$(REVISION)) # Comtrend 536, 5621 - $(call Image/Build/CFE,$(1),96348GW-11,6348,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),96348GW-11,6348,bc300,,bc300) - # TP-Link 8900GB - $(call Image/Build/CFE,$(1),96348GW-11,6348,bc310,$(shell printf 'PRID\x89\x10\x00\x02'),td8900GB) + $(call Image/Build/CFE,$(1),96348GW-11,6348,CT536_CT5621) # Davolink DV201AMR $(call Image/Build/CFEOLD,$(1),DV201AMR,6348) # USR 9108 - $(call Image/Build/CFE,$(1),96348GW-A,6348,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),96348GW-A,6348,bc300,,bc300) + $(call Image/Build/CFE,$(1),96348GW-A,6348,USR9108) # NetGear DG834GT, DG834PN - $(call Image/Build/CFE,$(1),96348GW-10,6348,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),96348GW-10,6348,bc300,,bc300) + $(call Image/Build/CFE,$(1),96348GW-10,6348,DG834GT_DG834PN) # Belkin f5d7633 - $(call Image/Build/CFE,$(1),96348GW-10,6348,bc310,,bc310) + $(call Image/Build/CFE,$(1),96348GW-10,6348,F5D7633) # D-Link DSL-2640B - $(call Image/Build/CFE,$(1),D-4P-W,6348,bc310,,bc310) + $(call Image/Build/CFE,$(1),D-4P-W,6348,DSL2640B) + # D-Link DSL-2740B + $(call Image/Build/CFE,$(1),96358GW,6358,DSL2740B) # TP-Link TD-8810A, TD-8810B, TD-8811A, TD-8811B - $(call Image/Build/CFE,$(1),8L-2M-8M,6338,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),8L-2M-8M,6338,bc300,,bc300) - - # Generic 6338 images - $(call Image/Build/CFE,$(1),6338GW,6338,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),6338GW,6338,bc221,,bc221) - $(call Image/Build/CFE,$(1),6338GW,6338,bc300,,bc300) - $(call Image/Build/CFE,$(1),6338GW,6338,bc310,,bc310) - $(call Image/Build/CFE,$(1),6338W,6338,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),6338W,6338,bc221,,bc221) - $(call Image/Build/CFE,$(1),6338W,6338,bc300,,bc300) - $(call Image/Build/CFE,$(1),6338W,6338,bc310,,bc310) + $(call Image/Build/CFE,$(1),8L-2M-8M,6338,TP8810_8811) + # TP-Link 8900GB + $(call Image/Build/CFE,$(1),96348GW-11,6348,TD8900GB,$(shell printf 'PRID\x89\x10\x00\x02')) # Sagem F@ST2404 - $(call Image/Build/CFE,$(1),F@ST2404,6348,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),F@ST2404,6348,bc300,,bc300) - $(call Image/Build/CFE,$(1),F@ST2404,6348,bc310,OpenWRT-$(REVISION),bc310) + $(call Image/Build/CFE,$(1),F@ST2404,6348,F@ST2404-cfe) + $(call Image/Build/CFE,$(1),F@ST2404,6348,F@ST2404,OpenWRT-$(REVISION)) # Inventel Livebox $(call Image/Build/RedBoot,livebox) - # D-Link DSL-2740B - $(call Image/Build/CFE,$(1),96358GW,6358,bc310,,dsl2740b) # Pirelli Alice Gate VoIP 2 Plus Wi-Fi AGPF-S0 - $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,bccfe,,bccfe) - $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,ag306,,agv2+w) + $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,AGV2+W-cfe) + $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,AGV2+W) # Pirelli A226G - $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,bccfe,,bccfe) - $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,ag306,DWV_96358,a226g) + $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,A226G-cfe) + $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,A226G) # RG100A,DB120 etc. - $(call Image/Build/RG100A,$(1),96358VW2,6358,0x20000,bc310,rg100a,bc310) + $(call Image/Build/RG100A,$(1),96358VW2,6358,0x20000,RG100A_DB120) endef diff --git a/target/linux/brcm63xx/image/README.images-bcm63xx b/target/linux/brcm63xx/image/README.images-bcm63xx index 9cf05743a..91b6d019e 100644 --- a/target/linux/brcm63xx/image/README.images-bcm63xx +++ b/target/linux/brcm63xx/image/README.images-bcm63xx @@ -16,6 +16,11 @@ Images flashable using cfe are labelled openwrt---cfe.bin The imagetags for tftp/ftp flashing is based on Broadcom 3.00-3.04 imagetags and is known to be correct as the source code GPL and is available for reading. +Broadcom code 2.21 is based on the BT Voyager firmware image I looked at. It +may in fact be BT Voyager-specific. 2.21 is actually more difficult to deal +with the imagetag from 3.00 as it has three different CRC calculations in +addtition to the header CRC. + Broadcom 3.00-3.02 flashing has been tested on Comtrend CT-5261, CT-536 and Tecom GW6000, and is the version of the flashing that was present before the imagetags were split by broadcom code version (early June 2009) @@ -27,16 +32,11 @@ this author (Daniel Dickinson) has seen is the Alice Gate (Pirelli) firmware which is known to be different due to vendor (Pirelli) modifications to the Broadcom code. -Broadcom 3.08 introduced changes to the imagetag to deal with TR69 (a remote -router management system developed by the DSL Forum). The version we are -using as 3.08 is based on the BT Voyager firmware image I looked at. It may -in fact be BT Voyager-specific, and may in fact not be 3.08, but modified 3.06 -and not apply to all 3.08 versions. - Broadcom 3.10 uses an imagetag that is believed to apply to all 3.10 and 3.12 -versions, and has been tested on the Tecom GW6200. It is similar to 3.08. -There is a field for vendor-specific information, that at least in some cases -is not optional. It is based on the hexedit of a neufbox4 firmware image, the +versions, and has been tested on the Tecom GW6200. This version introdec changes to +the imagetag to deal with TR69 (a remote rouer management system developed by the +DSL forum). There is a field for vendor-specific information, that at least in some +cases is not optional. It is based on the hexedit of a neufbox4 firmware image, the information in https://dev.openwrt.org/ticket/4987, and the hexedit of a Tecom GW6200 image. @@ -44,43 +44,41 @@ Some boards share the same tag format, but require vendor-specific fields in the board. In that case the tagid is shared, but the filename of the generated image reflects the router for which the image was created. -router |method| codever |tagid |filename -+-------------+------+---------+------+---------------------------------------- -|any |cfe | any |bccfe |openwrt---bccfe-cfe.bin -|any |t/ftp | any |bc300 |openwrt---bc300-cfe.bin -| |web |3.00-3.06|bc300 |openwrt---bc300-cfe.bin -| |web |3.10-3.12|bc310 |openwrt---bc310-cfe.bin -|AGVoIP2+WiFi |web |alice3.06|ag306 |openwrt-AGPF-S0--agv2+w-cfe.bin -|CT536 |web |3.02 |bc300 |openwrt-96348GW-11--bc300-cfe.bin -|CT5621 |web |3.02 |bc300 |openwrt-96348GW-11--bc300-cfe.bin -|DG834GT |web |3.02 |bc300 |openwrt-96348GW-10--bc300-cfe.bin -|DG834PN |web |3.02 |bc300 |openwrt-96348GW-10--bc300-cfe.bin -|DSL-2640B |web |3.10 |bc310 |openwrt-D-4P-W--bc310-cfe.bin -|DSL-2740B |web |3.10 |bc310 |openwrt-96358GW--dsl2740b-cfe.bin -|F5D7633 |web |3.10 |bc310 |openwrt-96348GW-10--bc310-cfe.bin -|F@ST2404 |web |? |bc300 |openwrt-F@ST2404--bc300-cfe.bin -|F@ST2404 |web |? |bc310 |openwrt-F@ST2404--bc310-cfe.bin -|GW6000 |web |3.00 |bc300 |openwrt-96348GW--bc300-cfe.bin -|GW6200 |web |3.10 |bc310 |openwrt-96348GW--gw6200-cfe.bin -|Neufbox4 |web |3.12 |bc310 |openwrt-96358VW--nb4-cfe.bin -|TD8810A |web |3.06 |bc300 |openwrt-8L-2M-8M--bc306-cfe.bin -|TD8810B |web |3.06 |bc300 |openwrt-8L-2M-8M--bc306-cfe.bin -|TD8811A |web |3.06 |bc300 |openwrt-8L-2M-8M--bc306-cfe.bin -|TD8811B |web |3.06 |bc300 |openwrt-8L-2M-8M--bc306-cfe.bin -|TD8900GB |web |3.06 |bc300 |openwrt-96348GW-11--td8900gb-cfe.bin -|USR9108 |web |? |bc300 |openwrt-96348GW-A--bc300-cfe.bin -|V2091_BTR |web |2.21 |bc221 |openwrt-V2091_BB--btvgr-cfe.bin -|V2091_ROI |web |2.21 |bc221 |openwrt-V2091--btvgr-cfe.bin -|V2091_WB |web |2.21 |bc221 |openwrt-V2091--btvgr-cfe.bin -|V210_BTR |web |2.21 |bc221 |openwrt-V210_BB--btvgr-cfe.bin -|V210_ROI |web |2.21 |bc221 |openwrt-V210--btvgr-cfe.bin -|V210_WB |web |2.21 |bc221 |openwrt-V210--btvgr-cfe.bin -|V2110 |web |2.21 |bc221 |openwrt-V2110--btvgr-cfe.bin -|V2110_AA |web |2.21 |bc221 |openwrt-V2110--btvgr-cfe.bin -|V2110_ROI |web |2.21 |bc221 |openwrt-V2110--btvgr-cfe.bin -|V2500V |web |2.21 |bc221 |openwrt-V2500V_BB--btvgr-cfe.bin -|V2500V_AA |web |2.21 |bc221 |openwrt-V2500V_BB--btvgr-cfe.bin -|V2500V_SIP_CLUB |web|2.21 |bc221 |openwrt-V2500V_BB--btvgr-cfe.bin +router |method | codever |filename ++-------------+-------------+---------+--------------------------------------- +|any |cfe+most web | any |openwrt---cfe.bin +|AGVoIP2+WiFi |cfe |alice3.06|openwrt-AGV2+W-cfe--cfe.bin +|AGVoIP2+WiFi |web |alice3.06|openwrt-AGV2+W-cfe--cfe.bin +|CT536 |web |3.02 |openwrt-CT536_CT5621--cfe.bin +|CT5621 |web |3.02 |openwrt-CT536_CT5621--cfe.bin +|DG834GT |web |3.02 |openwrt-DG834GT_DG834PN--cfe.bin +|DG834PN |web |3.02 |openwrt-DG834GT_DG834PN--cfe.bin +|DSL-2640B |web |3.10 |openwrt-DSL2640B--cfe.bin +|DSL-2740B |web |3.10 |openwrt-DSL2670B--cfe.bin +|F5D7633 |web |3.10 |openwrt-F5D7633--cfe.bin +|F@ST2404 |web |3.0X? |openwrt-F@ST2404-cfe--cfe.bin +|F@ST2404 |web |3.1X? |openwrt-F@ST2404--cfe.bin +|GW6000 |web |3.00 |openwrt-GW6000--cfe.bin +|GW6200 |web |3.10 |openwrt-GW6200--cfe.bin +|Neufbox4 |web |3.12 |openwrt-NEUFBOX4--cfe.bin +|TD8810A |web |3.06 |openwrt-TD8810--cfe.bin +|TD8810B |web |3.06 |openwrt-TD8810--cfe.bin +|TD8811A |web |3.06 |openwrt-TD8811--cfe.bin +|TD8811B |web |3.06 |openwrt-TD881--cfe.bin +|TD8900GB |web |3.06 |openwrt-TD8900DB-cfe.bin +|USR9108 |web |3.0X? |openwrt-USR9108--cfe.bin +|V2091_BTR |web |2.21 |openwrt-V2091_BTR--cfe.bin +|V2091_ROI |web |2.21 |openwrt-V2091--cfe.bin +|V2091_WB |web |2.21 |openwrt-V2091--cfe.bin +|V210_BTR |web |2.21 |openwrt-V210_BTR--cfe.bin +|V210_ROI |web |2.21 |openwrt-V210-ROI_WB-cfe.bin +|V210_WB |web |2.21 |openwrt-V210-ROI_WB-cfe.bin +|V2110 |web |2.21 |openwrt-V2110--cfe.bin +|V2110_AA |web |2.21 |openwrt-V2110--cfe.bin +|V2110_ROI |web |2.21 |openwrt-V2110--cfe.bin +|V2500V |web |2.21 |openwrt-V2500V-cfe.bin +|V2500V_AA |web |2.21 |openwrt-V2500V--cfe.bin +|V2500V_SIP_CLUB |web |2.21 |openwrt-V2500V--cfe.bin Old imagetag routers -------------------- @@ -126,3 +124,4 @@ TP-Link |TD-W8900GB |3.06 Tecom |GW6000 |3.00 Tecom |GW6200 |3.10 USR |9108 |? + diff --git a/target/linux/brcm63xx/patches-2.6.32/040-bcm963xx_flashmap.patch b/target/linux/brcm63xx/patches-2.6.32/040-bcm963xx_flashmap.patch index 556e8cb85..117074b99 100644 --- a/target/linux/brcm63xx/patches-2.6.32/040-bcm963xx_flashmap.patch +++ b/target/linux/brcm63xx/patches-2.6.32/040-bcm963xx_flashmap.patch @@ -11,9 +11,11 @@ Signed-off-by: Axel Gembe drivers/mtd/redboot.c | 13 ++++++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) ---- a/drivers/mtd/maps/Kconfig -+++ b/drivers/mtd/maps/Kconfig -@@ -259,6 +259,13 @@ config MTD_ALCHEMY +Index: linux-2.6.32.10/drivers/mtd/maps/Kconfig +=================================================================== +--- linux-2.6.32.10.orig/drivers/mtd/maps/Kconfig 2010-03-29 06:35:59.987293878 -0400 ++++ linux-2.6.32.10/drivers/mtd/maps/Kconfig 2010-03-29 06:37:14.968545954 -0400 +@@ -259,6 +259,13 @@ help Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards @@ -27,9 +29,11 @@ Signed-off-by: Axel Gembe config MTD_DILNETPC tristate "CFI Flash device mapped on DIL/Net PC" depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN ---- a/drivers/mtd/redboot.c -+++ b/drivers/mtd/redboot.c -@@ -39,7 +39,7 @@ static inline int redboot_checksum(struc +Index: linux-2.6.32.10/drivers/mtd/redboot.c +=================================================================== +--- linux-2.6.32.10.orig/drivers/mtd/redboot.c 2010-03-29 06:36:00.017292877 -0400 ++++ linux-2.6.32.10/drivers/mtd/redboot.c 2010-03-29 06:37:14.968545954 -0400 +@@ -39,7 +39,7 @@ return 1; } @@ -38,7 +42,7 @@ Signed-off-by: Axel Gembe struct mtd_partition **pparts, unsigned long fis_origin) { -@@ -162,6 +162,14 @@ static int parse_redboot_partitions(stru +@@ -162,6 +162,14 @@ goto out; } @@ -53,7 +57,7 @@ Signed-off-by: Axel Gembe for (i = 0; i < numslots; i++) { struct fis_list *new_fl, **prev; -@@ -184,9 +192,8 @@ static int parse_redboot_partitions(stru +@@ -184,9 +192,8 @@ new_fl->img = &buf[i]; if (fis_origin) { buf[i].flash_base -= fis_origin; @@ -64,16 +68,20 @@ Signed-off-by: Axel Gembe /* I'm sure the JFFS2 code has done me permanent damage. * I now think the following is _normal_ ---- a/drivers/mtd/maps/Makefile -+++ b/drivers/mtd/maps/Makefile -@@ -61,3 +61,4 @@ obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-asy +Index: linux-2.6.32.10/drivers/mtd/maps/Makefile +=================================================================== +--- linux-2.6.32.10.orig/drivers/mtd/maps/Makefile 2010-03-29 06:35:59.947294290 -0400 ++++ linux-2.6.32.10/drivers/mtd/maps/Makefile 2010-03-29 06:37:14.968545954 -0400 +@@ -61,3 +61,4 @@ obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o obj-$(CONFIG_MTD_VMU) += vmu-flash.o obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o +obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o ---- /dev/null -+++ b/drivers/mtd/maps/bcm963xx-flash.c -@@ -0,0 +1,399 @@ +Index: linux-2.6.32.10/drivers/mtd/maps/bcm963xx-flash.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.32.10/drivers/mtd/maps/bcm963xx-flash.c 2010-03-29 13:33:58.797288897 -0400 +@@ -0,0 +1,266 @@ +/* + * Copyright (C) 2006-2008 Florian Fainelli + * Mike Albon @@ -119,179 +127,46 @@ Signed-off-by: Axel Gembe + .bankwidth = BUSWIDTH, +}; + -+static struct tagiddesc_t tagidtab[NUM_TAGID] = TAGID_DEFINITIONS; -+ -+static uint32_t tagcrc32tab[256] = { -+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, -+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, -+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, -+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, -+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, -+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, -+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, -+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, -+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, -+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, -+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, -+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, -+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, -+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, -+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, -+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, -+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, -+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, -+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, -+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, -+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, -+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, -+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, -+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, -+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, -+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, -+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, -+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, -+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, -+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, -+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, -+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -+}; -+ -+static uint32_t tagcrc32(uint32_t crc, uint8_t *data, size_t len) -+{ -+ while (len--) -+ crc = (crc >> 8) ^ tagcrc32tab[(crc ^ *data++) & 0xFF]; -+ -+ return crc; -+} + +static int parse_cfe_partitions( struct mtd_info *master, struct mtd_partition **pparts) +{ + int nrparts = 3, curpart = 0; /* CFE,NVRAM and global LINUX are always present. */ -+ union bcm_tag *buf; ++ struct bcm_tag *buf; + struct mtd_partition *parts; + int ret; + size_t retlen; + unsigned int rootfsaddr, kerneladdr, spareaddr; + unsigned int rootfslen, kernellen, sparelen, totallen; -+ unsigned char *tagid; + int namelen = 0; + int i; -+ uint32_t tagidcrc; -+ uint32_t calctagidcrc; -+ bool tagid_match = false; + char *boardid; + char *tagversion; -+ char *matchtagid; + + /* Allocate memory for buffer */ -+ buf = vmalloc(sizeof(union bcm_tag)); ++ buf = vmalloc(sizeof(struct bcm_tag)); + if (!buf) + return -ENOMEM; + + /* Get the tag */ -+ ret = master->read(master,master->erasesize,sizeof(union bcm_tag), &retlen, (void *)buf); -+ if (retlen != sizeof(union bcm_tag)){ ++ ret = master->read(master,master->erasesize,sizeof(struct bcm_tag), &retlen, (void *)buf); ++ if (retlen != sizeof(struct bcm_tag)){ + vfree(buf); + return -EIO; + } + -+ /* tagId isn't in the same location, so we check each tagid against the -+ * tagid CRC. If the CRC is valid we have found the right tag and so -+ * use that tag -+ */ ++ sscanf(buf->kernelAddress, "%u", &kerneladdr); ++ sscanf(buf->kernelLength, "%u", &kernellen); ++ sscanf(buf->totalLength, "%u", &totallen); ++ tagversion = &(buf->tagVersion[0]); ++ boardid = &(buf->boardid[0]); + -+ for (i = 0; i < NUM_TAGID; i++) { -+ switch(i) { -+ case 0: -+ matchtagid = "bccfe"; -+ tagid = &(buf->bccfe.tagId[0]); -+ sscanf(buf->bccfe.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bccfe.rootLength, "%u", &rootfslen); -+ sscanf(buf->bccfe.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bccfe.kernelLength, "%u", &kernellen); -+ sscanf(buf->bccfe.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bccfe.tagIdCRC[0]); -+ tagversion = &(buf->bccfe.tagVersion[0]); -+ boardid = &(buf->bccfe.boardid[0]); -+ break; -+ case 1: -+ matchtagid = "bc300"; -+ tagid = &(buf->bc300.tagId[0]); -+ sscanf(buf->bc300.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bc300.rootLength, "%u", &rootfslen); -+ sscanf(buf->bc300.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bc300.kernelLength, "%u", &kernellen); -+ sscanf(buf->bc300.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bc300.tagIdCRC[0]); -+ tagversion = &(buf->bc300.tagVersion[0]); -+ boardid = &(buf->bc300.boardid[0]); -+ break; -+ case 2: -+ matchtagid = "ag306"; -+ tagid = &(buf->ag306.tagId[0]); -+ sscanf(buf->ag306.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->ag306.rootLength, "%u", &rootfslen); -+ sscanf(buf->ag306.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->ag306.kernelLength, "%u", &kernellen); -+ sscanf(buf->ag306.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->ag306.tagIdCRC[0]); -+ tagversion = &(buf->ag306.tagVersion[0]); -+ boardid = &(buf->ag306.boardid[0]); -+ break; -+ case 3: -+ matchtagid = "bc221"; -+ tagid = &(buf->bc221.tagId[0]); -+ sscanf(buf->bc221.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bc221.rootLength, "%u", &rootfslen); -+ sscanf(buf->bc221.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bc221.kernelLength, "%u", &kernellen); -+ sscanf(buf->bc221.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bc221.tagIdCRC[0]); -+ tagversion = &(buf->bc221.tagVersion[0]); -+ boardid = &(buf->bc221.boardid[0]); -+ break; -+ case 4: -+ matchtagid = "bc310"; -+ tagid = &(buf->bc310.tagId[0]); -+ sscanf(buf->bc310.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bc310.rootLength, "%u", &rootfslen); -+ sscanf(buf->bc310.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bc310.kernelLength, "%u", &kernellen); -+ sscanf(buf->bc310.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bc310.tagIdCRC[0]); -+ tagversion = &(buf->bc310.tagVersion[0]); -+ boardid = &(buf->bc310.boardid[0]); -+ break; -+ } -+ if (strncmp(tagid, matchtagid, TAGID_LEN) != 0) { -+ continue; -+ } ++ printk(KERN_INFO PFX "CFE boot tag found with version %s and board type %s\n",tagversion, boardid); + -+ calctagidcrc = htonl(tagcrc32(IMAGETAG_CRC_START, tagid, TAGID_LEN)); -+ if (tagidcrc == calctagidcrc) { -+ tagid_match = true; -+ break; -+ } -+ } -+ -+ if (!tagid_match) { -+ tagid = "bcram"; -+ sscanf(buf->bccfe.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bccfe.rootLength, "%u", &rootfslen); -+ sscanf(buf->bccfe.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bccfe.kernelLength, "%u", &kernellen); -+ sscanf(buf->bccfe.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bccfe.tagIdCRC[0]); -+ tagversion = &(buf->bccfe.tagVersion[0]); -+ boardid = &(buf->bccfe.boardid[0]); -+ } -+ -+ printk(KERN_INFO PFX "CFE boot tag found with version %s, board type %s, and tagid %s.\n",tagversion,boardid,tagid); -+ -+ rootfsaddr = rootfsaddr - EXTENDED_SIZE; + kerneladdr = kerneladdr - EXTENDED_SIZE; -+ spareaddr = roundup(totallen,master->erasesize) + master->erasesize; ++ rootfsaddr = kerneladdr + kernellen; ++ spareaddr = roundup(totallen, master->erasesize) + master->erasesize; + sparelen = master->size - spareaddr - master->erasesize; ++ rootfslen = spareaddr - rootfsaddr; + + /* Determine number of partitions */ + namelen = 8; @@ -342,9 +217,9 @@ Signed-off-by: Axel Gembe + parts[curpart].name = "linux"; + parts[curpart].offset = parts[0].size; + parts[curpart].size = master->size - parts[0].size - parts[3].size; -+ ++ + for (i = 0; i < nrparts; i++) -+ printk(KERN_INFO PFX "Partition %d is %s offset %lx and length %lx\n", i, parts[i].name, parts[i].offset, parts[i].size); ++ printk(KERN_INFO PFX "Partition %d is %s offset %lx and length %lx\n", i, parts[i].name, (long unsigned int)(parts[i].offset), (long unsigned int)(parts[i].size)); + + printk(KERN_INFO PFX "Spare partition is %x offset and length %x\n", spareaddr, sparelen); + *pparts = parts; @@ -375,7 +250,7 @@ Signed-off-by: Axel Gembe + char *part_type; + struct resource *r; + -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + bcm963xx_map.phys = r->start; + bcm963xx_map.size = (r->end - r->start) + 1; + bcm963xx_map.virt = ioremap(r->start, r->end - r->start + 1); @@ -473,9 +348,11 @@ Signed-off-by: Axel Gembe +MODULE_DESCRIPTION("Broadcom BCM63xx MTD partition parser/mapping for CFE and RedBoot"); +MODULE_AUTHOR("Florian Fainelli "); +MODULE_AUTHOR("Mike Albon "); ---- a/arch/mips/bcm63xx/boards/board_bcm963xx.c -+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -722,20 +722,6 @@ static int board_get_mac_address(u8 *mac +Index: linux-2.6.32.10/arch/mips/bcm63xx/boards/board_bcm963xx.c +=================================================================== +--- linux-2.6.32.10.orig/arch/mips/bcm63xx/boards/board_bcm963xx.c 2010-03-29 06:35:59.927292275 -0400 ++++ linux-2.6.32.10/arch/mips/bcm63xx/boards/board_bcm963xx.c 2010-03-29 06:37:35.178541753 -0400 +@@ -722,20 +722,6 @@ return 0; } @@ -496,7 +373,7 @@ Signed-off-by: Axel Gembe static struct resource mtd_resources[] = { { .start = 0, /* filled at runtime */ -@@ -745,12 +731,9 @@ static struct resource mtd_resources[] = +@@ -745,12 +731,9 @@ }; static struct platform_device mtd_dev = { diff --git a/tools/firmware-utils/src/imagetag.c b/tools/firmware-utils/src/imagetag.c index e93f5f45e..658674ec7 100644 --- a/tools/firmware-utils/src/imagetag.c +++ b/tools/firmware-utils/src/imagetag.c @@ -29,7 +29,7 @@ union int2char { uint32_t input; - unsigned char output[4]; + char output[4]; }; /* This appears to be necessary due to alignment issues */ @@ -43,7 +43,7 @@ struct kernelhdr { uint32_t lzmalen; /* Compressed length of the LZMA data that follows */ }; -static struct tagiddesc_t tagidtab[NUM_TAGID] = TAGID_DEFINITIONS; +static char pirellitab[NUM_PIRELLI][BOARDID_LEN] = PIRELLI_BOARDS; static uint32_t crc32tab[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, @@ -130,9 +130,9 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, const char *boardid, const char *chipid, const uint32_t fwaddr, const uint32_t loadaddr, const uint32_t entry, const char *ver, const char *magic2, const uint32_t flash_bs, - const char *tagid, const char *information, const char *layoutver) + const char *rsignature, const char *layoutver) { - union bcm_tag tag; + struct bcm_tag tag; struct kernelhdr khdr; FILE *kernelfile = NULL, *rootfsfile = NULL, *binfile; size_t kerneloff, kernellen, rootfsoff, rootfslen, read, imagelen, rootfsoffpadlen, kernelfslen; @@ -143,23 +143,26 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, uint32_t kernelfscrc = IMAGETAG_CRC_START; const uint32_t deadcode = htonl(DEADCODE); union int2char intchar; + int i; + int is_pirelli = 0; - memset(&tag, 0, sizeof(union bcm_tag)); + memset(&tag, 0, sizeof(struct bcm_tag)); - /* All imagetags have boardid in the same location and of the same - * size, so we just use the bccfe one - */ - if (strlen(boardid) >= sizeof(tag.bccfe.boardid)) { + if (strlen(boardid) >= sizeof(tag.boardid)) { fprintf(stderr, "Board id is too long!\n"); return 1; } /* Likewise chipid */ - if (strlen(chipid) >= sizeof(tag.bccfe.chipid)) { + if (strlen(chipid) >= sizeof(tag.chipid)) { fprintf(stderr, "Chip id is too long!\n"); return 1; } + if (!kernel || !rootfs) { + fprintf(stderr, "imagetag can't create an image without both kernel and rootfs\n"); + } + if (kernel && !(kernelfile = fopen(kernel, "rb"))) { fprintf(stderr, "Unable to open kernel \"%s\"\n", kernel); return 1; @@ -224,203 +227,70 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, */ fflush(binfile); - /* Choose and compute the CRC32 that should be inserted in the tag */ - if ( tagid && ( (strncmp(tagid, "bccfe", TAGID_LEN) == 0)) || ( strncmp(tagid, "bc300", TAGID_LEN) == 0)) { - /* Compute the crc32 of the entire image (deadC0de included) */ - imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen); - } else if ( tagid && (strncmp(tagid, "ag306", TAGID_LEN) == 0)) { - /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ - kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen); - } else if ( tagid && ( (strncmp(tagid, "bc221", TAGID_LEN) == 0))) { - /* Compute the crc32 of the entire image (deadC0de included) */ - imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen); - /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ - kernelfscrc = compute_crc32(kernelfscrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen + rootfslen + sizeof(deadcode)); - } else if ( tagid && (strncmp(tagid, "bc310", TAGID_LEN) == 0) ) { - /* Compute the crc32 of the entire image (deadC0de included) */ - imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen); - /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ - kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen); - /* Compute the crc32 of the flashImageStart to rootLength. - * The broadcom firmware assumes the rootfs starts the image, - * therefore uses the rootfs start to determine where to flash - * the image. Since we have the kernel first we have to give - * it the kernel address, but the crc uses the length - * associated with this address, which is added to the kernel - * length to determine the length of image to flash and thus - * needs to be rootfs + deadcode - */ - rootfscrc = compute_crc32(rootfscrc, binfile, kerneloff - fwaddr, rootfslen + sizeof(deadcode)); - } + /* Compute the crc32 of the entire image (deadC0de included) */ + imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen); + /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ + kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen); + /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ + kernelfscrc = compute_crc32(kernelfscrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen + rootfslen + sizeof(deadcode)); + /* Compute the crc32 of the flashImageStart to rootLength. + * The broadcom firmware assumes the rootfs starts the image, + * therefore uses the rootfs start to determine where to flash + * the image. Since we have the kernel first we have to give + * it the kernel address, but the crc uses the length + * associated with this address, which is added to the kernel + * length to determine the length of image to flash and thus + * needs to be rootfs + deadcode + */ + rootfscrc = compute_crc32(rootfscrc, binfile, kerneloff - fwaddr, rootfslen + sizeof(deadcode)); /* Close the files */ fclose(kernelfile); fclose(rootfsfile); - if ( tagid && (strcmp(tagid, "bccfe") == 0)) { - /* Build the tag */ - strncpy(tag.bccfe.tagVersion, ver, TAGVER_LEN); - strncpy(tag.bccfe.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bccfe.sig_1) - 1); - strncpy(tag.bccfe.sig_2, magic2, sizeof(tag.bccfe.sig_2) - 1); - strcpy(tag.bccfe.chipid, chipid); - strcpy(tag.bccfe.boardid, boardid); - strcpy(tag.bccfe.big_endian, "1"); - sprintf(tag.bccfe.totalLength, "%lu", imagelen); + /* Build the tag */ + strncpy(tag.tagVersion, ver, TAGVER_LEN); + strncpy(tag.sig_1, IMAGETAG_MAGIC1, sizeof(tag.sig_1) - 1); + strncpy(tag.sig_2, magic2, sizeof(tag.sig_2) - 1); + strcpy(tag.chipid, chipid); + strcpy(tag.boardid, boardid); + strcpy(tag.big_endian, "1"); + sprintf(tag.totalLength, "%lu", imagelen); - /* We don't include CFE */ - strcpy(tag.bccfe.cfeAddress, "0"); - strcpy(tag.bccfe.cfeLength, "0"); + /* We don't include CFE */ + strcpy(tag.cfeAddress, "0"); + strcpy(tag.cfeLength, "0"); - if (kernelfile) { - sprintf(tag.bccfe.kernelAddress, "%lu", kerneloff); - sprintf(tag.bccfe.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } + sprintf(tag.kernelAddress, "%lu", kerneloff); + sprintf(tag.kernelLength, "%lu", kernellen + rootfsoffpadlen); + sprintf(tag.flashImageStart, "%lu", kerneloff); + sprintf(tag.rootLength, "%lu", rootfslen + sizeof(deadcode)); - if (rootfsfile) { - sprintf(tag.bccfe.rootAddress, "%lu", rootfsoff); - sprintf(tag.bccfe.rootLength, "%lu", rootfslen); - } - - strncpy(tag.bccfe.tagId, "bccfe", TAGID_LEN); - - int2tag(tag.bccfe.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bccfe.tagId[0]), TAGID_LEN)); - int2tag(tag.bccfe.imageCRC, imagecrc); - int2tag(tag.bccfe.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); - } else if ( tagid && (strcmp(tagid, "bc300") == 0)) { - /* Build the tag */ - strncpy(tag.bc300.tagVersion, ver, TAGVER_LEN); - strncpy(tag.bc300.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bc300.sig_1) - 1); - strncpy(tag.bc300.sig_2, magic2, sizeof(tag.bc300.sig_2) - 1); - strcpy(tag.bc300.chipid, chipid); - strcpy(tag.bc300.boardid, boardid); - strcpy(tag.bc300.big_endian, "1"); - sprintf(tag.bc300.totalLength, "%lu", imagelen); - - /* We don't include CFE */ - strcpy(tag.bc300.cfeAddress, "0"); - strcpy(tag.bc300.cfeLength, "0"); - - if (kernelfile) { - sprintf(tag.bc300.kernelAddress, "%lu", kerneloff); - sprintf(tag.bc300.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } - - if (rootfsfile) { - sprintf(tag.bc300.flashImageStart, "%lu", kerneloff); - sprintf(tag.bc300.flashRootLength, "%lu", rootfslen + sizeof(deadcode)); - sprintf(tag.bc300.rootAddress, "%lu", rootfsoff); - sprintf(tag.bc300.rootLength, "%lu", rootfslen); - } - - strncpy(tag.bc300.tagId, "bc300", TAGID_LEN); - - int2tag(tag.bc300.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bc300.tagId[0]), TAGID_LEN)); - int2tag(tag.bc300.imageCRC, imagecrc); - int2tag(tag.bc300.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); - } else if ( tagid && (strcmp(tagid, "ag306") == 0)) { - /* Build the tag */ - strncpy(tag.ag306.tagVersion, ver, TAGVER_LEN); - strncpy(tag.ag306.sig_1, IMAGETAG_MAGIC1, sizeof(tag.ag306.sig_1) - 1); - strncpy(tag.ag306.sig_2, magic2, sizeof(tag.ag306.sig_2) - 1); - strcpy(tag.ag306.chipid, chipid); - strcpy(tag.ag306.boardid, boardid); - strcpy(tag.ag306.big_endian, "1"); - sprintf(tag.ag306.totalLength, "%lu", imagelen); - - /* We don't include CFE */ - strcpy(tag.ag306.cfeAddress, "0"); - strcpy(tag.ag306.cfeLength, "0"); - - if (kernelfile) { - sprintf(tag.ag306.kernelAddress, "%lu", kerneloff); - sprintf(tag.ag306.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } - - if (rootfsfile) { - sprintf(tag.ag306.flashImageStart, "%lu", kerneloff); - sprintf(tag.ag306.flashRootLength, "%lu", rootfslen + sizeof(deadcode)); - sprintf(tag.ag306.rootAddress, "%lu", rootfsoff); - sprintf(tag.ag306.rootLength, "%lu", rootfslen); - } - - strncpy(tag.ag306.tagId, "ag306", TAGID_LEN); - - int2tag(tag.ag306.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.ag306.tagId[0]), TAGID_LEN)); - int2tag(tag.ag306.kernelCRC, kernelcrc); - int2tag(tag.ag306.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); - } else if ( tagid && (strcmp(tagid, "bc221") == 0)) { - /* Build the tag */ - strncpy(tag.bc221.tagVersion, ver, TAGVER_LEN); - strncpy(tag.bc221.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bc221.sig_1) - 1); - strncpy(tag.bc221.sig_2, magic2, sizeof(tag.bc221.sig_2) - 1); - strcpy(tag.bc221.chipid, chipid); - strcpy(tag.bc221.boardid, boardid); - strcpy(tag.bc221.big_endian, "1"); - sprintf(tag.bc221.totalLength, "%lu", imagelen); - - /* We don't include CFE */ - strcpy(tag.bc221.cfeAddress, "0"); - strcpy(tag.bc221.cfeLength, "0"); - - if (kernelfile) { - sprintf(tag.bc221.kernelAddress, "%lu", kerneloff); - sprintf(tag.bc221.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } - - if (rootfsfile) { - sprintf(tag.bc221.flashImageStart, "%lu", kerneloff); - sprintf(tag.bc221.flashRootLength, "%lu", rootfslen + sizeof(deadcode)); - sprintf(tag.bc221.rootAddress, "%lu", rootfsoff); - sprintf(tag.bc221.rootLength, "%lu", rootfslen); - } - - strncpy(tag.bc221.tagId, "bc221", TAGID_LEN); - if (layoutver) { - strncpy(tag.bc221.flashLayoutVer, layoutver, TAGLAYOUT_LEN); - } - - int2tag(tag.bc221.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bc221.tagId[0]), TAGID_LEN)); - int2tag(tag.bc221.imageCRC, imagecrc); - int2tag(tag.bc221.fskernelCRC, kernelfscrc); - int2tag(tag.bc221.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); - } else if ( tagid && (strcmp(tagid, "bc310") == 0)) { - /* Build the tag */ - strncpy(tag.bc310.tagVersion, ver, TAGVER_LEN); - strncpy(tag.bc310.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bc310.sig_1) - 1); - strncpy(tag.bc310.sig_2, magic2, sizeof(tag.bc310.sig_2) - 1); - strcpy(tag.bc310.chipid, chipid); - strcpy(tag.bc310.boardid, boardid); - strcpy(tag.bc310.big_endian, "1"); - sprintf(tag.bc310.totalLength, "%lu", imagelen); - - /* We don't include CFE */ - strcpy(tag.bc310.cfeAddress, "0"); - strcpy(tag.bc310.cfeLength, "0"); - - if (kernelfile) { - sprintf(tag.bc310.kernelAddress, "%lu", kerneloff); - sprintf(tag.bc310.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } - - if (rootfsfile) { - sprintf(tag.bc310.flashImageStart, "%lu", kerneloff); - sprintf(tag.bc310.flashRootLength, "%lu", rootfslen + sizeof(deadcode)); - sprintf(tag.bc310.rootAddress, "%lu", rootfsoff); - sprintf(tag.bc310.rootLength, "%lu", rootfslen); - } - - strncpy(tag.bc310.tagId, "bc310", TAGID_LEN); - if (information) { - strncpy(tag.bc310.information1, information, TAGINFO_LEN); - } - - int2tag(tag.bc310.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bc310.tagId[0]), TAGID_LEN)); - int2tag(tag.bc310.imageCRC, imagecrc); - int2tag(tag.bc310.kernelCRC, kernelcrc); - int2tag(tag.bc310.rootfsCRC, rootfscrc); - int2tag(tag.bc310.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); + if (rsignature) { + strncpy(tag.rsa_signature, rsignature, RSASIG_LEN); } + if (layoutver) { + strncpy(tag.flashLayoutVer, layoutver, TAGLAYOUT_LEN); + } + + for (i = 0; i < NUM_PIRELLI; i++) { + if (strncmp(boardid, pirellitab[i], BOARDID_LEN) == 0) { + is_pirelli = 1; + break; + } + } + + if ( !is_pirelli ) { + int2tag(tag.imageCRC, imagecrc); + } else { + int2tag(tag.imageCRC, kernelcrc); + } + int2tag(tag.kernelCRC, kernelcrc); + int2tag(tag.rootfsCRC, rootfscrc); + int2tag(tag.fskernelCRC, kernelfscrc); + int2tag(tag.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); + fseek(binfile, 0L, SEEK_SET); fwrite(&tag, sizeof(uint8_t), sizeof(tag), binfile); @@ -432,12 +302,12 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, int main(int argc, char **argv) { int c, i; - char *kernel, *rootfs, *bin, *boardid, *chipid, *magic2, *ver, *tagid, *information, *layoutver; + char *kernel, *rootfs, *bin, *boardid, *chipid, *magic2, *ver, *tagid, *rsignature, *layoutver; uint32_t flashstart, fwoffset, loadaddr, entry; uint32_t fwaddr, flash_bs; int tagidfound = 0; - kernel = rootfs = bin = boardid = chipid = magic2 = ver = tagid = information = layoutver = NULL; + kernel = rootfs = bin = boardid = chipid = magic2 = ver = rsignature = layoutver = NULL; entry = 0; flashstart = DEFAULT_FLASH_START; @@ -445,11 +315,11 @@ int main(int argc, char **argv) loadaddr = IMAGETAG_DEFAULT_LOADADDR; flash_bs = DEFAULT_FLASH_BS; - printf("Broadcom image tagger - v0.2.0\n"); + printf("Broadcom image tagger - v1.0.0\n"); printf("Copyright (C) 2008 Axel Gembe\n"); - printf("Copyright (C) 2009 Daniel Dickinson\n"); + printf("Copyright (C) 2009-2010 Daniel Dickinson\n"); - while ((c = getopt(argc, argv, "i:f:o:b:c:s:n:v:m:k:l:e:h:t:d:y:")) != -1) { + while ((c = getopt(argc, argv, "i:f:o:b:c:s:n:v:m:k:l:e:h:r:y:")) != -1) { switch (c) { case 'i': kernel = optarg; @@ -487,11 +357,8 @@ int main(int argc, char **argv) case 'e': entry = strtoul(optarg, NULL, 16); break; - case 't': - tagid = optarg; - break; - case 'd': - information = optarg; + case 'r': + rsignature = optarg; break; case 'y': layoutver = optarg; @@ -511,9 +378,8 @@ int main(int argc, char **argv) fprintf(stderr, " -k - flash erase block size\n"); fprintf(stderr, " -l - Address where the kernel expects to be loaded (defaults to 0x80010000)\n"); fprintf(stderr, " -e - Address where the kernel entry point will end up\n"); - fprintf(stderr, " -t - type if imagetag to create, use 'list' to see available choices"); - fprintf(stderr, " -d - vendor specific information, for those that need it"); - fprintf(stderr, " -y - Flash Layout Version (2.2x code versions need this)"); + fprintf(stderr, " -r - vendor specific signature, for those that need it"); + fprintf(stderr, " -y - Flash Layout Version (2.2x code versions need this)"); fprintf(stderr, " -h - Displays this text\n\n"); return 1; } @@ -529,38 +395,6 @@ int main(int argc, char **argv) return 1; } - tagidfound = 0; - if (!tagid) { - fprintf(stderr, "You must specify a tagid (-t)\n"); - } else { - if (strncmp(tagid, "list", 4) == 0) { - fprintf(stderr, "\n----------------------------------------\n"); - fprintf(stderr, "\tAvailable tagId:"); - fprintf(stderr, "\n\n"); - for (i = 0; i < NUM_TAGID; i++) { - fprintf(stderr, "\t%s\t%s", tagidtab[i].tagid, tagidtab[i].tagiddesc); - } - fprintf(stderr, "\n----------------------------------------\n"); - return 0; - } - } - - if (tagid) { - for(i = 0; i < NUM_TAGID; i++) { - if (strncmp(tagid, tagidtab[i].tagid, TAGID_LEN) == 0) { - tagidfound = 1; - break; - } - } - if (!tagidfound) { - if (tagid) { - fprintf(stderr, "The tagid you selected '%s' does't exist.\n", tagid); - } - fprintf(stderr, "Use -t list to see the list of available ids"); - return 1; - } - } - /* Fallback to defaults */ fwaddr = flashstart + fwoffset; @@ -584,5 +418,5 @@ int main(int argc, char **argv) } - return tagfile(kernel, rootfs, bin, boardid, chipid, fwaddr, loadaddr, entry, ver, magic2, flash_bs, tagid, information, layoutver); + return tagfile(kernel, rootfs, bin, boardid, chipid, fwaddr, loadaddr, entry, ver, magic2, flash_bs, rsignature, layoutver); } From 25c1e23616e761e050a168af4045b7ce972cc46f Mon Sep 17 00:00:00 2001 From: florian Date: Fri, 2 Apr 2010 10:34:40 +0000 Subject: [PATCH 45/45] [rdc] do not set CONFIG_NET_DEV_OPS (#7005) git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20653 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/rdc/config-2.6.30 | 1 - 1 file changed, 1 deletion(-) diff --git a/target/linux/rdc/config-2.6.30 b/target/linux/rdc/config-2.6.30 index b18048b4b..b8d222d9c 100644 --- a/target/linux/rdc/config-2.6.30 +++ b/target/linux/rdc/config-2.6.30 @@ -38,7 +38,6 @@ CONFIG_CLOCKSOURCE_WATCHDOG=y CONFIG_CMDLINE_BOOL=y CONFIG_CMDLINE="console=ttyS0,38400 rootfstype=squashfs,jffs2" # CONFIG_CMDLINE_OVERRIDE is not set -# CONFIG_COMPAT_NET_DEV_OPS is not set # CONFIG_COMPAT_VDSO is not set # CONFIG_CPU5_WDT is not set # CONFIG_CPU_SUP_AMD is not set