From 76ed58d705e7f3892a1259abcd92882a527e7b53 Mon Sep 17 00:00:00 2001 From: nbd Date: Sat, 28 May 2005 09:17:29 +0000 Subject: move package/linux into target/linux, use wbx' new kernel code. support building images with more than one kernel, split kernel module parts off of packages that use their own kernel modules (fuse, shfs, openswan). some cleanup in the image building process in target/. image builder is disabled for now, needs some fixing. git-svn-id: svn://svn.openwrt.org/openwrt/trunk/openwrt@1085 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/control/kmod-usb2.control | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 target/linux/control/kmod-usb2.control (limited to 'target/linux/control/kmod-usb2.control') diff --git a/target/linux/control/kmod-usb2.control b/target/linux/control/kmod-usb2.control new file mode 100644 index 0000000000..8fef6cd4b5 --- /dev/null +++ b/target/linux/control/kmod-usb2.control @@ -0,0 +1,7 @@ +Package: kmod-usb2 +Priority: optional +Section: sys +Maintainer: Felix Fietkau +Source: buildroot internal +Depends: kmod-usb-core +Description: Kernel driver for USB2 controllers -- cgit v1.2.3 From 9f0f9cb05ffb57d44cbcd27489ad2cc51c212a70 Mon Sep 17 00:00:00 2001 From: nbd Date: Sat, 11 Jun 2005 15:36:31 +0000 Subject: add board tag to kernel module version and add versioned depend (does not work with current ipkg yet) git-svn-id: svn://svn.openwrt.org/openwrt/trunk/openwrt@1202 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/control/kmod-ip6tables.control | 1 - target/linux/control/kmod-usb-ohci.control | 1 - target/linux/control/kmod-usb-uhci.control | 1 - target/linux/control/kmod-usb2.control | 1 - target/linux/linux-2.4/Makefile | 22 ++++++++++++---------- target/linux/package/Makefile | 19 +++++++++---------- target/linux/package/fuse/Makefile | 2 +- target/linux/package/openswan/Makefile | 2 +- target/linux/package/shfs/Makefile | 2 +- target/linux/package/wlcompat/Makefile | 2 +- target/linux/rules.mk | 12 ++++++++++-- 11 files changed, 35 insertions(+), 30 deletions(-) (limited to 'target/linux/control/kmod-usb2.control') diff --git a/target/linux/control/kmod-ip6tables.control b/target/linux/control/kmod-ip6tables.control index 32a72aa65e..777ab14bc4 100644 --- a/target/linux/control/kmod-ip6tables.control +++ b/target/linux/control/kmod-ip6tables.control @@ -4,4 +4,3 @@ Section: net Maintainer: Felix Fietkau Source: buildroot internal Description: Kernel modules for ip6tables -Depends: kmod-ipv6 diff --git a/target/linux/control/kmod-usb-ohci.control b/target/linux/control/kmod-usb-ohci.control index cc87fa8da5..adb6e27635 100644 --- a/target/linux/control/kmod-usb-ohci.control +++ b/target/linux/control/kmod-usb-ohci.control @@ -3,5 +3,4 @@ Priority: optional Section: sys Maintainer: Felix Fietkau Source: buildroot internal -Depends: kmod-usb-core Description: Kernel driver for OHCI USB controllers diff --git a/target/linux/control/kmod-usb-uhci.control b/target/linux/control/kmod-usb-uhci.control index 53a07d892e..c7e678f188 100644 --- a/target/linux/control/kmod-usb-uhci.control +++ b/target/linux/control/kmod-usb-uhci.control @@ -3,5 +3,4 @@ Priority: optional Section: sys Maintainer: Felix Fietkau Source: buildroot internal -Depends: kmod-usb-core Description: Kernel driver for UHCI USB controllers diff --git a/target/linux/control/kmod-usb2.control b/target/linux/control/kmod-usb2.control index 8fef6cd4b5..48da3a6fc8 100644 --- a/target/linux/control/kmod-usb2.control +++ b/target/linux/control/kmod-usb2.control @@ -3,5 +3,4 @@ Priority: optional Section: sys Maintainer: Felix Fietkau Source: buildroot internal -Depends: kmod-usb-core Description: Kernel driver for USB2 controllers diff --git a/target/linux/linux-2.4/Makefile b/target/linux/linux-2.4/Makefile index db7d71c16a..e8ce928e86 100644 --- a/target/linux/linux-2.4/Makefile +++ b/target/linux/linux-2.4/Makefile @@ -40,7 +40,10 @@ MODULES_DIR := $(LINUX_BUILD_DIR)/modules/$(MODULES_SUBDIR) TARGET_MODULES_DIR := $(TARGET_DIR)/lib/modules/$(LINUX_VERSION) IPKG_KERNEL:=IPKG_TMP=$(BUILD_DIR)/tmp IPKG_INSTROOT=$(LINUX_TARGET_DIR) IPKG_CONF_DIR=$(LINUX_BUILD_DIR) $(SCRIPT_DIR)/ipkg -force-defaults -force-depends -KERNEL_IPKG:=$(LINUX_BUILD_DIR)/kernel_$(LINUX_VERSION)-$(BOARD)_$(ARCH).ipk +PKG_BUILD_DIR := $(LINUX_BUILD_DIR)/linux-modules +PKG_RELEASE := 1 + +KERNEL_IPKG:=$(LINUX_BUILD_DIR)/kernel_$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE)_$(ARCH).ipk KERNEL_IDIR:=$(LINUX_BUILD_DIR)/kernel-ipkg include $(LINUX_KCONFIG) @@ -48,9 +51,6 @@ ifeq ($(BOARD),brcm) include ./broadcom.mk endif -PKG_BUILD_DIR := $(LINUX_BUILD_DIR)/linux-modules -PKG_RELEASE := 1 - TARGETS := INSTALL_TARGETS := $(KERNEL_IPKG) @@ -77,7 +77,7 @@ $(eval $(call KMOD_template,IPTABLES_V4_EXTRA,iptables-extra,\ )) $(eval $(call KMOD_template,IPTABLES_V6,ip6tables,\ $(MODULES_DIR)/kernel/net/ipv6/netfilter/ip*.o \ -,CONFIG_IP6_NF_IPTABLES)) +,CONFIG_IP6_NF_IPTABLES,kmod-ipv6)) $(eval $(call KMOD_template,IPV6,ipv6,\ $(MODULES_DIR)/kernel/net/ipv6/ipv6.o \ ,CONFIG_IPV6)) @@ -94,13 +94,13 @@ $(eval $(call KMOD_template,USB,usb-core,\ ,CONFIG_USB)) $(eval $(call KMOD_template,USB_UHCI,usb-uhci,\ $(MODULES_DIR)/kernel/drivers/usb/host/uhci.o \ -,CONFIG_USB_UHCI_ALT)) +,CONFIG_USB_UHCI_ALT,kmod-usb-core)) $(eval $(call KMOD_template,USB_OHCI,usb-ohci,\ $(MODULES_DIR)/kernel/drivers/usb/host/usb-ohci.o \ -,CONFIG_USB_OHCI)) +,CONFIG_USB_OHCI,kmod-usb-core)) $(eval $(call KMOD_template,USB2,usb2,\ $(MODULES_DIR)/kernel/drivers/usb/host/ehci-hcd.o \ -,CONFIG_USB_EHCI_HCD)) +,CONFIG_USB_EHCI_HCD,kmod-usb-core)) $(eval $(call KMOD_template,USB_STORAGE,usb-storage,\ $(MODULES_DIR)/kernel/drivers/scsi/*.o \ $(MODULES_DIR)/kernel/drivers/usb/storage/*.o \ @@ -216,7 +216,7 @@ $(TARGET_MODULES_DIR): $(KERNEL_IPKG): rm -rf $(KERNEL_IDIR) mkdir -p $(KERNEL_IDIR)/etc - $(SCRIPT_DIR)/make-ipkg-dir.sh $(KERNEL_IDIR) ../control/kernel.control $(LINUX_VERSION)-$(BOARD) $(ARCH) + $(SCRIPT_DIR)/make-ipkg-dir.sh $(KERNEL_IDIR) ../control/kernel.control $(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE) $(ARCH) if [ -f ./config/$(BOARD).modules ]; then \ cp ./config/$(BOARD).modules $(KERNEL_IDIR)/etc/modules; \ fi @@ -227,10 +227,12 @@ prepare: $(LINUX_DIR)/.configured compile: $(LINUX_DIR)/.modules_done $(TARGETS) ln -sf $(LINUX_BUILD_DIR)/linux-$(LINUX_VERSION) $(LINUX_DIR) $(MAKE) -C $(TOPDIR)/target/linux/package \ + BOARD="$(BOARD)" \ TARGET_DIR="$(LINUX_TARGET_DIR)" \ BUILD_DIR="$(LINUX_BUILD_DIR)" \ KERNEL_DIR="$(LINUX_SOURCE_DIR)" \ - LINUX_VERSION="$(LINUX_VERSION)" + LINUX_VERSION="$(LINUX_VERSION)" \ + KERNEL_RELEASE="$(PKG_RELEASE)" install: compile $(TARGET_MODULES_DIR) $(KERNEL_IPKG) rm -rf $(LINUX_BUILD_DIR)/root* diff --git a/target/linux/package/Makefile b/target/linux/package/Makefile index 055bd2ffe4..fd66e5a973 100644 --- a/target/linux/package/Makefile +++ b/target/linux/package/Makefile @@ -13,28 +13,27 @@ clean: $(patsubst %,%-clean,$(package-) $(package-y) $(package-m)) compile: $(patsubst %,%-compile,$(package-y) $(package-m)) install: $(patsubst %,%-install,$(package-y)) -%-prepare: - $(MAKE) -C $(patsubst %-prepare,%,$@) \ +MAKEOPTS:= BOARD="$(BOARD)" \ TARGET_DIR="$(TARGET_DIR)" \ BUILD_DIR="$(BUILD_DIR)" \ KERNEL_DIR="$(KERNEL_DIR)" \ LINUX_VERSION="$(LINUX_VERSION)" \ + KERNEL_RELEASE="$(KERNEL_RELEASE)" + + +%-prepare: + $(MAKE) -C $(patsubst %-prepare,%,$@) \ + $(MAKEOPTS) \ prepare %-compile: %-prepare $(MAKE) -C $(patsubst %-compile,%,$@) \ - TARGET_DIR="$(TARGET_DIR)" \ - BUILD_DIR="$(BUILD_DIR)" \ - KERNEL_DIR="$(KERNEL_DIR)" \ - LINUX_VERSION="$(LINUX_VERSION)" \ + $(MAKEOPTS) \ compile %-install: %-compile $(MAKE) -C $(patsubst %-install,%,$@) \ - TARGET_DIR="$(TARGET_DIR)" \ - BUILD_DIR="$(BUILD_DIR)" \ - KERNEL_DIR="$(KERNEL_DIR)" \ - LINUX_VERSION="$(LINUX_VERSION)" \ + $(MAKEOPTS) \ install %-clean: diff --git a/target/linux/package/fuse/Makefile b/target/linux/package/fuse/Makefile index 9db6295980..8b997d6b4f 100644 --- a/target/linux/package/fuse/Makefile +++ b/target/linux/package/fuse/Makefile @@ -20,7 +20,7 @@ endif include $(TOPDIR)/package/rules.mk -$(eval $(call PKG_template,KMOD_FUSE,kmod-fuse,$(LINUX_VERSION)+$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH))) +$(eval $(call PKG_template,KMOD_FUSE,kmod-fuse,$(LINUX_VERSION)$(BOARD)+$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH),kernel ($(LINUX_VERSION)-$(BOARD)-$(KERNEL_RELEASE)))) $(PKG_BUILD_DIR)/.configured: (cd $(PKG_BUILD_DIR); \ diff --git a/target/linux/package/openswan/Makefile b/target/linux/package/openswan/Makefile index 5ebb8702dd..a105a1f540 100644 --- a/target/linux/package/openswan/Makefile +++ b/target/linux/package/openswan/Makefile @@ -18,7 +18,7 @@ ifeq ($(KERNEL_DIR),) KERNEL_DIR:=$(LINUX_DIR) endif -$(eval $(call PKG_template,KMOD_OPENSWAN,kmod-openswan,$(LINUX_VERSION)+$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH))) +$(eval $(call PKG_template,KMOD_OPENSWAN,kmod-openswan,$(LINUX_VERSION)$(BOARD)+$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH),kernel ($(LINUX_VERSION)-$(BOARD)-$(KERNEL_RELEASE)))) FLAGS := $(TARGET_CFLAGS) -I$(PKG_BUILD_DIR)/linux/include -L$(STAGING_DIR)/usr/lib -I$(STAGING_DIR)/usr/include diff --git a/target/linux/package/shfs/Makefile b/target/linux/package/shfs/Makefile index a329bbffc9..36046065f8 100644 --- a/target/linux/package/shfs/Makefile +++ b/target/linux/package/shfs/Makefile @@ -20,7 +20,7 @@ endif include $(TOPDIR)/package/rules.mk -$(eval $(call PKG_template,KMOD_SHFS,kmod-shfs,$(LINUX_VERSION)+$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH))) +$(eval $(call PKG_template,KMOD_SHFS,kmod-shfs,$(LINUX_VERSION)$(BOARD)+$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH),kernel ($(LINUX_VERSION)-$(BOARD)-$(KERNEL_RELEASE)))) $(PKG_BUILD_DIR)/.configured: touch $@ diff --git a/target/linux/package/wlcompat/Makefile b/target/linux/package/wlcompat/Makefile index da905527cd..706948e8ea 100644 --- a/target/linux/package/wlcompat/Makefile +++ b/target/linux/package/wlcompat/Makefile @@ -8,7 +8,7 @@ PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) include $(TOPDIR)/package/rules.mk -$(eval $(call PKG_template,KMOD_WLCOMPAT,$(PKG_NAME),$(LINUX_VERSION)-$(PKG_RELEASE),$(ARCH))) +$(eval $(call PKG_template,KMOD_WLCOMPAT,$(PKG_NAME),$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE),$(ARCH),kernel ($(LINUX_VERSION)-$(BOARD)-$(KERNEL_RELEASE)))) ifeq ($(KERNEL_DIR),) KERNEL_DIR:=$(LINUX_DIR) diff --git a/target/linux/rules.mk b/target/linux/rules.mk index 451ec26e42..9446c343fa 100644 --- a/target/linux/rules.mk +++ b/target/linux/rules.mk @@ -5,7 +5,13 @@ else KDEPEND_$(1):=$($(4)) endif -PKG_$(1) := $(PACKAGE_DIR)/kmod-$(2)_$(LINUX_VERSION)-$(PKG_RELEASE)_$(ARCH).ipk +ifeq ($$(strip $(5)),) +IDEPEND_$(1):=kernel ($(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE)) +else +IDEPEND_$(1):=kernel ($(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE)), $(5) +endif + +PKG_$(1) := $(PACKAGE_DIR)/kmod-$(2)_$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE)_$(ARCH).ipk I_$(1) := $(PKG_BUILD_DIR)/ipkg/$(2) ifeq ($$(KDEPEND_$(1)),m) @@ -18,8 +24,10 @@ endif endif $$(PKG_$(1)): $(LINUX_DIR)/.modules_done + rm -rf $$(I_$(1)) mkdir -p $$(I_$(1))/lib/modules/$(LINUX_VERSION) - $(SCRIPT_DIR)/make-ipkg-dir.sh $$(I_$(1)) ../control/kmod-$(2).control $(LINUX_VERSION)-$(PKG_RELEASE) $(ARCH) + $(SCRIPT_DIR)/make-ipkg-dir.sh $$(I_$(1)) ../control/kmod-$(2).control $(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE) $(ARCH) + echo "Depends: $$(IDEPEND_$(1))" >> $$(I_$(1))/CONTROL/control cp $(3) $$(I_$(1))/lib/modules/$(LINUX_VERSION) $(IPKG_BUILD) $$(I_$(1)) $(PACKAGE_DIR) -- cgit v1.2.3 From be8ad0190d689eb7f797bdc0618d7e87892a831d Mon Sep 17 00:00:00 2001 From: nbd Date: Tue, 30 May 2006 19:38:38 +0000 Subject: resync with kamikaze git-svn-id: svn://svn.openwrt.org/openwrt/branches/buildroot-ng/openwrt@3844 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/base-files/default/etc/functions.sh | 4 + package/base-files/default/etc/init.d/S10boot | 3 +- package/iptables/files/firewall.awk | 1 + target/Config.in | 9 + target/linux/Config.in | 12 +- target/linux/Makefile | 2 + target/linux/aruba-2.6/Makefile | 4 +- target/linux/aruba-2.6/patches/000-aruba.patch | 42 +- target/linux/aruba-2.6/patches/004-wdt.patch | 126 + target/linux/au1000-2.6/Makefile | 11 +- target/linux/au1000-2.6/config | 811 +- .../au1000-2.6/patches/002-mtx1_flash_map.patch | 16 + target/linux/au1000-2.6/patches/003-zImage.patch | 1364 + .../au1000-2.6/patches/004-mtx1_watchdog.patch | 279 + .../patches/005-au1000_eth_link_beat.patch | 24 + .../patches/006-mtx1_system_button.patch | 241 + .../linux/au1000-2.6/patches/007-mtx1_sio2.patch | 13 + .../au1000-2.6/patches/008-isdel_cardbus.patch | 63 + target/linux/au1000-2.6/patches/009-boot.patch | 15 + target/linux/brcm-2.4/Config.in | 10 - target/linux/brcm-2.4/Makefile | 17 +- target/linux/brcm-2.4/config | 1 - target/linux/brcm-2.4/patches/001-bcm47xx.patch | 34791 +++++++++---------- .../brcm-2.4/patches/009-wrt54g3g_pcmcia.patch | 119 + target/linux/brcm-2.6/Makefile | 4 +- target/linux/control/kernel.control | 2 - target/linux/control/kmod-arptables.control | 2 - target/linux/control/kmod-atm.control | 2 - target/linux/control/kmod-ax25.control | 2 - target/linux/control/kmod-bluetooth.control | 2 - target/linux/control/kmod-brcm-et.control | 2 - target/linux/control/kmod-brcm-wl.control | 2 - target/linux/control/kmod-brcm-wl2.control | 2 - target/linux/control/kmod-cpmac.control | 2 - target/linux/control/kmod-crypto.control | 2 - target/linux/control/kmod-ebtables.control | 2 - target/linux/control/kmod-gre.control | 2 - target/linux/control/kmod-ide.control | 2 - target/linux/control/kmod-ip6tables.control | 2 - target/linux/control/kmod-ipip.control | 4 + target/linux/control/kmod-iptables-extra.control | 2 - target/linux/control/kmod-iptables.control | 2 - target/linux/control/kmod-ipv6.control | 2 - target/linux/control/kmod-loop.control | 2 - target/linux/control/kmod-lp.control | 2 - target/linux/control/kmod-mppe.control | 2 - target/linux/control/kmod-nbd.control | 2 - target/linux/control/kmod-nls-base.control | 2 - target/linux/control/kmod-nls-cp437.control | 2 - target/linux/control/kmod-nls-cp850.control | 2 - target/linux/control/kmod-nls-iso8859-1.control | 2 - target/linux/control/kmod-nls-iso8859-15.control | 2 - target/linux/control/kmod-nls-utf8.control | 2 - target/linux/control/kmod-ppp.control | 2 - target/linux/control/kmod-pppoatm.control | 2 - target/linux/control/kmod-pppoe.control | 2 - target/linux/control/kmod-pwc.control | 2 - .../linux/control/kmod-sangam-atm-annex-a.control | 2 - .../linux/control/kmod-sangam-atm-annex-b.control | 2 - target/linux/control/kmod-sched.control | 2 - target/linux/control/kmod-softdog.control | 2 - target/linux/control/kmod-soundcore.control | 2 - target/linux/control/kmod-tun.control | 2 - target/linux/control/kmod-usb-acm.control | 2 - .../linux/control/kmod-usb-atm-speedtouch.control | 2 - target/linux/control/kmod-usb-audio.control | 2 - target/linux/control/kmod-usb-core.control | 2 - target/linux/control/kmod-usb-ohci.control | 2 - target/linux/control/kmod-usb-printer.control | 2 - .../linux/control/kmod-usb-serial-belkin.control | 2 - target/linux/control/kmod-usb-serial-ftdi.control | 2 - .../linux/control/kmod-usb-serial-mct-u232.control | 2 - .../linux/control/kmod-usb-serial-pl2303.control | 2 - target/linux/control/kmod-usb-serial-visor.control | 5 +- target/linux/control/kmod-usb-serial.control | 2 - target/linux/control/kmod-usb-storage.control | 2 - target/linux/control/kmod-usb-uhci.control | 2 - target/linux/control/kmod-usb2.control | 2 - target/linux/control/kmod-videodev.control | 2 - target/linux/control/kmod-wd1100.control | 2 - target/linux/generic-2.4/modules.mk | 10 +- target/linux/generic-2.6/modules.mk | 6 +- .../linux/generic-2.6/patches/005-gcc4_fix.patch | 14 +- target/linux/image/au1000/Makefile | 58 +- target/linux/image/jffs2.mk | 2 +- target/linux/image/squashfs.mk | 6 +- target/linux/image/xscale/Makefile | 36 + target/linux/kernel.mk | 6 +- target/linux/package/Makefile | 3 - .../base-files/files/au1000-2.6/sbin/mount_root | 23 + .../files/brcm-2.4/etc/hotplug.d/net/09-net | 6 +- .../base-files/files/sibyte-2.6/etc/config/network | 12 + .../base-files/files/sibyte-2.6/etc/inittab | 3 + .../linux/package/base-files/files/sibyte-2.6/init | 6 + .../base-files/files/xscale-2.6/etc/config/network | 5 + .../files/xscale-2.6/etc/init.d/S00xscale | 4 + .../linux/package/base-files/files/xscale-2.6/init | 3 + target/linux/package/bcm43xx-standalone/Config.in | 12 - target/linux/package/bcm43xx-standalone/Makefile | 57 - .../package/bcm43xx-standalone/fwcutter/Makefile | 32 - .../package/bcm43xx-standalone/fwcutter/fwcutter.c | 562 - .../bcm43xx-standalone/fwcutter/fwcutter_list.h | 810 - .../package/bcm43xx-standalone/fwcutter/md5.c | 253 - .../package/bcm43xx-standalone/fwcutter/md5.h | 16 - .../ipkg/kmod-bcm43xx-standalone.control | 4 - target/linux/package/ieee80211-dscape/Config.in | 10 - target/linux/package/ieee80211-dscape/Makefile | 46 - .../ipkg/kmod-ieee80211-dscape.control | 4 - target/linux/package/ieee80211-dscape/src/Kconfig | 32 - target/linux/package/ieee80211-dscape/src/Makefile | 23 - target/linux/package/ieee80211-dscape/src/aes.c | 564 - .../linux/package/ieee80211-dscape/src/aes_ccm.c | 119 - .../linux/package/ieee80211-dscape/src/aes_ccm.h | 22 - .../package/ieee80211-dscape/src/fifo_qdisc.c | 103 - .../package/ieee80211-dscape/src/hostapd_ioctl.h | 438 - .../linux/package/ieee80211-dscape/src/ieee80211.c | 4895 --- .../package/ieee80211-dscape/src/ieee80211_i.h | 571 - .../package/ieee80211-dscape/src/ieee80211_ioctl.c | 2832 -- .../package/ieee80211-dscape/src/ieee80211_key.h | 80 - .../package/ieee80211-dscape/src/ieee80211_led.c | 32 - .../package/ieee80211-dscape/src/ieee80211_proc.c | 777 - .../package/ieee80211-dscape/src/ieee80211_proc.h | 41 - .../package/ieee80211-dscape/src/ieee80211_scan.c | 352 - .../package/ieee80211-dscape/src/ieee80211_sta.c | 2868 -- .../ieee80211-dscape/src/include/net/ieee80211.h | 872 - .../src/include/net/ieee80211_common.h | 96 - .../src/include/net/ieee80211_mgmt.h | 196 - .../src/include/net/ieee80211_shared.h | 50 - .../linux/package/ieee80211-dscape/src/michael.c | 104 - .../linux/package/ieee80211-dscape/src/michael.h | 18 - .../package/ieee80211-dscape/src/rate_control.c | 381 - .../package/ieee80211-dscape/src/rate_control.h | 128 - .../linux/package/ieee80211-dscape/src/sta_info.c | 417 - .../linux/package/ieee80211-dscape/src/sta_info.h | 142 - target/linux/package/ieee80211-dscape/src/tkip.c | 341 - target/linux/package/ieee80211-dscape/src/tkip.h | 26 - target/linux/package/ieee80211-dscape/src/wep.c | 423 - target/linux/package/ieee80211-dscape/src/wep.h | 34 - target/linux/package/ieee80211-dscape/src/wme.c | 700 - target/linux/package/ieee80211-dscape/src/wme.h | 53 - target/linux/package/ieee80211-dscape/src/wpa.c | 825 - target/linux/package/ieee80211-dscape/src/wpa.h | 30 - target/linux/package/madwifi/Config.in | 2 +- target/linux/package/madwifi/Makefile | 7 +- .../madwifi/patches/100-kernel_cflags.patch | 11 + target/linux/package/wlcompat/Config.in | 4 +- target/linux/package/wlcompat/wlcompat.c | 4 +- target/linux/rules.mk | 6 + target/linux/sibyte-2.6/Makefile | 19 + target/linux/sibyte-2.6/config | 1311 + target/linux/sibyte-2.6/patches/000-DUART.patch | 956 + .../linux/sibyte-2.6/patches/001-bcm112x_ax.patch | 17 + target/linux/x86-2.6/Makefile | 4 +- target/linux/xscale-2.6/Makefile | 18 + target/linux/xscale-2.6/config | 1363 + .../xscale-2.6/patches/001-gateway_7001.patch | 159 + 156 files changed, 23066 insertions(+), 39506 deletions(-) create mode 100644 target/linux/aruba-2.6/patches/004-wdt.patch create mode 100644 target/linux/au1000-2.6/patches/002-mtx1_flash_map.patch create mode 100644 target/linux/au1000-2.6/patches/003-zImage.patch create mode 100644 target/linux/au1000-2.6/patches/004-mtx1_watchdog.patch create mode 100644 target/linux/au1000-2.6/patches/005-au1000_eth_link_beat.patch create mode 100644 target/linux/au1000-2.6/patches/006-mtx1_system_button.patch create mode 100644 target/linux/au1000-2.6/patches/007-mtx1_sio2.patch create mode 100644 target/linux/au1000-2.6/patches/008-isdel_cardbus.patch create mode 100644 target/linux/au1000-2.6/patches/009-boot.patch create mode 100644 target/linux/brcm-2.4/patches/009-wrt54g3g_pcmcia.patch create mode 100644 target/linux/control/kmod-ipip.control create mode 100644 target/linux/image/xscale/Makefile create mode 100755 target/linux/package/base-files/files/au1000-2.6/sbin/mount_root create mode 100644 target/linux/package/base-files/files/sibyte-2.6/etc/config/network create mode 100644 target/linux/package/base-files/files/sibyte-2.6/etc/inittab create mode 100755 target/linux/package/base-files/files/sibyte-2.6/init create mode 100644 target/linux/package/base-files/files/xscale-2.6/etc/config/network create mode 100755 target/linux/package/base-files/files/xscale-2.6/etc/init.d/S00xscale create mode 100755 target/linux/package/base-files/files/xscale-2.6/init delete mode 100644 target/linux/package/bcm43xx-standalone/Config.in delete mode 100644 target/linux/package/bcm43xx-standalone/Makefile delete mode 100644 target/linux/package/bcm43xx-standalone/fwcutter/Makefile delete mode 100644 target/linux/package/bcm43xx-standalone/fwcutter/fwcutter.c delete mode 100644 target/linux/package/bcm43xx-standalone/fwcutter/fwcutter_list.h delete mode 100644 target/linux/package/bcm43xx-standalone/fwcutter/md5.c delete mode 100644 target/linux/package/bcm43xx-standalone/fwcutter/md5.h delete mode 100644 target/linux/package/bcm43xx-standalone/ipkg/kmod-bcm43xx-standalone.control delete mode 100644 target/linux/package/ieee80211-dscape/Config.in delete mode 100644 target/linux/package/ieee80211-dscape/Makefile delete mode 100644 target/linux/package/ieee80211-dscape/ipkg/kmod-ieee80211-dscape.control delete mode 100644 target/linux/package/ieee80211-dscape/src/Kconfig delete mode 100644 target/linux/package/ieee80211-dscape/src/Makefile delete mode 100644 target/linux/package/ieee80211-dscape/src/aes.c delete mode 100644 target/linux/package/ieee80211-dscape/src/aes_ccm.c delete mode 100644 target/linux/package/ieee80211-dscape/src/aes_ccm.h delete mode 100644 target/linux/package/ieee80211-dscape/src/fifo_qdisc.c delete mode 100644 target/linux/package/ieee80211-dscape/src/hostapd_ioctl.h delete mode 100644 target/linux/package/ieee80211-dscape/src/ieee80211.c delete mode 100644 target/linux/package/ieee80211-dscape/src/ieee80211_i.h delete mode 100644 target/linux/package/ieee80211-dscape/src/ieee80211_ioctl.c delete mode 100644 target/linux/package/ieee80211-dscape/src/ieee80211_key.h delete mode 100644 target/linux/package/ieee80211-dscape/src/ieee80211_led.c delete mode 100644 target/linux/package/ieee80211-dscape/src/ieee80211_proc.c delete mode 100644 target/linux/package/ieee80211-dscape/src/ieee80211_proc.h delete mode 100644 target/linux/package/ieee80211-dscape/src/ieee80211_scan.c delete mode 100644 target/linux/package/ieee80211-dscape/src/ieee80211_sta.c delete mode 100644 target/linux/package/ieee80211-dscape/src/include/net/ieee80211.h delete mode 100644 target/linux/package/ieee80211-dscape/src/include/net/ieee80211_common.h delete mode 100644 target/linux/package/ieee80211-dscape/src/include/net/ieee80211_mgmt.h delete mode 100644 target/linux/package/ieee80211-dscape/src/include/net/ieee80211_shared.h delete mode 100644 target/linux/package/ieee80211-dscape/src/michael.c delete mode 100644 target/linux/package/ieee80211-dscape/src/michael.h delete mode 100644 target/linux/package/ieee80211-dscape/src/rate_control.c delete mode 100644 target/linux/package/ieee80211-dscape/src/rate_control.h delete mode 100644 target/linux/package/ieee80211-dscape/src/sta_info.c delete mode 100644 target/linux/package/ieee80211-dscape/src/sta_info.h delete mode 100644 target/linux/package/ieee80211-dscape/src/tkip.c delete mode 100644 target/linux/package/ieee80211-dscape/src/tkip.h delete mode 100644 target/linux/package/ieee80211-dscape/src/wep.c delete mode 100644 target/linux/package/ieee80211-dscape/src/wep.h delete mode 100644 target/linux/package/ieee80211-dscape/src/wme.c delete mode 100644 target/linux/package/ieee80211-dscape/src/wme.h delete mode 100644 target/linux/package/ieee80211-dscape/src/wpa.c delete mode 100644 target/linux/package/ieee80211-dscape/src/wpa.h create mode 100644 target/linux/sibyte-2.6/Makefile create mode 100644 target/linux/sibyte-2.6/config create mode 100644 target/linux/sibyte-2.6/patches/000-DUART.patch create mode 100644 target/linux/sibyte-2.6/patches/001-bcm112x_ax.patch create mode 100644 target/linux/xscale-2.6/Makefile create mode 100644 target/linux/xscale-2.6/config create mode 100644 target/linux/xscale-2.6/patches/001-gateway_7001.patch (limited to 'target/linux/control/kmod-usb2.control') diff --git a/package/base-files/default/etc/functions.sh b/package/base-files/default/etc/functions.sh index 858dc286ad..d54a346315 100755 --- a/package/base-files/default/etc/functions.sh +++ b/package/base-files/default/etc/functions.sh @@ -61,3 +61,7 @@ config_get() { config_set() { export CONFIG_${1}_${2}="${3}" } + +load_modules() { + sed 's/^[^#]/insmod &/' $* | ash 2>&- || : +} diff --git a/package/base-files/default/etc/init.d/S10boot b/package/base-files/default/etc/init.d/S10boot index 0cc519d8eb..42bb438861 100755 --- a/package/base-files/default/etc/init.d/S10boot +++ b/package/base-files/default/etc/init.d/S10boot @@ -1,4 +1,5 @@ #!/bin/sh +. /etc/functions.sh [ -f /proc/jffs2_bbc ] && echo "S" > /proc/jffs2_bbc vconfig set_name_type VLAN_PLUS_VID_NO_PAD @@ -16,7 +17,7 @@ for iface in $(/sbin/ifconfig -a | awk '{print $1}' | grep eth); do /usr/bin/env -i ACTION=add INTERFACE="$iface" /sbin/hotplug net done -sed 's/^[^#]/insmod &/' /etc/modules /etc/modules.d/* 2>&-|ash +load_modules /etc/modules /etc/modules.d/* ifconfig lo 127.0.0.1 up ifconfig eth0 promisc diff --git a/package/iptables/files/firewall.awk b/package/iptables/files/firewall.awk index 1b63f83862..1a201a0bce 100644 --- a/package/iptables/files/firewall.awk +++ b/package/iptables/files/firewall.awk @@ -1,4 +1,5 @@ BEGIN { + print ". /etc/config/network" print "proto=\"$wan_proto\"" print "[ -z \"$proto\" -o \"$proto\" = \"none\" ] && exit" print "ifname=\"$wan_ifname\"" diff --git a/target/Config.in b/target/Config.in index f20504031c..aad5f9940f 100644 --- a/target/Config.in +++ b/target/Config.in @@ -7,6 +7,7 @@ config LINUX_2_6_ARUBA select mips select LINUX_2_6 select PCI_SUPPORT + select BIG_ENDIAN help Build firmware images for Aruba boards @@ -14,6 +15,7 @@ config LINUX_2_4_AR531X bool "Atheros AR531x [2.4]" select mips select LINUX_2_4 + select BIG_ENDIAN help Build firmware images for Atheros AR531x based boards (e.g. Netgear WGT624, Linksys WRT55AG) @@ -84,6 +86,7 @@ config LINUX_2_6_ARM config LINUX_2_6_ARMEB bool "UNSUPPORTED big-endian arm platform" select LINUX_2_6 + select BIG_ENDIAN select armeb config LINUX_2_6_CRIS @@ -99,6 +102,7 @@ config LINUX_2_6_M68K config LINUX_2_6_PPC bool "UNSUPPORTED powerpc platform" select LINUX_2_6 + select BIG_ENDIAN select powerpc config LINUX_2_6_SH3 @@ -109,6 +113,7 @@ config LINUX_2_6_SH3 config LINUX_2_6_SH3EB bool "UNSUPPORTED big-endian sh3 platform" select LINUX_2_6 + select BIG_ENDIAN select sh3eb config LINUX_2_6_SH4 @@ -119,11 +124,13 @@ config LINUX_2_6_SH4 config LINUX_2_6_SH4EB bool "UNSUPPORTED big-endian sh4 platform" select LINUX_2_6 + select BIG_ENDIAN select sh4eb config LINUX_2_6_SPARC bool "UNSUPPORTED sparc platform" select LINUX_2_6 + select BIG_ENDIAN select sparc endif @@ -145,6 +152,8 @@ config PCI_SUPPORT config PCMCIA_SUPPORT bool +config BIG_ENDIAN + bool # Architecture selection diff --git a/target/linux/Config.in b/target/linux/Config.in index 5257c78ad0..540e2b7364 100644 --- a/target/linux/Config.in +++ b/target/linux/Config.in @@ -10,6 +10,7 @@ menu "Target Root Filesystem" bool "squashfs-lzma" default y depends !LINUX_2_6_ARUBA + depends !LINUX_2_6_XSCALE help Build a squashfs-lzma root filesystem @@ -53,6 +54,13 @@ config PACKAGE_KMOD_IMQ help Kernel support for the Intermediate Queueing device +config PACKAGE_KMOD_IPIP + prompt "kmod-ipip......................... IP in IP encapsulation support" + tristate + default m + help + Kernel module for IP in IP encapsulation + config PACKAGE_KMOD_IPV6 prompt "kmod-ipv6......................... IPv6 support" tristate @@ -294,7 +302,7 @@ config PACKAGE_KMOD_IDE - ide-core - ide-detect - ide-disk - - pdc202old + - pdc202xx_old config PACKAGE_KMOD_LOOP prompt "kmod-loop......................... Loop mount support" @@ -316,7 +324,7 @@ config PACKAGE_KMOD_CRYPTO prompt "CryptoAPI modules" tristate default m - select BUSYBOX_FEATURE_CHECK_TAINTED_MODULE + select BUSYBOX_CONFIG_FEATURE_CHECK_TAINTED_MODULE help Kernel modules for cryptographic algorithms diff --git a/target/linux/Makefile b/target/linux/Makefile index d7744f56e0..bea43514a7 100644 --- a/target/linux/Makefile +++ b/target/linux/Makefile @@ -84,3 +84,5 @@ $(eval $(call kernel_template,2.6,x86,2_6_X86)) $(eval $(call kernel_template,2.4,ar531x,2_4_AR531X)) $(eval $(call kernel_template,2.6,aruba,2_6_ARUBA)) $(eval $(call kernel_template,2.6,au1000,2_6_AU1000)) +$(eval $(call kernel_template,2.6,xscale,2_6_XSCALE)) +$(eval $(call kernel_template,2.6,sibyte,2_6_SIBYTE)) diff --git a/target/linux/aruba-2.6/Makefile b/target/linux/aruba-2.6/Makefile index b5b220d0f2..e21bf818de 100644 --- a/target/linux/aruba-2.6/Makefile +++ b/target/linux/aruba-2.6/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk -LINUX_VERSION:=2.6.16.4 +LINUX_VERSION:=2.6.16.7 LINUX_RELEASE:=1 -LINUX_KERNEL_MD5SUM:=cb675279c9711237a06ebb8379a4da27 +LINUX_KERNEL_MD5SUM:=9682b2bd6e02f3087982d7c3f5ba824e include ../rules.mk include ./config diff --git a/target/linux/aruba-2.6/patches/000-aruba.patch b/target/linux/aruba-2.6/patches/000-aruba.patch index 34fbaf2dec..7bb8a26d7f 100644 --- a/target/linux/aruba-2.6/patches/000-aruba.patch +++ b/target/linux/aruba-2.6/patches/000-aruba.patch @@ -45,7 +45,7 @@ diff -Nur linux-2.6.16/arch/mips/aruba/Makefile linux-2.6.16-owrt/arch/mips/arub +# .S.o: +# $(CC) $(CFLAGS) -c $< -o $*.o + -+obj-y := prom.o setup.o idtIRQ.o irq.o time.o flash_lock.o wdt_merlot.o ++obj-y := prom.o setup.o idtIRQ.o irq.o time.o flash_lock.o +obj-$(CONFIG_SERIAL_8250) += serial.o + +subdir-y += nvram @@ -823,6 +823,7 @@ diff -Nur linux-2.6.16/arch/mips/aruba/setup.c linux-2.6.16-owrt/arch/mips/aruba + */ + +#include ++#include +#include +#include +#include @@ -872,7 +873,6 @@ diff -Nur linux-2.6.16/arch/mips/aruba/setup.c linux-2.6.16-owrt/arch/mips/aruba + +extern char * getenv(char *e); +extern void unlock_ap60_70_flash(void); -+extern void wdt_merlot_disable(void); + +void __init plat_setup(void) +{ @@ -895,8 +895,6 @@ diff -Nur linux-2.6.16/arch/mips/aruba/setup.c linux-2.6.16-owrt/arch/mips/aruba + + printk("BOARD - %s\n",getenv("boardname")); + -+ wdt_merlot_disable(); -+ + return 0; +} + @@ -909,6 +907,8 @@ diff -Nur linux-2.6.16/arch/mips/aruba/setup.c linux-2.6.16-owrt/arch/mips/aruba +{ + return "MIPS IDT32434 - ARUBA"; +} ++ ++EXPORT_SYMBOL(get_system_type); diff -Nur linux-2.6.16/arch/mips/aruba/time.c linux-2.6.16-owrt/arch/mips/aruba/time.c --- linux-2.6.16/arch/mips/aruba/time.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-owrt/arch/mips/aruba/time.c 2006-03-20 14:25:10.000000000 +0100 @@ -1021,40 +1021,6 @@ diff -Nur linux-2.6.16/arch/mips/aruba/time.c linux-2.6.16-owrt/arch/mips/aruba/ + timer_interrupt(irq, NULL, regs); + irq_exit(); +} -diff -Nur linux-2.6.16/arch/mips/aruba/wdt_merlot.c linux-2.6.16-owrt/arch/mips/aruba/wdt_merlot.c ---- linux-2.6.16/arch/mips/aruba/wdt_merlot.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-owrt/arch/mips/aruba/wdt_merlot.c 2006-03-20 14:25:10.000000000 +0100 -@@ -0,0 +1,30 @@ -+#include -+#include -+#include -+ -+void wdt_merlot_disable() -+{ -+ volatile __u32 *wdt_errcs; -+ volatile __u32 *wdt_wtc; -+ volatile __u32 *wdt_ctl; -+ volatile __u32 val; -+ -+ switch (mips_machtype) { -+ case MACH_ARUBA_AP70: -+ wdt_errcs = (__u32 *) 0xb8030030; -+ wdt_wtc = (__u32 *) 0xb803003c; -+ val = *wdt_errcs; -+ val &= ~0x201; -+ *wdt_errcs = val; -+ val = *wdt_wtc; -+ val &= ~0x1; -+ *wdt_wtc = val; -+ break; -+ case MACH_ARUBA_AP65: -+ case MACH_ARUBA_AP60: -+ default: -+ wdt_ctl = (__u32 *) 0xbc003008; -+ *wdt_ctl = 0; -+ break; -+ } -+} diff -Nur linux-2.6.16/arch/mips/Kconfig linux-2.6.16-owrt/arch/mips/Kconfig --- linux-2.6.16/arch/mips/Kconfig 2006-03-20 06:53:29.000000000 +0100 +++ linux-2.6.16-owrt/arch/mips/Kconfig 2006-03-20 14:25:10.000000000 +0100 diff --git a/target/linux/aruba-2.6/patches/004-wdt.patch b/target/linux/aruba-2.6/patches/004-wdt.patch new file mode 100644 index 0000000000..15fbffa043 --- /dev/null +++ b/target/linux/aruba-2.6/patches/004-wdt.patch @@ -0,0 +1,126 @@ +diff -Nur linux-2.6.15.1/drivers/char/watchdog/wdt_merlot.c linux-2.6.15.1-openwrt/drivers/char/watchdog/wdt_merlot.c +--- linux-2.6.15.1/drivers/char/watchdog/wdt_merlot.c 2006-01-26 21:14:02.204626250 -0800 ++++ linux-2.6.15.1-openwrt/drivers/char/watchdog/wdt_merlot.c 2006-02-02 20:31:43.000000000 -0800 +@@ -0,0 +1,110 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++extern unsigned long mips_machtype; ++ ++static unsigned long wdt_is_open; ++static struct timer_list wdt_timer; ++ ++static void wdt_merlot_refresh(void) ++{ ++ volatile __u32 *wdt; ++ switch (mips_machtype) { ++ case MACH_ARUBA_AP70: ++ wdt = (__u32 *) 0xb8030034; ++ *wdt = 0x10000000; ++ break; ++ default: ++ wdt = (__u32 *) 0xbc00300c; ++ *wdt = 0x40000000; ++ break; ++ } ++} ++ ++static void wdt_merlot_timer_fn(unsigned long data) ++{ ++ wdt_merlot_refresh(); ++ if (!test_bit(1, &wdt_is_open)) ++ mod_timer(&wdt_timer, jiffies + HZ); ++} ++ ++static int wdt_merlot_setup_timer(void) ++{ ++ ++ init_timer(&wdt_timer); ++ wdt_timer.function = wdt_merlot_timer_fn; ++ wdt_timer.data = 0; ++ wdt_timer.expires = jiffies + HZ; ++ add_timer(&wdt_timer); ++ return 0; ++} ++ ++static int wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(0, &wdt_is_open)) ++ return -EBUSY; ++ set_bit(1, &wdt_is_open); ++ return nonseekable_open(inode, file); ++} ++ ++static ssize_t wdt_write(struct file *file, const char __user * buf, size_t count, loff_t * ppos) ++{ ++ if (count) /* something was written */ ++ wdt_merlot_refresh(); ++ return count; ++} ++ ++static int wdt_release(struct inode *inode, struct file *file) ++{ ++ clear_bit(0, &wdt_is_open); ++ return 0; ++} ++ ++static struct file_operations wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .write = wdt_write, ++ .open = wdt_open, ++ .release = wdt_release, ++}; ++ ++static struct miscdevice wdt_miscdev = { ++ .minor = WATCHDOG_MINOR, ++ .name = "watchdog", ++ .fops = &wdt_fops, ++}; ++ ++static void __exit wdt_exit(void) ++{ ++ misc_deregister(&wdt_miscdev); ++} ++ ++static int __init wdt_init(void) ++{ ++ int ret; ++ ret = misc_register(&wdt_miscdev); ++ if (ret) { ++ printk(KERN_ERR ++ "wdt: cannot register miscdev on minor=%d (err=%d)\n", ++ WATCHDOG_MINOR, ret); ++ misc_deregister(&wdt_miscdev); ++ goto out; ++ } ++ printk("wdt: registered with refresh\n"); ++ wdt_merlot_refresh(); ++ wdt_merlot_setup_timer(); ++ out: ++ return ret; ++} ++ ++module_init(wdt_init); ++module_exit(wdt_exit); +diff -Nur linux-2.6.15.3/drivers/char/watchdog/Makefile linux-2.6.15.3-openwrt/drivers/char/watchdog/Makefile +--- linux-2.6.15.3/drivers/char/watchdog/Makefile 2006-02-22 10:04:18.596278000 -0800 ++++ linux-2.6.15.3-openwrt/drivers/char/watchdog/Makefile 2006-02-22 10:06:21.400960000 -0800 +@@ -71,5 +71,8 @@ + + # SPARC64 Architecture + ++# Aruba Architecture ++obj-$(CONFIG_MACH_ARUBA) += wdt_merlot.o ++ + # Architecture Independant + obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o diff --git a/target/linux/au1000-2.6/Makefile b/target/linux/au1000-2.6/Makefile index 8c1c67d183..8ba22aa683 100644 --- a/target/linux/au1000-2.6/Makefile +++ b/target/linux/au1000-2.6/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk -LINUX_VERSION:=2.6.16.4 +LINUX_VERSION:=2.6.16.7 LINUX_RELEASE:=1 -LINUX_KERNEL_MD5SUM:=cb675279c9711237a06ebb8379a4da27 +LINUX_KERNEL_MD5SUM:=9682b2bd6e02f3087982d7c3f5ba824e include ../rules.mk include ./config @@ -17,9 +17,10 @@ $(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked @$(CP) config $(LINUX_DIR)/.config touch $@ -$(LINUX_BUILD_DIR)/bzImage: $(LINUX_DIR)/vmlinux - $(MAKE) -C $(LINUX_DIR) V=1 CROSS_COMPILE=$(TARGET_CROSS) ARCH=$(LINUX_KARCH) PATH=$(TARGET_PATH) bzImage - $(CP) $(LINUX_DIR)/vmlinux $@ +$(LINUX_BUILD_DIR)/zImage.flash.srec: $(LINUX_DIR)/arch/mips/boot/compressed/images/zImage.flash.srec $(LINUX_DIR)/arch/mips/boot/compressed/images/zImage.srec + $(MAKE) -C $(LINUX_DIR) V=1 CROSS_COMPILE=$(TARGET_CROSS) ARCH=$(LINUX_KARCH) PATH=$(TARGET_PATH) zImage.flash + $(CP) $(LINUX_DIR)/arch/mips/boot/compressed/images/zImage.flash.srec $(LINUX_DIR)/zImage.flash.srec + $(CP) $(LINUX_DIR)/arch/mips/boot/compressed/images/zImage.srec $(LINUX_DIR)/zImage.srec touch $@ compile: $(LINUX_DIR)/vmlinux diff --git a/target/linux/au1000-2.6/config b/target/linux/au1000-2.6/config index 37dac8ed26..b274fcfd55 100644 --- a/target/linux/au1000-2.6/config +++ b/target/linux/au1000-2.6/config @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.2 -# Tue Apr 11 13:27:02 2006 +# Linux kernel version: 2.6.16.7 +# Sat Apr 29 20:33:29 2006 # CONFIG_MIPS=y @@ -113,7 +113,7 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_64KB is not set CONFIG_CPU_HAS_PREFETCH=y # CONFIG_MIPS_MT is not set -# CONFIG_64BIT_PHYS_ADDR is not set +CONFIG_64BIT_PHYS_ADDR=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y @@ -148,19 +148,21 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_INITRAMFS_SOURCE="" -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_EMBEDDED=y -# CONFIG_KALLSYMS is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y -# CONFIG_ELF_CORE is not set +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -169,10 +171,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 -# CONFIG_SLAB is not set +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -CONFIG_SLOB=y +# CONFIG_SLOB is not set CONFIG_OBSOLETE_INTERMODULE=y # @@ -180,11 +182,11 @@ CONFIG_OBSOLETE_INTERMODULE=y # CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_KMOD is not set +CONFIG_KMOD=y # # Block layer @@ -196,8 +198,8 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set +CONFIG_IOSCHED_DEADLINE=m +CONFIG_IOSCHED_CFQ=m CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_DEADLINE is not set # CONFIG_DEFAULT_CFQ is not set @@ -226,7 +228,7 @@ CONFIG_MMU=y # Executable file formats # CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m +CONFIG_BINFMT_MISC=y CONFIG_TRAD_SIGNALS=y # CONFIG_PM is not set @@ -239,12 +241,12 @@ CONFIG_NET=y # Networking options # # CONFIG_NETDEBUG is not set -CONFIG_PACKET=y +CONFIG_PACKET=m CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y +CONFIG_UNIX=m CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_NET_KEY is not set +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=m CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y @@ -255,33 +257,35 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_FWMARK=y CONFIG_IP_ROUTE_MULTIPATH=y # CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set -# CONFIG_IP_ROUTE_VERBOSE is not set -# CONFIG_IP_PNP is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set CONFIG_NET_IPIP=m CONFIG_NET_IPGRE=m -# CONFIG_NET_IPGRE_BROADCAST is not set -CONFIG_IPSEC_NAT_TRAVERSAL=y +CONFIG_NET_IPGRE_BROADCAST=y +# CONFIG_IPSEC_NAT_TRAVERSAL is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m CONFIG_INET_TUNNEL=m -CONFIG_INET_DIAG=m -CONFIG_INET_TCP_DIAG=m +# CONFIG_INET_DIAG is not set CONFIG_TCP_CONG_ADVANCED=y # # TCP congestion control # -CONFIG_TCP_CONG_BIC=m -CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_BIC=y +# CONFIG_TCP_CONG_CUBIC is not set CONFIG_TCP_CONG_WESTWOOD=m CONFIG_TCP_CONG_HTCP=m CONFIG_TCP_CONG_HSTCP=m CONFIG_TCP_CONG_HYBLA=m -CONFIG_TCP_CONG_VEGAS=y +CONFIG_TCP_CONG_VEGAS=m CONFIG_TCP_CONG_SCALABLE=m # @@ -289,62 +293,67 @@ CONFIG_TCP_CONG_SCALABLE=m # # CONFIG_IP_VS is not set CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_IPV6_TUNNEL is not set +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m +CONFIG_IPV6_TUNNEL=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set -# CONFIG_BRIDGE_NETFILTER is not set +CONFIG_BRIDGE_NETFILTER=y # # Core Netfilter Configuration # -# CONFIG_NETFILTER_NETLINK is not set -CONFIG_NETFILTER_XTABLES=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set CONFIG_NETFILTER_XT_TARGET_MARK=m -# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set -# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set -# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m CONFIG_NETFILTER_XT_MATCH_HELPER=m CONFIG_NETFILTER_XT_MATCH_LENGTH=m CONFIG_NETFILTER_XT_MATCH_LIMIT=m CONFIG_NETFILTER_XT_MATCH_MAC=m CONFIG_NETFILTER_XT_MATCH_MARK=m -# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set -# CONFIG_NETFILTER_XT_MATCH_REALM is not set -# CONFIG_NETFILTER_XT_MATCH_SCTP is not set -CONFIG_NETFILTER_XT_MATCH_STATE=y -# CONFIG_NETFILTER_XT_MATCH_STRING is not set -CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m # # IP: Netfilter Configuration # -CONFIG_IP_NF_CONNTRACK=y +CONFIG_IP_NF_CONNTRACK=m CONFIG_IP_NF_CT_ACCT=y CONFIG_IP_NF_CONNTRACK_MARK=y -# CONFIG_IP_NF_CONNTRACK_EVENTS is not set -# CONFIG_IP_NF_CT_PROTO_SCTP is not set -CONFIG_IP_NF_FTP=y -CONFIG_IP_NF_IRC=y -# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m CONFIG_IP_NF_PPTP=m CONFIG_IP_NF_SIP=m CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_IPRANGE=m CONFIG_IP_NF_MATCH_LAYER7=m -# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set +CONFIG_IP_NF_MATCH_LAYER7_DEBUG=y CONFIG_IP_NF_MATCH_MULTIPORT=m CONFIG_IP_NF_MATCH_IPP2P=m CONFIG_IP_NF_MATCH_TOS=m @@ -355,36 +364,38 @@ CONFIG_IP_NF_MATCH_DSCP=m CONFIG_IP_NF_MATCH_AH_ESP=m CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_MATCH_OWNER=m -# CONFIG_IP_NF_MATCH_ADDRTYPE is not set -# CONFIG_IP_NF_MATCH_HASHLIMIT is not set -# CONFIG_IP_NF_MATCH_POLICY is not set -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_MATCH_POLICY=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_IMQ=m -# CONFIG_IP_NF_TARGET_LOG is not set +CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=y -CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=y -CONFIG_IP_NF_TARGET_REDIRECT=y -# CONFIG_IP_NF_TARGET_NETMAP is not set -# CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=y -CONFIG_IP_NF_NAT_FTP=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m CONFIG_IP_NF_NAT_TFTP=m CONFIG_IP_NF_NAT_AMANDA=m CONFIG_IP_NF_NAT_PPTP=m CONFIG_IP_NF_NAT_SIP=m -CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_TOS=m CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_TTL=m -# CONFIG_IP_NF_TARGET_CLUSTERIP is not set -# CONFIG_IP_NF_RAW is not set -# CONFIG_IP_NF_ARPTABLES is not set +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m CONFIG_IP_NF_SET=m CONFIG_IP_NF_SET_MAX=256 CONFIG_IP_NF_SET_HASHSIZE=1024 @@ -401,24 +412,7 @@ CONFIG_IP_NF_TARGET_SET=m # IPv6: Netfilter Configuration (EXPERIMENTAL) # CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_AHESP is not set -CONFIG_IP6_NF_MATCH_EUI64=m -# CONFIG_IP6_NF_MATCH_POLICY is not set -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_IMQ=m -# CONFIG_IP6_NF_TARGET_LOG is not set -CONFIG_IP6_NF_TARGET_REJECT=m -CONFIG_IP6_NF_MANGLE=m -# CONFIG_IP6_NF_TARGET_HL is not set -# CONFIG_IP6_NF_RAW is not set +# CONFIG_IP6_NF_IPTABLES is not set # # Bridge: Netfilter Configuration @@ -458,17 +452,12 @@ CONFIG_BRIDGE_EBT_ULOG=m # TIPC Configuration (EXPERIMENTAL) # # CONFIG_TIPC is not set -CONFIG_ATM=m -CONFIG_ATM_CLIP=m -CONFIG_ATM_CLIP_NO_ICMP=y -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_ATM_BR2684_IPFILTER=y -CONFIG_BRIDGE=y -CONFIG_VLAN_8021Q=y +# CONFIG_ATM is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m # CONFIG_DECNET is not set -# CONFIG_LLC2 is not set +CONFIG_LLC=m +CONFIG_LLC2=m # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set @@ -491,16 +480,15 @@ CONFIG_NET_SCH_CLK_JIFFIES=y CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_ATM=m CONFIG_NET_SCH_PRIO=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_ESFQ=m +# CONFIG_NET_SCH_ESFQ is not set CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_GRED=m CONFIG_NET_SCH_DSMARK=m -# CONFIG_NET_SCH_NETEM is not set +CONFIG_NET_SCH_NETEM=m CONFIG_NET_SCH_INGRESS=m # @@ -513,67 +501,36 @@ CONFIG_NET_CLS_ROUTE4=m CONFIG_NET_CLS_ROUTE=y CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m -# CONFIG_CLS_U32_PERF is not set -# CONFIG_CLS_U32_MARK is not set +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m -# CONFIG_NET_EMATCH is not set -# CONFIG_NET_CLS_ACT is not set -CONFIG_NET_CLS_POLICE=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +# CONFIG_NET_ACT_IPT is not set +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m # CONFIG_NET_CLS_IND is not set CONFIG_NET_ESTIMATOR=y # # Network testing # -# CONFIG_NET_PKTGEN is not set -CONFIG_HAMRADIO=y - -# -# Packet Radio protocols -# -CONFIG_AX25=m -# CONFIG_AX25_DAMA_SLAVE is not set -# CONFIG_NETROM is not set -# CONFIG_ROSE is not set - -# -# AX.25 network device drivers -# -CONFIG_MKISS=m -# CONFIG_6PACK is not set -# CONFIG_BPQETHER is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -# CONFIG_YAM is not set +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set -CONFIG_BT=m -CONFIG_BT_L2CAP=m -CONFIG_BT_SCO=m -CONFIG_BT_RFCOMM=m -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=m -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_HIDP=m - -# -# Bluetooth device drivers -# -CONFIG_BT_HCIUSB=m -CONFIG_BT_HCIUSB_SCO=y -CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_HCIUART_BCSP=y -# CONFIG_BT_HCIBCM203X is not set -# CONFIG_BT_HCIBPA10X is not set -# CONFIG_BT_HCIBFUSB is not set -# CONFIG_BT_HCIVHCI is not set -CONFIG_IEEE80211=m -# CONFIG_IEEE80211_DEBUG is not set -CONFIG_IEEE80211_CRYPT_WEP=m -CONFIG_IEEE80211_CRYPT_CCMP=m -CONFIG_IEEE80211_CRYPT_TKIP=m +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -582,21 +539,21 @@ CONFIG_IEEE80211_CRYPT_TKIP=m # # Generic Driver Options # -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y # # Connector - unified userspace <-> kernelspace linker # -CONFIG_CONNECTOR=m +# CONFIG_CONNECTOR is not set # # Memory Technology Devices (MTD) # CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_CONCAT=y CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_CMDLINE_PARTS is not set @@ -628,7 +585,7 @@ CONFIG_MTD_CFI_I1=y CONFIG_MTD_CFI_I2=y # CONFIG_MTD_CFI_I4 is not set # CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CFI_AMDSTD=y CONFIG_MTD_CFI_AMDSTD_RETRY=0 # CONFIG_MTD_CFI_STAA is not set @@ -641,11 +598,10 @@ CONFIG_MTD_CFI_UTIL=y # # Mapping drivers for chip access # -CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set # CONFIG_MTD_PHYSMAP is not set # CONFIG_MTD_ALCHEMY is not set CONFIG_MTD_MTX1=y -# CONFIG_MTD_PCI is not set # CONFIG_MTD_PLATRAM is not set # @@ -697,8 +653,9 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_UB is not set -# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -712,7 +669,7 @@ CONFIG_BLK_DEV_RAM_COUNT=16 # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=m -CONFIG_SCSI_PROC_FS=y +# CONFIG_SCSI_PROC_FS is not set # # SCSI support type (disk, tape, CD-ROM) @@ -721,14 +678,14 @@ CONFIG_BLK_DEV_SD=m # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set +CONFIG_CHR_DEV_SG=m # CONFIG_CHR_DEV_SCH is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set # @@ -798,8 +755,9 @@ CONFIG_BLK_DEV_SD=m # Network device support # CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set +# CONFIG_IFB is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m # CONFIG_EQUALIZER is not set CONFIG_IMQ=m # CONFIG_IMQ_BEHAVIOR_AA is not set @@ -837,26 +795,7 @@ CONFIG_MIPS_AU1X00_ENET=y # # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_AMD8111_ETH is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_B44 is not set -# CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set -# CONFIG_EEPRO100 is not set -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_8139CP is not set -# CONFIG_8139TOO is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_LAN_SAA9730 is not set +# CONFIG_NET_PCI is not set # # Ethernet (1000 Mbit) @@ -872,7 +811,6 @@ CONFIG_NET_PCI=y # CONFIG_SKGE is not set # CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set -# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set @@ -896,20 +834,15 @@ CONFIG_NET_RADIO=y # # Obsolete Wireless cards support (pre-802.11) # -# CONFIG_STRIP is not set +CONFIG_STRIP=m # # Wireless 802.11b ISA/PCI cards support # -CONFIG_IPW2100=m -CONFIG_IPW2100_MONITOR=y -# CONFIG_IPW2100_DEBUG is not set -CONFIG_IPW2200=m -# CONFIG_IPW2200_DEBUG is not set CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_TMD_HERMES=m -CONFIG_NORTEL_HERMES=m +# CONFIG_PLX_HERMES is not set +# CONFIG_TMD_HERMES is not set +# CONFIG_NORTEL_HERMES is not set CONFIG_PCI_HERMES=m CONFIG_ATMEL=m CONFIG_PCI_ATMEL=m @@ -918,49 +851,27 @@ CONFIG_PCI_ATMEL=m # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support # CONFIG_PRISM54=m -CONFIG_HOSTAP=m -CONFIG_HOSTAP_FIRMWARE=y -CONFIG_HOSTAP_FIRMWARE_NVRAM=y -CONFIG_HOSTAP_PLX=m -CONFIG_HOSTAP_PCI=m +# CONFIG_HOSTAP is not set CONFIG_NET_WIRELESS=y # # Wan interfaces # # CONFIG_WAN is not set - -# -# ATM drivers -# -CONFIG_ATM_DUMMY=m -CONFIG_ATM_TCP=m -# CONFIG_ATM_LANAI is not set -# CONFIG_ATM_ENI is not set -# CONFIG_ATM_FIRESTREAM is not set -# CONFIG_ATM_ZATM is not set -# CONFIG_ATM_NICSTAR is not set -# CONFIG_ATM_IDT77252 is not set -# CONFIG_ATM_AMBASSADOR is not set -# CONFIG_ATM_HORIZON is not set -# CONFIG_ATM_IA is not set -# CONFIG_ATM_FORE200E_MAYBE is not set -# CONFIG_ATM_HE is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set +CONFIG_PPP_MULTILINK=y CONFIG_PPP_FILTER=y CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_SYNC_TTY=m CONFIG_PPP_DEFLATE=m CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_MPPE=m +# CONFIG_PPP_MPPE is not set CONFIG_PPPOE=m -CONFIG_PPPOATM=m # CONFIG_SLIP is not set # CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set +CONFIG_SHAPER=m # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -978,7 +889,7 @@ CONFIG_PPPOATM=m # # Input device support # -CONFIG_INPUT=m +CONFIG_INPUT=y # # Userland interfaces @@ -986,7 +897,7 @@ CONFIG_INPUT=m # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set # @@ -1007,7 +918,9 @@ CONFIG_INPUT_EVDEV=m # # Character devices # -# CONFIG_VT is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -1015,10 +928,10 @@ CONFIG_INPUT_EVDEV=m # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=2 -CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_AU1X00 is not set +CONFIG_SERIAL_8250_AU1X00=y # # Non-8250 serial port support @@ -1038,7 +951,25 @@ CONFIG_UNIX98_PTYS=y # # Watchdog Cards # -# CONFIG_WATCHDOG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_MTX1_WATCHDOG=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set # CONFIG_RTC is not set # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set @@ -1090,29 +1021,7 @@ CONFIG_UNIX98_PTYS=y # # Multimedia devices # -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# - -# -# Video Adapters -# -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_MXB is not set -# CONFIG_VIDEO_DPC is not set -# CONFIG_VIDEO_HEXIUM_ORION is not set -# CONFIG_VIDEO_HEXIUM_GEMINI is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set +# CONFIG_VIDEO_DEV is not set # # Digital Video Broadcasting Devices @@ -1124,94 +1033,16 @@ CONFIG_VIDEO_DEV=m # # CONFIG_FB is not set +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + # # Sound # -CONFIG_SOUND=m - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=m -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -CONFIG_SND_HWDEP=m -CONFIG_SND_RAWMIDI=m -# CONFIG_SND_SEQUENCER is not set -# CONFIG_SND_MIXER_OSS is not set -# CONFIG_SND_PCM_OSS is not set -# CONFIG_SND_DYNAMIC_MINORS is not set -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set - -# -# Generic devices -# -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set - -# -# PCI devices -# -# CONFIG_SND_AD1889 is not set -# CONFIG_SND_ALI5451 is not set -# CONFIG_SND_ATIIXP is not set -# CONFIG_SND_ATIIXP_MODEM is not set -# CONFIG_SND_AU8810 is not set -# CONFIG_SND_AU8820 is not set -# CONFIG_SND_AU8830 is not set -# CONFIG_SND_AZT3328 is not set -# CONFIG_SND_BT87X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_CS4281 is not set -# CONFIG_SND_CS46XX is not set -# CONFIG_SND_EMU10K1 is not set -# CONFIG_SND_EMU10K1X is not set -# CONFIG_SND_ENS1370 is not set -# CONFIG_SND_ENS1371 is not set -# CONFIG_SND_ES1938 is not set -# CONFIG_SND_ES1968 is not set -# CONFIG_SND_FM801 is not set -# CONFIG_SND_HDA_INTEL is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_HDSPM is not set -# CONFIG_SND_ICE1712 is not set -# CONFIG_SND_ICE1724 is not set -# CONFIG_SND_INTEL8X0 is not set -# CONFIG_SND_INTEL8X0M is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_MAESTRO3 is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_PCXHR is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set -# CONFIG_SND_SONICVIBES is not set -# CONFIG_SND_TRIDENT is not set -# CONFIG_SND_VIA82XX is not set -# CONFIG_SND_VIA82XX_MODEM is not set -# CONFIG_SND_VX222 is not set -# CONFIG_SND_YMFPCI is not set - -# -# ALSA MIPS devices -# -# CONFIG_SND_AU1X00 is not set - -# -# USB devices -# -CONFIG_SND_USB_AUDIO=m - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set +# CONFIG_SOUND is not set # # USB support @@ -1232,20 +1063,15 @@ CONFIG_USB_DEVICEFS=y # # USB Host Controller Drivers # -CONFIG_USB_EHCI_HCD=m -# CONFIG_USB_EHCI_SPLIT_ISO is not set -# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_HCD is not set # CONFIG_USB_ISP116X_HCD is not set -CONFIG_USB_OHCI_HCD=m -# CONFIG_USB_OHCI_BIG_ENDIAN is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y -CONFIG_USB_UHCI_HCD=m +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set # CONFIG_USB_SL811_HCD is not set # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m @@ -1258,15 +1084,14 @@ CONFIG_USB_PRINTER=m # CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_USBAT is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_STORAGE_ALAUDA is not set -# CONFIG_USB_STORAGE_ONETOUCH is not set # CONFIG_USB_LIBUSUAL is not set # @@ -1297,34 +1122,36 @@ CONFIG_USB_STORAGE=m # # USB Imaging devices # -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m # # USB Multimedia devices # -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_PWC is not set +CONFIG_USB_DABUSB=m + +# +# Video4Linux support is needed for USB Multimedia device support +# # # USB Network Adapters # -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_ZD1201 is not set -# CONFIG_USB_MON is not set +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=m +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_ZD1201=m +CONFIG_USB_MON=y # # USB port drivers @@ -1334,62 +1161,58 @@ CONFIG_USB_STORAGE=m # USB Serial Converter support # CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_AIRPRIME is not set +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m # CONFIG_USB_SERIAL_ANYDATA is not set CONFIG_USB_SERIAL_BELKIN=m -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_CP2101 is not set -# CONFIG_USB_SERIAL_CYPRESS_M8 is not set -# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_USB_SERIAL_VISOR=m -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_EDGEPORT_TI is not set -# CONFIG_USB_SERIAL_GARMIN is not set -# CONFIG_USB_SERIAL_IPW is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m # CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_KOBIL_SCT is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m CONFIG_USB_SERIAL_PL2303=m -# CONFIG_USB_SERIAL_HP4X is not set -# CONFIG_USB_SERIAL_SAFE is not set -# CONFIG_USB_SERIAL_TI is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y # # USB Miscellaneous drivers # -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_SISUSBVGA is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TEST is not set +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_LD=m +CONFIG_USB_TEST=m # # USB DSL modem support # -CONFIG_USB_ATM=m -CONFIG_USB_SPEEDTOUCH=m -# CONFIG_USB_CXACRU is not set -CONFIG_USB_UEAGLEATM=m -# CONFIG_USB_XUSBATM is not set # # USB Gadget Support @@ -1413,34 +1236,26 @@ CONFIG_USB_UEAGLEATM=m # # File systems # -CONFIG_EXT2_FS=m -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT2_FS is not set CONFIG_EXT3_FS=m # CONFIG_EXT3_FS_XATTR is not set CONFIG_JBD=m # CONFIG_JBD_DEBUG is not set -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_REISERFS_FS_XATTR is not set -CONFIG_JFS_FS=m -# CONFIG_JFS_POSIX_ACL is not set -# CONFIG_JFS_SECURITY is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_FS_POSIX_ACL is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=m +CONFIG_XFS_EXPORT=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set # CONFIG_OCFS2_FS is not set -CONFIG_MINIX_FS=m -# CONFIG_ROMFS_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=m CONFIG_INOTIFY=y # CONFIG_QUOTA is not set -# CONFIG_DNOTIFY is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set @@ -1455,26 +1270,28 @@ CONFIG_INOTIFY=y # DOS/FAT/NT Filesystems # CONFIG_FAT_FS=m -# CONFIG_MSDOS_FS is not set +CONFIG_MSDOS_FS=m CONFIG_VFAT_FS=m CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y # # Pseudo filesystems # CONFIG_PROC_FS=y -# CONFIG_PROC_KCORE is not set +CONFIG_PROC_KCORE=y CONFIG_DEVFS_FS=y CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVFS_DEBUG=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_RELAYFS_FS is not set -# CONFIG_CONFIGFS_FS is not set +CONFIG_CONFIGFS_FS=y # # Miscellaneous filesystems @@ -1490,15 +1307,12 @@ CONFIG_RAMFS=y CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_SUMMARY is not set -CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set -# CONFIG_JFFS2_CMODE_NONE is not set -CONFIG_JFFS2_CMODE_PRIORITY=y -# CONFIG_JFFS2_CMODE_SIZE is not set -# CONFIG_CRAMFS is not set +CONFIG_CRAMFS=m CONFIG_SQUASHFS=y # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 @@ -1512,24 +1326,32 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # # Network File Systems # -CONFIG_NFS_FS=m +CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y # CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_LOCKD=m +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +# CONFIG_ROOT_NFS is not set +CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=m -CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_XATTR is not set +CONFIG_CIFS_STATS=y +# CONFIG_CIFS_STATS2 is not set +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1539,28 +1361,13 @@ CONFIG_CIFS=m # # Partition Types # -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -CONFIG_MAC_PARTITION=y +# CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -# CONFIG_EFI_PARTITION is not set # # Native Language Support # -CONFIG_NLS=m +CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=m # CONFIG_NLS_CODEPAGE_737 is not set @@ -1610,11 +1417,11 @@ CONFIG_NLS_UTF8=m # Kernel hacking # # CONFIG_PRINTK_TIME is not set -# CONFIG_MAGIC_SYSRQ is not set +CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_KERNEL is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd console=ttyS0,115200" +CONFIG_CMDLINE="init=/etc/preinit" # # Security options @@ -1627,29 +1434,29 @@ CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 init=/etc/preinit # CONFIG_CRYPTO=y CONFIG_CRYPTO_HMAC=y -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_MD4 is not set -CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=m -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_TGR192 is not set -CONFIG_CRYPTO_DES=m -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_MICHAEL_MIC=m -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_TEST=m # # Hardware crypto devices @@ -1659,8 +1466,12 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # Library routines # CONFIG_CRC_CCITT=m -CONFIG_CRC16=m +CONFIG_CRC16=y CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set +CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m diff --git a/target/linux/au1000-2.6/patches/002-mtx1_flash_map.patch b/target/linux/au1000-2.6/patches/002-mtx1_flash_map.patch new file mode 100644 index 0000000000..9a6b05b146 --- /dev/null +++ b/target/linux/au1000-2.6/patches/002-mtx1_flash_map.patch @@ -0,0 +1,16 @@ +diff -urN linux-2.6.16.7/drivers/mtd/maps/alchemy-flash.c linux-2.6.16.7.new/drivers/mtd/maps/alchemy-flash.c +--- linux-2.6.16.7/drivers/mtd/maps/alchemy-flash.c 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7.new/drivers/mtd/maps/alchemy-flash.c 2006-04-20 19:16:26.000000000 +0200 +@@ -105,6 +105,12 @@ + #define USE_LOCAL_ACCESSORS /* why? */ + #endif + ++#ifdef CONFIG_MIPS_MTX1 ++#define BOARD_MAP_NAME "MTX-1 Flash" ++#define BOARD_FLASH_SIZE 0x04000000 /* 64MB */ ++#define BOARD_FLASH_WIDTH 4 /* 32-bits */ ++#endif ++ + static struct map_info alchemy_map = { + .name = BOARD_MAP_NAME, + }; diff --git a/target/linux/au1000-2.6/patches/003-zImage.patch b/target/linux/au1000-2.6/patches/003-zImage.patch new file mode 100644 index 0000000000..1d4c6ad5d1 --- /dev/null +++ b/target/linux/au1000-2.6/patches/003-zImage.patch @@ -0,0 +1,1364 @@ +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/au1xxx/head.S linux-2.6.16.7.new/arch/mips/boot/compressed/au1xxx/head.S +--- linux-2.6.16.7/arch/mips/boot/compressed/au1xxx/head.S 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/au1xxx/head.S 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,119 @@ ++/* ++ * arch/mips/kernel/head.S ++ * ++ * 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. ++ * ++ * Copyright (C) 1994, 1995 Waldorf Electronics ++ * Written by Ralf Baechle and Andreas Busse ++ * Copyright (C) 1995 - 1999 Ralf Baechle ++ * Copyright (C) 1996 Paul M. Antoine ++ * Modified for DECStation and hence R3000 support by Paul M. Antoine ++ * Further modifications by David S. Miller and Harald Koerfgen ++ * Copyright (C) 1999 Silicon Graphics, Inc. ++ * ++ * Head.S contains the MIPS exception handler and startup code. ++ * ++ ************************************************************************** ++ * 9 Nov, 2000. ++ * Added Cache Error exception handler and SBDDP EJTAG debug exception. ++ * ++ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com ++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. ++ ************************************************************************** ++ */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define IndexInvalidate_I 0x00 ++#define IndexWriteBack_D 0x01 ++ ++ .set noreorder ++ .cprestore ++ LEAF(start) ++start: ++ bal locate ++ nop ++locate: ++ subu s8, ra, 8 /* Where we were loaded */ ++ la sp, (.stack + 8192) ++ ++ move s0, a0 /* Save boot rom start args */ ++ move s1, a1 ++ move s2, a2 ++ move s3, a3 ++ ++ la a0, start /* Where we were linked to run */ ++ ++ move a1, s8 ++ la a2, _edata ++ subu t1, a2, a0 ++ srl t1, t1, 2 ++ ++ /* copy text section */ ++ li t0, 0 ++1: lw v0, 0(a1) ++ nop ++ sw v0, 0(a0) ++ xor t0, t0, v0 ++ addu a0, 4 ++ bne a2, a0, 1b ++ addu a1, 4 ++ ++ /* Clear BSS */ ++ la a0, _edata ++ la a2, _end ++2: sw zero, 0(a0) ++ bne a2, a0, 2b ++ addu a0, 4 ++ ++ /* push the D-Cache and invalidate I-Cache */ ++ li k0, 0x80000000 # start address ++ li k1, 0x80004000 # end address (16KB I-Cache) ++ subu k1, 128 ++ ++1: ++ .set mips3 ++ cache IndexWriteBack_D, 0(k0) ++ cache IndexWriteBack_D, 32(k0) ++ cache IndexWriteBack_D, 64(k0) ++ cache IndexWriteBack_D, 96(k0) ++ cache IndexInvalidate_I, 0(k0) ++ cache IndexInvalidate_I, 32(k0) ++ cache IndexInvalidate_I, 64(k0) ++ cache IndexInvalidate_I, 96(k0) ++ .set mips0 ++ ++ bne k0, k1, 1b ++ addu k0, k0, 128 ++ /* done */ ++ ++ move a0, s8 /* load address */ ++ move a1, t1 /* length in words */ ++ move a2, t0 /* checksum */ ++ move a3, sp ++ ++ la ra, 1f ++ la k0, decompress_kernel ++ jr k0 ++ nop ++1: ++ ++ move a0, s0 ++ move a1, s1 ++ move a2, s2 ++ move a3, s3 ++ li k0, KERNEL_ENTRY ++ jr k0 ++ nop ++3: ++ b 3b ++ END(start) ++ .comm .stack,4096*2,4 +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/au1xxx/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/au1xxx/Makefile +--- linux-2.6.16.7/arch/mips/boot/compressed/au1xxx/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/au1xxx/Makefile 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,110 @@ ++# arch/mips/boot/compressed/au1xxx/Makefile ++# ++# Makefile for AMD Alchemy Semiconductor Au1x based boards. ++# All of the boot loader code was derived from the ppc ++# boot code. ++# ++# Copyright 2001,2002 MontaVista Software Inc. ++# ++# Author: Mark A. Greer ++# mgreer@mvista.com ++# ++# Copyright 2004 Embedded Alley Solutions, Inc ++# Ported and modified for mips 2.6 support by ++# Pete Popov ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License as published by the ++# Free Software Foundation; either version 2 of the License, or (at your ++# option) any later version. ++ ++boot := arch/mips/boot ++compressed := $(boot)/compressed ++utils := $(compressed)/utils ++lib := $(compressed)/lib ++images := $(compressed)/images ++common := $(compressed)/common ++ ++######################################################################### ++# START BOARD SPECIFIC VARIABLES ++ ++# These two variables control where the zImage is stored ++# in flash and loaded in memory. It only controls how the srec ++# file is generated, the code is the same. ++RAM_RUN_ADDR = 0x81000000 ++ ++ifdef CONFIG_MIPS_XXS1500 ++FLASH_LOAD_ADDR = 0xBF000000 ++else ++FLASH_LOAD_ADDR = 0xBFD00000 ++endif ++ ++# These two variables specify the free ram region ++# that can be used for temporary malloc area ++AVAIL_RAM_START=0x80500000 ++AVAIL_RAM_END=0x80900000 ++ ++# This one must match the LOADADDR in arch/mips/Makefile! ++LOADADDR=0x80100000 ++ ++# WARNING WARNING WARNING ++# Note that with a LOADADDR of 0x80100000 and AVAIL_RAM_START of ++# 0x80500000, the max decompressed kernel size can be 4MB. Else we ++# start overwriting ourselve. You can change these vars as needed; ++# it would be much better if we just figured everything out on the fly. ++ ++# END BOARD SPECIFIC VARIABLES ++######################################################################### ++ ++OBJECTS := $(obj)/head.o $(common)/misc-common.o $(common)/misc-simple.o \ ++ $(common)/au1k_uart.o ++LIBS := $(lib)/lib.a ++ ++ENTRY := $(utils)/entry ++OFFSET := $(utils)/offset ++SIZE := $(utils)/size ++ ++LD_ARGS := -T $(compressed)/ld.script -Ttext $(RAM_RUN_ADDR) -Bstatic ++ ++ifdef CONFIG_CPU_LITTLE_ENDIAN ++OBJCOPY_ARGS = -O elf32-tradlittlemips ++else ++OBJCOPY_ARGS = -O elf32-tradbigmips ++endif ++ ++$(obj)/head.o: $(obj)/head.S $(TOPDIR)/vmlinux ++ $(CC) -I $(TOPDIR)/include $(AFLAGS) \ ++ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \ ++ -c -o $*.o $< ++ ++$(common)/misc-simple.o: ++ $(CC) -I $(TOPDIR)/include $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ ++ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \ ++ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \ ++ -DLOADADDR=$(LOADADDR) \ ++ -DZIMAGE_SIZE=0 -c -o $@ $*.c ++ ++$(obj)/zvmlinux: $(OBJECTS) $(LIBS) $(srctree)/$(compressed)/ld.script $(images)/vmlinux.gz $(common)/dummy.o ++ $(OBJCOPY) \ ++ --add-section=.image=$(images)/vmlinux.gz \ ++ --set-section-flags=.image=contents,alloc,load,readonly,data \ ++ $(common)/dummy.o $(common)/image.o ++ $(LD) $(LD_ARGS) -o $@ $(OBJECTS) $(common)/image.o $(LIBS) ++ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R __kcrctab -R __ksymtab_strings \ ++ -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap ++ ++# Here we manipulate the image in order to get it the necessary ++# srecord file we need. ++zImage: $(obj)/zvmlinux ++ mv $(obj)/zvmlinux $(images)/zImage ++ $(OBJCOPY) -O srec $(images)/zImage $(images)/zImage.srec ++ $(OBJCOPY) -O binary $(images)/zImage $(images)/zImage.bin ++ ++zImage.flash: zImage ++ ( \ ++ flash=${FLASH_LOAD_ADDR} ; \ ++ ram=${RAM_RUN_ADDR} ; \ ++ adjust=$$[ $$flash - $$ram ] ; \ ++ $(OBJCOPY) -O srec --adjust-vma `printf '0x%08x' $$adjust` \ ++ $(images)/zImage $(images)/zImage.flash.srec ; \ ++ ) +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/au1k_uart.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/au1k_uart.c +--- linux-2.6.16.7/arch/mips/boot/compressed/common/au1k_uart.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/au1k_uart.c 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,103 @@ ++/* ++ * BRIEF MODULE DESCRIPTION ++ * Simple Au1000 uart routines. ++ * ++ * Copyright 2001 MontaVista Software Inc. ++ * Author: MontaVista Software, Inc. ++ * ppopov@mvista.com or source@mvista.com ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++#include ++#include ++#include ++#include "ns16550.h" ++ ++typedef unsigned char uint8; ++typedef unsigned int uint32; ++ ++#define UART16550_BAUD_2400 2400 ++#define UART16550_BAUD_4800 4800 ++#define UART16550_BAUD_9600 9600 ++#define UART16550_BAUD_19200 19200 ++#define UART16550_BAUD_38400 38400 ++#define UART16550_BAUD_57600 57600 ++#define UART16550_BAUD_115200 115200 ++ ++#define UART16550_PARITY_NONE 0 ++#define UART16550_PARITY_ODD 0x08 ++#define UART16550_PARITY_EVEN 0x18 ++#define UART16550_PARITY_MARK 0x28 ++#define UART16550_PARITY_SPACE 0x38 ++ ++#define UART16550_DATA_5BIT 0x0 ++#define UART16550_DATA_6BIT 0x1 ++#define UART16550_DATA_7BIT 0x2 ++#define UART16550_DATA_8BIT 0x3 ++ ++#define UART16550_STOP_1BIT 0x0 ++#define UART16550_STOP_2BIT 0x4 ++ ++/* It would be nice if we had a better way to do this. ++ * It could be a variable defined in one of the board specific files. ++ */ ++#undef UART_BASE ++#ifdef CONFIG_COGENT_CSB250 ++#define UART_BASE UART3_ADDR ++#else ++#define UART_BASE UART0_ADDR ++#endif ++ ++/* memory-mapped read/write of the port */ ++#define UART16550_READ(y) (au_readl(UART_BASE + y) & 0xff) ++#define UART16550_WRITE(y,z) (au_writel(z&0xff, UART_BASE + y)) ++ ++/* ++ * We use uart 0, which is already initialized by ++ * yamon. ++ */ ++volatile struct NS16550 * ++serial_init(int chan) ++{ ++ volatile struct NS16550 *com_port; ++ com_port = (struct NS16550 *) UART_BASE; ++ return (com_port); ++} ++ ++void ++serial_putc(volatile struct NS16550 *com_port, unsigned char c) ++{ ++ while ((UART16550_READ(UART_LSR)&0x40) == 0); ++ UART16550_WRITE(UART_TX, c); ++} ++ ++unsigned char ++serial_getc(volatile struct NS16550 *com_port) ++{ ++ while((UART16550_READ(UART_LSR) & 0x1) == 0); ++ return UART16550_READ(UART_RX); ++} ++ ++int ++serial_tstc(volatile struct NS16550 *com_port) ++{ ++ return((UART16550_READ(UART_LSR) & LSR_DR) != 0); ++} +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/dummy.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/dummy.c +--- linux-2.6.16.7/arch/mips/boot/compressed/common/dummy.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/dummy.c 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,4 @@ ++int main(void) ++{ ++ return 0; ++} +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/common/Makefile +--- linux-2.6.16.7/arch/mips/boot/compressed/common/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/Makefile 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,14 @@ ++# ++# arch/mips/boot/compressed/common/Makefile ++# ++# 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. ++# ++# Tom Rini January 2001 ++# ++# Pete Popov, 2004 ++# ++ ++lib-y := misc-common.o no_initrd.o dummy.o ++lib-$(CONFIG_SOC_AU1X00) += au1k_uart.o +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/misc-common.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/misc-common.c +--- linux-2.6.16.7/arch/mips/boot/compressed/common/misc-common.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/misc-common.c 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,434 @@ ++/* ++ * arch/mips/boot/compressed/common/misc-common.c ++ * ++ * Misc. bootloader code (almost) all platforms can use ++ * ++ * Author: Johnnie Peters ++ * Editor: Tom Rini ++ * ++ * Derived from arch/ppc/boot/prep/misc.c ++ * ++ * Ported by Pete Popov to ++ * support mips board(s). I also got rid of the vga console ++ * code. ++ * ++ * Copyright 2000-2001 MontaVista Software Inc. ++ * ++ * Ported to MIPS 2.6 by Pete Popov, ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include /* for va_ bits */ ++#include ++#include ++#include ++ ++extern char *avail_ram; ++extern char *end_avail; ++extern char _end[]; ++ ++void puts(const char *); ++void putc(const char c); ++void puthex(unsigned long val); ++void _bcopy(char *src, char *dst, int len); ++void gunzip(void *, int, unsigned char *, int *); ++static int _cvt(unsigned long val, char *buf, long radix, char *digits); ++ ++void _vprintk(void(*)(const char), const char *, va_list ap); ++ ++struct NS16550 *com_port; ++ ++int serial_tstc(volatile struct NS16550 *); ++unsigned char serial_getc(volatile struct NS16550 *); ++void serial_putc(volatile struct NS16550 *, unsigned char); ++ ++void pause(void) ++{ ++ puts("pause\n"); ++} ++ ++void exit(void) ++{ ++ puts("exit\n"); ++ while(1); ++} ++ ++int tstc(void) ++{ ++ return (serial_tstc(com_port)); ++} ++ ++int getc(void) ++{ ++ while (1) { ++ if (serial_tstc(com_port)) ++ return (serial_getc(com_port)); ++ } ++} ++ ++void ++putc(const char c) ++{ ++ serial_putc(com_port, c); ++ if ( c == '\n' ) ++ serial_putc(com_port, '\r'); ++} ++ ++void puts(const char *s) ++{ ++ char c; ++ while ( ( c = *s++ ) != '\0' ) { ++ serial_putc(com_port, c); ++ if ( c == '\n' ) serial_putc(com_port, '\r'); ++ } ++} ++ ++void error(char *x) ++{ ++ puts("\n\n"); ++ puts(x); ++ puts("\n\n -- System halted"); ++ ++ while(1); /* Halt */ ++} ++ ++static void *zalloc(unsigned size) ++{ ++ void *p = avail_ram; ++ ++ size = (size + 7) & -8; ++ avail_ram += size; ++ if (avail_ram > end_avail) { ++ puts("oops... out of memory\n"); ++ pause(); ++ } ++ return p; ++} ++ ++ ++#define HEAD_CRC 2 ++#define EXTRA_FIELD 4 ++#define ORIG_NAME 8 ++#define COMMENT 0x10 ++#define RESERVED 0xe0 ++ ++#define DEFLATED 8 ++ ++void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) ++{ ++ z_stream s; ++ int r, i, flags; ++ ++ /* skip header */ ++ i = 10; ++ flags = src[3]; ++ if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) { ++ puts("bad gzipped data\n"); ++ exit(); ++ } ++ if ((flags & EXTRA_FIELD) != 0) ++ i = 12 + src[10] + (src[11] << 8); ++ if ((flags & ORIG_NAME) != 0) ++ while (src[i++] != 0) ++ ; ++ if ((flags & COMMENT) != 0) ++ while (src[i++] != 0) ++ ; ++ if ((flags & HEAD_CRC) != 0) ++ i += 2; ++ if (i >= *lenp) { ++ puts("gunzip: ran out of data in header\n"); ++ exit(); ++ } ++ ++ /* Initialize ourself. */ ++ s.workspace = zalloc(zlib_inflate_workspacesize()); ++ r = zlib_inflateInit2(&s, -MAX_WBITS); ++ if (r != Z_OK) { ++ puts("zlib_inflateInit2 returned "); puthex(r); puts("\n"); ++ exit(); ++ } ++ s.next_in = src + i; ++ s.avail_in = *lenp - i; ++ s.next_out = dst; ++ s.avail_out = dstlen; ++ r = zlib_inflate(&s, Z_FINISH); ++ if (r != Z_OK && r != Z_STREAM_END) { ++ puts("inflate returned "); puthex(r); puts("\n"); ++ exit(); ++ } ++ *lenp = s.next_out - (unsigned char *) dst; ++ zlib_inflateEnd(&s); ++} ++ ++void ++puthex(unsigned long val) ++{ ++ ++ unsigned char buf[10]; ++ int i; ++ for (i = 7; i >= 0; i--) ++ { ++ buf[i] = "0123456789ABCDEF"[val & 0x0F]; ++ val >>= 4; ++ } ++ buf[8] = '\0'; ++ puts(buf); ++} ++ ++#define FALSE 0 ++#define TRUE 1 ++ ++void ++_printk(char const *fmt, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, fmt); ++ _vprintk(putc, fmt, ap); ++ va_end(ap); ++ return; ++} ++ ++#define is_digit(c) ((c >= '0') && (c <= '9')) ++ ++void ++_vprintk(void(*putc)(const char), const char *fmt0, va_list ap) ++{ ++ char c, sign, *cp = 0; ++ int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right; ++ char buf[32]; ++ long val; ++ while ((c = *fmt0++)) ++ { ++ if (c == '%') ++ { ++ c = *fmt0++; ++ left_prec = right_prec = pad_on_right = 0; ++ if (c == '-') ++ { ++ c = *fmt0++; ++ pad_on_right++; ++ } ++ if (c == '0') ++ { ++ zero_fill = TRUE; ++ c = *fmt0++; ++ } else ++ { ++ zero_fill = FALSE; ++ } ++ while (is_digit(c)) ++ { ++ left_prec = (left_prec * 10) + (c - '0'); ++ c = *fmt0++; ++ } ++ if (c == '.') ++ { ++ c = *fmt0++; ++ zero_fill++; ++ while (is_digit(c)) ++ { ++ right_prec = (right_prec * 10) + (c - '0'); ++ c = *fmt0++; ++ } ++ } else ++ { ++ right_prec = left_prec; ++ } ++ sign = '\0'; ++ switch (c) ++ { ++ case 'd': ++ case 'x': ++ case 'X': ++ val = va_arg(ap, long); ++ switch (c) ++ { ++ case 'd': ++ if (val < 0) ++ { ++ sign = '-'; ++ val = -val; ++ } ++ length = _cvt(val, buf, 10, "0123456789"); ++ break; ++ case 'x': ++ length = _cvt(val, buf, 16, "0123456789abcdef"); ++ break; ++ case 'X': ++ length = _cvt(val, buf, 16, "0123456789ABCDEF"); ++ break; ++ } ++ cp = buf; ++ break; ++ case 's': ++ cp = va_arg(ap, char *); ++ length = strlen(cp); ++ break; ++ case 'c': ++ c = va_arg(ap, long /*char*/); ++ (*putc)(c); ++ continue; ++ default: ++ (*putc)('?'); ++ } ++ pad = left_prec - length; ++ if (sign != '\0') ++ { ++ pad--; ++ } ++ if (zero_fill) ++ { ++ c = '0'; ++ if (sign != '\0') ++ { ++ (*putc)(sign); ++ sign = '\0'; ++ } ++ } else ++ { ++ c = ' '; ++ } ++ if (!pad_on_right) ++ { ++ while (pad-- > 0) ++ { ++ (*putc)(c); ++ } ++ } ++ if (sign != '\0') ++ { ++ (*putc)(sign); ++ } ++ while (length-- > 0) ++ { ++ (*putc)(c = *cp++); ++ if (c == '\n') ++ { ++ (*putc)('\r'); ++ } ++ } ++ if (pad_on_right) ++ { ++ while (pad-- > 0) ++ { ++ (*putc)(c); ++ } ++ } ++ } else ++ { ++ (*putc)(c); ++ if (c == '\n') ++ { ++ (*putc)('\r'); ++ } ++ } ++ } ++} ++ ++int ++_cvt(unsigned long val, char *buf, long radix, char *digits) ++{ ++ char temp[80]; ++ char *cp = temp; ++ int length = 0; ++ if (val == 0) ++ { /* Special case */ ++ *cp++ = '0'; ++ } else ++ while (val) ++ { ++ *cp++ = digits[val % radix]; ++ val /= radix; ++ } ++ while (cp != temp) ++ { ++ *buf++ = *--cp; ++ length++; ++ } ++ *buf = '\0'; ++ return (length); ++} ++ ++void ++_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base) ++{ ++ int i, c; ++ if ((unsigned int)s > (unsigned int)p) ++ { ++ s = (unsigned int)s - (unsigned int)p; ++ } ++ while (s > 0) ++ { ++ if (base) ++ { ++ _printk("%06X: ", (int)p - (int)base); ++ } else ++ { ++ _printk("%06X: ", p); ++ } ++ for (i = 0; i < 16; i++) ++ { ++ if (i < s) ++ { ++ _printk("%02X", p[i] & 0xFF); ++ } else ++ { ++ _printk(" "); ++ } ++ if ((i % 2) == 1) _printk(" "); ++ if ((i % 8) == 7) _printk(" "); ++ } ++ _printk(" |"); ++ for (i = 0; i < 16; i++) ++ { ++ if (i < s) ++ { ++ c = p[i] & 0xFF; ++ if ((c < 0x20) || (c >= 0x7F)) c = '.'; ++ } else ++ { ++ c = ' '; ++ } ++ _printk("%c", c); ++ } ++ _printk("|\n"); ++ s -= 16; ++ p += 16; ++ } ++} ++ ++void ++_dump_buf(unsigned char *p, int s) ++{ ++ _printk("\n"); ++ _dump_buf_with_offset(p, s, 0); ++} ++ ++/* ++ * Local variables: ++ * c-indent-level: 8 ++ * c-basic-offset: 8 ++ * tab-width: 8 ++ * End: ++ */ +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/misc-simple.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/misc-simple.c +--- linux-2.6.16.7/arch/mips/boot/compressed/common/misc-simple.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/misc-simple.c 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,122 @@ ++/* ++ * arch/mips/zboot/common/misc-simple.c ++ * ++ * Misc. bootloader code for many machines. This assumes you have are using ++ * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory ++ * below 8MB is free. Finally, it assumes you have a NS16550-style uart for ++ * your serial console. If a machine meets these requirements, it can quite ++ * likely use this code during boot. ++ * ++ * Author: Matt Porter ++ * Derived from arch/ppc/boot/prep/misc.c ++ * ++ * Copyright 2001 MontaVista Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "linux/zlib.h" ++ ++extern struct NS16550 *com_port; ++ ++char *avail_ram; ++char *end_avail; ++extern char _end[]; ++char *zimage_start; ++ ++#ifdef CONFIG_CMDLINE ++#define CMDLINE CONFIG_CMDLINE ++#else ++#define CMDLINE "" ++#endif ++char cmd_preset[] = CMDLINE; ++char cmd_buf[256]; ++char *cmd_line = cmd_buf; ++ ++/* The linker tells us where the image is. ++*/ ++extern unsigned char __image_begin, __image_end; ++extern unsigned char __ramdisk_begin, __ramdisk_end; ++unsigned long initrd_size; ++ ++extern void puts(const char *); ++extern void putc(const char c); ++extern void puthex(unsigned long val); ++extern void *memcpy(void * __dest, __const void * __src, ++ __kernel_size_t __n); ++extern void gunzip(void *, int, unsigned char *, int *); ++extern void udelay(long delay); ++extern int tstc(void); ++extern int getc(void); ++extern volatile struct NS16550 *serial_init(int chan); ++ ++void ++decompress_kernel(unsigned long load_addr, int num_words, ++ unsigned long cksum, unsigned long *sp) ++{ ++ extern unsigned long start; ++ int zimage_size; ++ ++ com_port = (struct NS16550 *)serial_init(0); ++ ++ initrd_size = (unsigned long)(&__ramdisk_end) - ++ (unsigned long)(&__ramdisk_begin); ++ ++ /* ++ * Reveal where we were loaded at and where we ++ * were relocated to. ++ */ ++ puts("loaded at: "); puthex(load_addr); ++ puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); ++ if ( (unsigned long)load_addr != (unsigned long)&start ) ++ { ++ puts("relocated to: "); puthex((unsigned long)&start); ++ puts(" "); ++ puthex((unsigned long)((unsigned long)&start + (4*num_words))); ++ puts("\n"); ++ } ++ ++ /* ++ * We link ourself to an arbitrary low address. When we run, we ++ * relocate outself to that address. __image_being points to ++ * the part of the image where the zImage is. -- Tom ++ */ ++ zimage_start = (char *)(unsigned long)(&__image_begin); ++ zimage_size = (unsigned long)(&__image_end) - ++ (unsigned long)(&__image_begin); ++ ++ /* ++ * The zImage and initrd will be between start and _end, so they've ++ * already been moved once. We're good to go now. -- Tom ++ */ ++ puts("zimage at: "); puthex((unsigned long)zimage_start); ++ puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); ++ puts("\n"); ++ ++ if ( initrd_size ) { ++ puts("initrd at: "); ++ puthex((unsigned long)(&__ramdisk_begin)); ++ puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n"); ++ } ++ ++ /* assume the chunk below 8M is free */ ++ avail_ram = (char *)AVAIL_RAM_START; ++ end_avail = (char *)AVAIL_RAM_END; ++ ++ /* Display standard Linux/MIPS boot prompt for kernel args */ ++ puts("Uncompressing Linux at load address "); ++ puthex(LOADADDR); ++ puts("\n"); ++ /* I don't like this hard coded gunzip size (fixme) */ ++ gunzip((void *)LOADADDR, 0x400000, zimage_start, &zimage_size); ++ puts("Now booting the kernel\n"); ++} +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/common/no_initrd.c linux-2.6.16.7.new/arch/mips/boot/compressed/common/no_initrd.c +--- linux-2.6.16.7/arch/mips/boot/compressed/common/no_initrd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/common/no_initrd.c 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,2 @@ ++char initrd_data[1]; ++int initrd_len = 0; +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/images/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/images/Makefile +--- linux-2.6.16.7/arch/mips/boot/compressed/images/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/images/Makefile 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,17 @@ ++ ++# ++# This dir holds all of the images for MIPS machines. ++# Tom Rini January 2001 ++# Pete Popov 2004 ++ ++extra-y := vmlinux.bin vmlinux.gz ++ ++OBJCOPYFLAGS_vmlinux.bin := -O binary ++$(obj)/vmlinux.bin: vmlinux FORCE ++ $(call if_changed,objcopy) ++ ++$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE ++ $(call if_changed,gzip) ++ ++# Files generated that shall be removed upon make clean ++clean-files := vmlinux* zImage* +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/include/nonstdio.h linux-2.6.16.7.new/arch/mips/boot/compressed/include/nonstdio.h +--- linux-2.6.16.7/arch/mips/boot/compressed/include/nonstdio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/include/nonstdio.h 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (C) Paul Mackerras 1997. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++typedef int FILE; ++extern FILE *stdin, *stdout; ++#define NULL ((void *)0) ++#define EOF (-1) ++#define fopen(n, m) NULL ++#define fflush(f) 0 ++#define fclose(f) 0 ++extern char *fgets(); ++ ++#define perror(s) printf("%s: no files!\n", (s)) +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/include/ns16550.h linux-2.6.16.7.new/arch/mips/boot/compressed/include/ns16550.h +--- linux-2.6.16.7/arch/mips/boot/compressed/include/ns16550.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/include/ns16550.h 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,46 @@ ++/* ++ * NS16550 Serial Port ++ */ ++ ++/* ++ * Figure out which file will have the definitons of COMx ++ */ ++ ++/* Some machines have their uart registers 16 bytes apart. Most don't. ++ * TODO: Make this work like drivers/char/serial does - Tom */ ++#if !defined(UART_REG_PAD) ++#define UART_REG_PAD(x) ++#endif ++ ++struct NS16550 ++ { ++ unsigned char rbr; /* 0 */ ++ UART_REG_PAD(rbr) ++ unsigned char ier; /* 1 */ ++ UART_REG_PAD(ier) ++ unsigned char fcr; /* 2 */ ++ UART_REG_PAD(fcr) ++ unsigned char lcr; /* 3 */ ++ UART_REG_PAD(lcr) ++ unsigned char mcr; /* 4 */ ++ UART_REG_PAD(mcr) ++ unsigned char lsr; /* 5 */ ++ UART_REG_PAD(lsr) ++ unsigned char msr; /* 6 */ ++ UART_REG_PAD(msr) ++ unsigned char scr; /* 7 */ ++ }; ++ ++#define thr rbr ++#define iir fcr ++#define dll rbr ++#define dlm ier ++ ++#define LSR_DR 0x01 /* Data ready */ ++#define LSR_OE 0x02 /* Overrun */ ++#define LSR_PE 0x04 /* Parity error */ ++#define LSR_FE 0x08 /* Framing error */ ++#define LSR_BI 0x10 /* Break */ ++#define LSR_THRE 0x20 /* Xmit holding register empty */ ++#define LSR_TEMT 0x40 /* Xmitter empty */ ++#define LSR_ERR 0x80 /* Error */ +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/include/pb1000_serial.h linux-2.6.16.7.new/arch/mips/boot/compressed/include/pb1000_serial.h +--- linux-2.6.16.7/arch/mips/boot/compressed/include/pb1000_serial.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/include/pb1000_serial.h 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,20 @@ ++/* ++ * arch/ppc/boot/include/sandpoint_serial.h ++ * ++ * Location of the COM ports on Motorola SPS Sandpoint machines ++ * ++ * Author: Mark A. Greer ++ * mgreer@mvista.com ++ * ++ * Copyright 2001 MontaVista Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#define COM1 0xfe0003f8 ++#define COM2 0xfe0002f8 ++#define COM3 0x00000000 /* No COM3 */ ++#define COM4 0x00000000 /* No COM4 */ +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/ld.script linux-2.6.16.7.new/arch/mips/boot/compressed/ld.script +--- linux-2.6.16.7/arch/mips/boot/compressed/ld.script 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/ld.script 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,151 @@ ++OUTPUT_ARCH(mips) ++ENTRY(start) ++SECTIONS ++{ ++ /* Read-only sections, merged into text segment: */ ++ /* . = 0x81000000; */ ++ .init : { *(.init) } =0 ++ .text : ++ { ++ _ftext = . ; ++ *(.text) ++ *(.rodata) *(.rodata.*) ++ *(.rodata1) ++ /* .gnu.warning sections are handled specially by elf32.em. */ ++ *(.gnu.warning) ++ } =0 ++ .kstrtab : { *(.kstrtab) } ++ ++ . = ALIGN(16); /* Exception table */ ++ __start___ex_table = .; ++ __ex_table : { *(__ex_table) } ++ __stop___ex_table = .; ++ ++ __start___dbe_table = .; /* Exception table for data bus errors */ ++ __dbe_table : { *(__dbe_table) } ++ __stop___dbe_table = .; ++ ++ __start___ksymtab = .; /* Kernel symbol table */ ++ __ksymtab : { *(__ksymtab) } ++ __stop___ksymtab = .; ++ ++ _etext = .; ++ ++ . = ALIGN(8192); ++ .data.init_task : { *(.data.init_task) } ++ ++ /* Startup code */ ++ . = ALIGN(4096); ++ __init_begin = .; ++ .text.init : { *(.text.init) } ++ .data.init : { *(.data.init) } ++ . = ALIGN(16); ++ __setup_start = .; ++ .setup.init : { *(.setup.init) } ++ __setup_end = .; ++ __initcall_start = .; ++ .initcall.init : { *(.initcall.init) } ++ __initcall_end = .; ++ . = ALIGN(4096); /* Align double page for init_task_union */ ++ __init_end = .; ++ ++ . = ALIGN(4096); ++ .data.page_aligned : { *(.data.idt) } ++ ++ . = ALIGN(32); ++ .data.cacheline_aligned : { *(.data.cacheline_aligned) } ++ ++ .fini : { *(.fini) } =0 ++ .reginfo : { *(.reginfo) } ++ /* Adjust the address for the data segment. We want to adjust up to ++ the same address within the page on the next page up. It would ++ be more correct to do this: ++ . = .; ++ The current expression does not correctly handle the case of a ++ text segment ending precisely at the end of a page; it causes the ++ data segment to skip a page. The above expression does not have ++ this problem, but it will currently (2/95) cause BFD to allocate ++ a single segment, combining both text and data, for this case. ++ This will prevent the text segment from being shared among ++ multiple executions of the program; I think that is more ++ important than losing a page of the virtual address space (note ++ that no actual memory is lost; the page which is skipped can not ++ be referenced). */ ++ . = .; ++ .data : ++ { ++ _fdata = . ; ++ *(.data) ++ ++ /* Put the compressed image here, so bss is on the end. */ ++ __image_begin = .; ++ *(.image) ++ __image_end = .; ++ /* Align the initial ramdisk image (INITRD) on page boundaries. */ ++ . = ALIGN(4096); ++ __ramdisk_begin = .; ++ *(.initrd) ++ __ramdisk_end = .; ++ . = ALIGN(4096); ++ ++ CONSTRUCTORS ++ } ++ .data1 : { *(.data1) } ++ _gp = . + 0x8000; ++ .lit8 : { *(.lit8) } ++ .lit4 : { *(.lit4) } ++ .ctors : { *(.ctors) } ++ .dtors : { *(.dtors) } ++ .got : { *(.got.plt) *(.got) } ++ .dynamic : { *(.dynamic) } ++ /* We want the small data sections together, so single-instruction offsets ++ can access them all, and initialized data all before uninitialized, so ++ we can shorten the on-disk segment size. */ ++ .sdata : { *(.sdata) } ++ . = ALIGN(4); ++ _edata = .; ++ PROVIDE (edata = .); ++ ++ __bss_start = .; ++ _fbss = .; ++ .sbss : { *(.sbss) *(.scommon) } ++ .bss : ++ { ++ *(.dynbss) ++ *(.bss) ++ *(COMMON) ++ . = ALIGN(4); ++ _end = . ; ++ PROVIDE (end = .); ++ } ++ ++ /* Sections to be discarded */ ++ /DISCARD/ : ++ { ++ *(.text.exit) ++ *(.data.exit) ++ *(.exitcall.exit) ++ } ++ ++ /* This is the MIPS specific mdebug section. */ ++ .mdebug : { *(.mdebug) } ++ /* These are needed for ELF backends which have not yet been ++ converted to the new style linker. */ ++ .stab 0 : { *(.stab) } ++ .stabstr 0 : { *(.stabstr) } ++ /* DWARF debug sections. ++ Symbols in the .debug DWARF section are relative to the beginning of the ++ section so we begin .debug at 0. It's not clear yet what needs to happen ++ for the others. */ ++ .debug 0 : { *(.debug) } ++ .debug_srcinfo 0 : { *(.debug_srcinfo) } ++ .debug_aranges 0 : { *(.debug_aranges) } ++ .debug_pubnames 0 : { *(.debug_pubnames) } ++ .debug_sfnames 0 : { *(.debug_sfnames) } ++ .line 0 : { *(.line) } ++ /* These must appear regardless of . */ ++ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } ++ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } ++ .comment : { *(.comment) } ++ .note : { *(.note) } ++} +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/lib/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/lib/Makefile +--- linux-2.6.16.7/arch/mips/boot/compressed/lib/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/lib/Makefile 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,11 @@ ++ ++# ++# Makefile for some libs needed by zImage. ++# ++ ++lib-y := $(addprefix ../../../../../lib/zlib_inflate/, \ ++ infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o) \ ++ $(addprefix ../../../../../lib/, ctype.o string.o) \ ++ $(addprefix ../../../../../arch/mips/lib/, memcpy.o) \ ++ ++ +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/Makefile linux-2.6.16.7.new/arch/mips/boot/compressed/Makefile +--- linux-2.6.16.7/arch/mips/boot/compressed/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/Makefile 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,32 @@ ++ ++# ++# arch/mips/boot/compressed/Makefile ++# ++# 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. ++# ++# Copyright (C) 1994 by Linus Torvalds ++# Adapted for PowerPC by Gary Thomas ++# modified by Cort (cort@cs.nmt.edu) ++# ++# Ported to MIPS by Pete Popov, ppopov@embeddedalley.com ++# ++ ++boot := arch/mips/boot ++compressed := arch/mips/boot/compressed ++ ++CFLAGS += -fno-builtin -D__BOOTER__ -I$(compressed)/include ++ ++BOOT_TARGETS = zImage zImage.flash ++ ++bootdir-$(CONFIG_SOC_AU1X00) := au1xxx ++subdir-y := common lib images ++ ++.PHONY: $(BOOT_TARGETS) $(bootdir-y) ++ ++$(BOOT_TARGETS): $(bootdir-y) ++ ++$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \ ++ $(addprefix $(obj)/,$(hostprogs-y)) ++ $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS) +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/utils/entry linux-2.6.16.7.new/arch/mips/boot/compressed/utils/entry +--- linux-2.6.16.7/arch/mips/boot/compressed/utils/entry 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/utils/entry 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,12 @@ ++#!/bin/sh ++ ++# grab the kernel_entry address from the vmlinux elf image ++entry=`$1 $2 | grep kernel_entry` ++ ++fs=`echo $entry | grep ffffffff` # check toolchain output ++ ++if [ -n "$fs" ]; then ++ echo "0x"`$1 $2 | grep kernel_entry | cut -c9- | awk '{print $1}'` ++else ++ echo "0x"`$1 $2 | grep kernel_entry | cut -c1- | awk '{print $1}'` ++fi +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/utils/offset linux-2.6.16.7.new/arch/mips/boot/compressed/utils/offset +--- linux-2.6.16.7/arch/mips/boot/compressed/utils/offset 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/utils/offset 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,3 @@ ++#!/bin/sh ++ ++echo "0x"`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'` +diff -urN linux-2.6.16.7/arch/mips/boot/compressed/utils/size linux-2.6.16.7.new/arch/mips/boot/compressed/utils/size +--- linux-2.6.16.7/arch/mips/boot/compressed/utils/size 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/boot/compressed/utils/size 2006-05-04 23:08:18.000000000 +0200 +@@ -0,0 +1,4 @@ ++#!/bin/sh ++ ++OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'` ++echo "0x"$OFFSET +diff -urN linux-2.6.16.7/arch/mips/boot/Makefile linux-2.6.16.7.new/arch/mips/boot/Makefile +--- linux-2.6.16.7/arch/mips/boot/Makefile 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7.new/arch/mips/boot/Makefile 2006-05-04 23:08:18.000000000 +0200 +@@ -16,6 +16,7 @@ + E2EFLAGS = + endif + ++ + # + # Drop some uninteresting sections in the kernel. + # This is only relevant for ELF kernels but doesn't hurt a.out +@@ -25,7 +26,10 @@ + + VMLINUX = vmlinux + +-all: vmlinux.ecoff vmlinux.srec addinitrd ++ZBOOT_TARGETS = zImage zImage.flash ++bootdir-y := compressed ++ ++all: vmlinux.ecoff vmlinux.srec addinitrd zImage + + vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX) + $(obj)/elf2ecoff $(VMLINUX) vmlinux.ecoff $(E2EFLAGS) +@@ -51,3 +55,11 @@ + vmlinux.bin \ + vmlinux.ecoff \ + vmlinux.srec ++ ++.PHONY: $(ZBOOT_TARGETS) $(bootdir-y) ++ ++$(ZBOOT_TARGETS): $(bootdir-y) ++ ++$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \ ++ $(addprefix $(obj)/,$(hostprogs-y)) ++ $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS) +diff -urN linux-2.6.16.7/arch/mips/Makefile linux-2.6.16.7.new/arch/mips/Makefile +--- linux-2.6.16.7/arch/mips/Makefile 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7.new/arch/mips/Makefile 2006-05-04 23:09:44.000000000 +0200 +@@ -831,6 +831,10 @@ + all: vmlinux.ecoff + endif + ++ifdef CONFIG_MIPS_MTX1 ++all: vmlinux.srec zImage zImage.flash ++endif ++ + vmlinux.bin: $(vmlinux-32) + +@$(call makeboot,$@) + +@@ -840,6 +844,12 @@ + vmlinux.srec: $(vmlinux-32) + +@$(call makeboot,$@) + ++zImage: vmlinux ++ +@$(call makeboot,$@) ++ ++zImage.flash: vmlinux ++ +@$(call makeboot,$@) ++ + CLEAN_FILES += vmlinux.ecoff \ + vmlinux.srec \ + vmlinux.rm200.tmp \ +@@ -848,6 +858,7 @@ + archclean: + @$(MAKE) $(clean)=arch/mips/boot + @$(MAKE) $(clean)=arch/mips/lasat ++ @$(MAKE) $(clean)=arch/mips/boot/compressed + + CLEAN_FILES += vmlinux.32 \ + vmlinux.64 \ diff --git a/target/linux/au1000-2.6/patches/004-mtx1_watchdog.patch b/target/linux/au1000-2.6/patches/004-mtx1_watchdog.patch new file mode 100644 index 0000000000..c7e329b295 --- /dev/null +++ b/target/linux/au1000-2.6/patches/004-mtx1_watchdog.patch @@ -0,0 +1,279 @@ +diff -urN linux-2.6.16.7/drivers/char/watchdog/Kconfig linux-2.6.16.7.new/drivers/char/watchdog/Kconfig +--- linux-2.6.16.7/drivers/char/watchdog/Kconfig 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7.new/drivers/char/watchdog/Kconfig 2006-04-22 23:23:53.000000000 +0200 +@@ -460,6 +460,14 @@ + timer expired and no process has written to /dev/watchdog during + that time. + ++config MTX1_WATCHDOG ++ tristate "MTX-1 Hardware Watchdog" ++ depends on WATCHDOG && MIPS_MTX1 ++ help ++ Hardware driver for the AccessCube MTX-1 watchdog. This is a ++ watchdog timer that will reboot the machine after a 100 seconds ++ timer expired. ++ + # S390 Architecture + + config ZVM_WATCHDOG +diff -urN linux-2.6.16.7/drivers/char/watchdog/Makefile linux-2.6.16.7.new/drivers/char/watchdog/Makefile +--- linux-2.6.16.7/drivers/char/watchdog/Makefile 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7.new/drivers/char/watchdog/Makefile 2006-04-22 23:21:18.000000000 +0200 +@@ -65,6 +65,7 @@ + + # MIPS Architecture + obj-$(CONFIG_INDYDOG) += indydog.o ++obj-$(CONFIG_MTX1_WATCHDOG) += mtx-1_watchdog.o + + # S390 Architecture + +diff -urN linux-2.6.16.7/drivers/char/watchdog/mtx-1_watchdog.c linux-2.6.16.7.new/drivers/char/watchdog/mtx-1_watchdog.c +--- linux-2.6.16.7/drivers/char/watchdog/mtx-1_watchdog.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/drivers/char/watchdog/mtx-1_watchdog.c 2006-04-22 23:20:53.000000000 +0200 +@@ -0,0 +1,246 @@ ++/* ++ * Driver for the MTX-1 Watchdog. ++ * ++ * (c) Copyright 2005 4G Systems , All Rights Reserved. ++ * http://www.4g-systems.biz ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Neither Michael Stickel nor 4G Systems admit liability nor provide ++ * warranty for any of this software. This material is provided ++ * "AS-IS" and at no charge. ++ * ++ * (c) Copyright 2005 4G Systems ++ * ++ * Release 0.01. ++ * ++ * Author: Michael Stickel michael.stickel@4g-systems.biz ++ * ++ * ++ * The Watchdog is configured to reset the MTX-1 ++ * if it is not triggered for 100 seconds. ++ * It should not be triggered more often than 1.6 seconds. ++ * ++ * A timer triggers the watchdog every 5 seconds, until ++ * it is opened for the first time. After the first open ++ * it MUST be triggered every 2..95 seconds. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifndef FALSE ++# define FALSE (0) ++#endif ++ ++#ifndef TRUE ++# define TRUE (!FALSE) ++#endif ++ ++ ++//---------[ Hardware Functions ]----------------- ++ ++static void mtx1_trigger_wd (void) ++{ ++ /* ++ * toggle GPIO2_15 ++ */ ++ ++ u32 tmp = au_readl(GPIO2_DIR); ++ tmp = (tmp & ~(1<<15)) | ((~tmp) & (1<<15)); ++ au_writel (tmp, GPIO2_DIR); ++} ++ ++static void mtx1_enable_wd (void) ++{ ++ au_writel (au_readl(GPIO2_DIR) | (u32)(1<<15), GPIO2_DIR); ++} ++ ++static void mtx1_disable_wd (void) ++{ ++ au_writel (au_readl(GPIO2_DIR) & ~((u32)(1<<15)), GPIO2_DIR); ++} ++ ++ ++//---------[ Timer Functions ]----------------- ++ ++static struct timer_list wd_trigger_timer; ++static char timer_is_running = FALSE; ++ ++static void wd_timer_callback (unsigned long data) ++{ ++ if (timer_is_running) ++ mod_timer (&wd_trigger_timer, jiffies + 5 * HZ); ++ mtx1_trigger_wd(); ++} ++ ++static void start_wd_timer (void) ++{ ++ if (!timer_is_running) { ++ struct timer_list *t = &wd_trigger_timer; ++ ++ init_timer (t); ++ t->function = wd_timer_callback; ++ t->data = (unsigned long)0L; ++ t->expires = jiffies + 5 * HZ; // 5 seconds. ++ add_timer (t); ++ timer_is_running = TRUE; ++ } ++} ++ ++ ++ ++static void stop_wd_timer (void) ++{ ++ if (timer_is_running) { ++ del_timer(&wd_trigger_timer); ++ timer_is_running = FALSE; ++ } ++} ++ ++ ++//---------[ File Functions ]----------------- ++ ++static char restart_after_close; ++ ++static int mtx1wd_open (struct inode *inode, struct file *file) ++{ ++ if (MINOR(inode->i_rdev) != WATCHDOG_MINOR) return -ENODEV; ++ //MOD_INC_USE_COUNT; ++ ++ // stop the timer, if it is running. It will not be ++ // started again, until the module is loaded again. ++ stop_wd_timer(); ++ ++ // sleep for 2 seconds, to ensure, that the wd is ++ // not triggered more often than every 2 seconds. ++ schedule_timeout (2 * HZ); ++ ++ return 0; ++} ++ ++ ++static int mtx1wd_release (struct inode *inode, struct file *file) { ++ if (MINOR(inode->i_rdev)==WATCHDOG_MINOR) { ++ } ++ if (restart_after_close) ++ start_wd_timer(); ++ //MOD_DEC_USE_COUNT; ++ return 0; ++} ++ ++ ++static ssize_t mtx1wd_write (struct file *file, const char *buf, size_t count, loff_t *ppos) { ++ ++ mtx1_trigger_wd (); ++ ++ if (count > 0) { ++ char buffer[10]; ++ int n = (count>9)?9:count; ++ ++ if (copy_from_user (&buffer, buf, n)) ++ return -EFAULT; ++ buffer[n]=0; ++ ++ if (count >= 4 && strncmp("auto", buffer, 4)==0) ++ restart_after_close = 1; ++ ++ else if (count >= 6 && strncmp("manual", buffer, 6)==0) ++ restart_after_close = 0; ++ ++ return n; ++ } ++ ++ return 0; ++} ++ ++static ssize_t mtx1wd_read (struct file *file, char *buf, size_t count, loff_t *ppos) ++{ ++ char * state = restart_after_close ? "auto\n" : "manual\n"; ++ int n = strlen(state)+1; ++ ++ if (file->f_pos >= n) ++ return 0; ++ ++ if (count < n) ++ return -EINVAL; ++ ++ if(copy_to_user(buf, state, n)) ++ return -EFAULT; ++ ++ file->f_pos += n; ++ ++ return n; ++} ++ ++static struct file_operations mtx1wd_fops = { ++ .owner = THIS_MODULE, ++ .read = mtx1wd_read, ++ .write = mtx1wd_write, ++ .open = mtx1wd_open, ++ .release = mtx1wd_release ++}; ++ ++ ++static struct miscdevice mtx1wd_miscdev = { ++ WATCHDOG_MINOR, ++ "watchdog", ++ &mtx1wd_fops ++}; ++ ++ ++ ++//---------[ Module Functions ]----------------- ++ ++ ++static int __init init_mtx1_watchdog(void) ++{ ++ printk("MTX-1 watchdog driver\n"); ++ ++ misc_register(&mtx1wd_miscdev); ++ ++ restart_after_close = 0; ++ ++ mtx1_enable_wd (); ++ ++ //-- trigger it for the first time. ++ //-- We do not exactly know how long it has not been triggered. ++ mtx1_trigger_wd (); ++ ++ // start a timer, that calls mtx1_trigger_wd every 5 seconds. ++ start_wd_timer(); ++ ++ return 0; ++} ++ ++static void __exit exit_mtx1_watchdog(void) { ++ ++ // stop the timer, if it is running. ++ stop_wd_timer(); ++ ++ misc_deregister(&mtx1wd_miscdev); ++ ++ mtx1_disable_wd(); ++} ++ ++module_init(init_mtx1_watchdog); ++module_exit(exit_mtx1_watchdog); ++ ++MODULE_AUTHOR("Michael Stickel"); ++MODULE_DESCRIPTION("Driver for the MTX-1 watchdog"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/au1000-2.6/patches/005-au1000_eth_link_beat.patch b/target/linux/au1000-2.6/patches/005-au1000_eth_link_beat.patch new file mode 100644 index 0000000000..946bd84540 --- /dev/null +++ b/target/linux/au1000-2.6/patches/005-au1000_eth_link_beat.patch @@ -0,0 +1,24 @@ +diff -urN linux-2.6.16.7/drivers/net/au1000_eth.c linux-2.6.16.7.new/drivers/net/au1000_eth.c +--- linux-2.6.16.7/drivers/net/au1000_eth.c 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7.new/drivers/net/au1000_eth.c 2006-04-23 01:42:48.000000000 +0200 +@@ -12,6 +12,9 @@ + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * ++ * Bjoern Riemer 2004 ++ * riemer@fokus.fraunhofer.de or riemer@riemer-nt.de ++ * // fixed the link beat detection with ioctls (SIOCGMIIPHY) + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it +@@ -1672,6 +1675,10 @@ + aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed); + control = MAC_DISABLE_RX_OWN | MAC_RX_ENABLE | MAC_TX_ENABLE; + #ifndef CONFIG_CPU_LITTLE_ENDIAN ++ /*riemer: fix for startup without cable */ ++ if (!link) ++ dev->flags &= ~IFF_RUNNING; ++ + control |= MAC_BIG_ENDIAN; + #endif + if (link && (dev->if_port == IF_PORT_100BASEFX)) { diff --git a/target/linux/au1000-2.6/patches/006-mtx1_system_button.patch b/target/linux/au1000-2.6/patches/006-mtx1_system_button.patch new file mode 100644 index 0000000000..511df2c8da --- /dev/null +++ b/target/linux/au1000-2.6/patches/006-mtx1_system_button.patch @@ -0,0 +1,241 @@ +diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/irqmap.c linux-2.6.16.7.new/arch/mips/au1000/mtx-1/irqmap.c +--- linux-2.6.16.7/arch/mips/au1000/mtx-1/irqmap.c 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/irqmap.c 2006-04-23 11:54:31.000000000 +0200 +@@ -64,6 +64,7 @@ + { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, ++ { AU1500_GPIO_207, INTC_INT_RISE_AND_FALL_EDGE, 0 }, + }; + + int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/Makefile linux-2.6.16.7.new/arch/mips/au1000/mtx-1/Makefile +--- linux-2.6.16.7/arch/mips/au1000/mtx-1/Makefile 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/Makefile 2006-04-23 14:01:36.000000000 +0200 +@@ -8,3 +8,4 @@ + # + + lib-y := init.o board_setup.o irqmap.o ++obj-y := mtx-1_sysbtn.o +diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c linux-2.6.16.7.new/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c +--- linux-2.6.16.7/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c 2006-04-23 14:01:17.000000000 +0200 +@@ -0,0 +1,218 @@ ++/* ++ * Driver for the MTX-1 System Button. ++ * ++ * (c) Copyright 2005 4G Systems , All Rights Reserved. ++ * http://www.4g-systems.biz ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Neither Michael Stickel nor 4G Systeme GmbH admit liability nor provide ++ * warranty for any of this software. This material is provided ++ * "AS-IS" and at no charge. ++ * ++ * (c) Copyright 2005 4G Systems ++ * ++ * Release 0.01. ++ * ++ * Author: Michael Stickel michael.stickel@4g-systems.biz ++ * ++ * ++ * After the module is loaded there is a device /dev/misc/btn ++ * that can be read. It returns one char '1' if the button ++ * has been pressed an '0' if it has been released. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++ ++#ifndef FALSE ++# define FALSE (0) ++#endif ++ ++#ifndef TRUE ++# define TRUE (!FALSE) ++#endif ++ ++ ++//---------[ declarations ]----------------- ++ ++ ++static DECLARE_WAIT_QUEUE_HEAD(mtx1btn_wait_queue); ++static char state_changed; ++static char last_value; ++static char is_inuse; ++ ++ ++//---------[ Hardware Functions ]----------------- ++ ++// The MTX-1 Button is attached to GPIO207. ++#define MTX1_GPIO2_SYSBTN (7) ++#define MTX1_SYSBTN_IRQ (AU1500_GPIO_207) ++ ++ ++static char mtx1_getbtn (int btnno) ++{ ++ if (btnno==0) { ++ return (au_readl(GPIO2_PINSTATE) & (1<i_rdev)!=mtx1sysbtn_minor) return -ENODEV; ++ if (is_inuse) return -EBUSY; ++ is_inuse=1; ++ last_value = mtx1_getbtn(0); ++ state_changed = 0; ++ return 0; ++} ++ ++ ++static int mtx1sysbtn_release (struct inode *inode, struct file *file) { ++ if (MINOR(inode->i_rdev)==mtx1sysbtn_minor) { ++ is_inuse=0; ++ } ++ return 0; ++} ++ ++ ++static ssize_t mtx1sysbtn_read (struct file *file, char *buf, size_t count, loff_t *ppos) ++{ ++ if (count < 1) ++ return -EINVAL; ++ if (!state_changed) ++ interruptible_sleep_on (&mtx1btn_wait_queue); ++ state_changed = 0; ++ char c = last_value ? '1' : '0'; /* mtx1_getbtn(0) */ ++ if(copy_to_user(buf, &c, 1)) ++ return -EFAULT; ++ return 1; ++} ++ ++ ++static unsigned int mtx1sysbtn_poll (struct file *file, poll_table * wait) ++{ ++ unsigned int mask = 0; ++ ++ poll_wait (file, &mtx1btn_wait_queue, wait); ++ ++ if (state_changed) // state changed since last time. ++ mask |= POLLIN | POLLRDNORM; ++ ++ return mask; ++} ++ ++ ++static struct file_operations mtx1sysbtn_fops = { ++ .owner = THIS_MODULE, ++ .read = mtx1sysbtn_read, ++ .poll = mtx1sysbtn_poll, ++ .open = mtx1sysbtn_open, ++ .release = mtx1sysbtn_release ++}; ++ ++ ++static struct miscdevice mtx1sysbtn_miscdev = { ++ MISC_DYNAMIC_MINOR /* SYSBTN_MINOR */ , ++ "btn", ++ &mtx1sysbtn_fops ++}; ++ ++ ++ ++//---------[ Module Functions ]----------------- ++ ++ ++void __exit exit_mtx1_sysbtn (void) ++{ ++ is_inuse = 1; ++ mtx1_btn_stopirq (); ++ misc_deregister(&mtx1sysbtn_miscdev); ++} ++ ++ ++static int __init init_mtx1_sysbtn (void) ++{ ++ printk("MTX-1 System Button driver\n"); ++ is_inuse = 1; ++ mtx1_initbuttons (); ++ if (misc_register (&mtx1sysbtn_miscdev) >= 0) { ++ mtx1sysbtn_minor = mtx1sysbtn_miscdev.minor; ++ if (mtx1_btn_startirq () == 0) { ++ is_inuse=0; ++ return 0; ++ } ++ misc_deregister(&mtx1sysbtn_miscdev); ++ } ++ return 1; ++} ++ ++module_init(init_mtx1_sysbtn); ++module_exit(exit_mtx1_sysbtn); ++ ++MODULE_AUTHOR("Michael Stickel"); ++MODULE_DESCRIPTION("Driver for the MTX-1 system button"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/au1000-2.6/patches/007-mtx1_sio2.patch b/target/linux/au1000-2.6/patches/007-mtx1_sio2.patch new file mode 100644 index 0000000000..34d1005347 --- /dev/null +++ b/target/linux/au1000-2.6/patches/007-mtx1_sio2.patch @@ -0,0 +1,13 @@ +--- linux-2.6.16.7/arch/mips/au1000/mtx-1/board_setup.c 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/board_setup.c 2006-04-23 14:35:42.000000000 +0200 +@@ -71,9 +71,7 @@ + #endif + + // initialize sys_pinfunc: +- // disable second ethernet port (SYS_PF_NI2) +- // set U3/GPIO23 to GPIO23 (SYS_PF_U3) +- au_writel( SYS_PF_NI2 | SYS_PF_U3, SYS_PINFUNC ); ++ au_writel( SYS_PF_NI2, SYS_PINFUNC ); + + // initialize GPIO + au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR ); diff --git a/target/linux/au1000-2.6/patches/008-isdel_cardbus.patch b/target/linux/au1000-2.6/patches/008-isdel_cardbus.patch new file mode 100644 index 0000000000..9e54ac1c59 --- /dev/null +++ b/target/linux/au1000-2.6/patches/008-isdel_cardbus.patch @@ -0,0 +1,63 @@ +diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/board_setup.c linux-2.6.16.7.new/arch/mips/au1000/mtx-1/board_setup.c +--- linux-2.6.16.7/arch/mips/au1000/mtx-1/board_setup.c 2006-04-23 14:39:21.000000000 +0200 ++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/board_setup.c 2006-04-23 14:39:03.000000000 +0200 +@@ -44,6 +44,9 @@ + #include + #include + ++extern int (*board_pci_idsel)(unsigned int devsel, int assert); ++int mtx1_pci_idsel(unsigned int devsel, int assert); ++ + void board_reset (void) + { + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ +@@ -77,11 +80,37 @@ + au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR ); + au_writel( 0x00000001, SYS_OUTPUTCLR ); // set M66EN (PCI 66MHz) to OFF + au_writel( 0x00000008, SYS_OUTPUTSET ); // set PCI CLKRUN# to OFF ++ au_writel( 0x00000002, SYS_OUTPUTSET ); // set EXT_IO3 ON + au_writel( 0x00000020, SYS_OUTPUTCLR ); // set eth PHY TX_ER to OFF + + // enable LED and set it to green + au_writel( au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR ); + au_writel( 0x18000800, GPIO2_OUTPUT ); + ++ board_pci_idsel = mtx1_pci_idsel; ++ + printk("4G Systems MTX-1 Board\n"); + } ++ ++int ++mtx1_pci_idsel(unsigned int devsel, int assert) ++{ ++#define MTX_IDSEL_ONLY_0_AND_3 0 ++#if MTX_IDSEL_ONLY_0_AND_3 ++ if (devsel != 0 && devsel != 3) { ++ printk("*** not 0 or 3\n"); ++ return 0; ++ } ++#endif ++ ++ if (assert && devsel != 0) { ++ // supress signal to cardbus ++ au_writel( 0x00000002, SYS_OUTPUTCLR ); // set EXT_IO3 OFF ++ } ++ else { ++ au_writel( 0x00000002, SYS_OUTPUTSET ); // set EXT_IO3 ON ++ } ++ au_sync_udelay(1); ++ return 1; ++} ++ +diff -urN linux-2.6.16.7/arch/mips/au1000/mtx-1/irqmap.c linux-2.6.16.7.new/arch/mips/au1000/mtx-1/irqmap.c +--- linux-2.6.16.7/arch/mips/au1000/mtx-1/irqmap.c 2006-04-23 14:40:54.000000000 +0200 ++++ linux-2.6.16.7.new/arch/mips/au1000/mtx-1/irqmap.c 2006-04-23 14:40:12.000000000 +0200 +@@ -48,7 +48,7 @@ + #include + + char irq_tab_alchemy[][5] __initdata = { +- [0] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 00 - AdapterA-Slot0 (top) */ ++ [0] = { -1, INTA, INTA, INTX, INTX}, /* IDSEL 00 - AdapterA-Slot0 (top) */ + [1] = { -1, INTB, INTA, INTX, INTX}, /* IDSEL 01 - AdapterA-Slot1 (bottom) */ + [2] = { -1, INTC, INTD, INTX, INTX}, /* IDSEL 02 - AdapterB-Slot0 (top) */ + [3] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 03 - AdapterB-Slot1 (bottom) */ diff --git a/target/linux/au1000-2.6/patches/009-boot.patch b/target/linux/au1000-2.6/patches/009-boot.patch new file mode 100644 index 0000000000..611c70d460 --- /dev/null +++ b/target/linux/au1000-2.6/patches/009-boot.patch @@ -0,0 +1,15 @@ +diff -Nur linux-cvs/arch/mips/kernel/head.S linux-aruba/arch/mips/kernel/head.S +--- linux-cvs/arch/mips/kernel/head.S 2004-12-23 00:21:39.000000000 -0800 ++++ linux-aruba/arch/mips/kernel/head.S 2005-10-20 09:16:08.000000000 -0700 +@@ -122,6 +122,10 @@ + #endif + .endm + ++ ++ j kernel_entry ++ nop ++ + /* + * Reserved space for exception handlers. + * Necessary for machines which link their kernels at KSEG0. + diff --git a/target/linux/brcm-2.4/Config.in b/target/linux/brcm-2.4/Config.in index 181014f7b3..c766a45c3d 100644 --- a/target/linux/brcm-2.4/Config.in +++ b/target/linux/brcm-2.4/Config.in @@ -6,13 +6,3 @@ config PACKAGE_KMOD_BRCM_WL help Proprietary driver for Broadcom Wireless chipsets -config PACKAGE_KMOD_BRCM_WL2 - prompt "kmod-brcm-wl2..................... Broadcom Wireless Network Driver (new)" - tristate - depends LINUX_2_4_BRCM - default m - help - Proprietary driver for Broadcom Wireless chipsets - New version with Multi-BSS capability - - diff --git a/target/linux/brcm-2.4/Makefile b/target/linux/brcm-2.4/Makefile index 06da0ac010..9447114d4e 100644 --- a/target/linux/brcm-2.4/Makefile +++ b/target/linux/brcm-2.4/Makefile @@ -12,10 +12,6 @@ $(eval $(call KMOD_template,BRCM_WL,brcm-wl,\ $(MODULES_DIR)/kernel/drivers/net/wl/wl.o \ ,CONFIG_WL,,20,wl)) -$(eval $(call KMOD_template,BRCM_WL2,brcm-wl2,\ - $(MODULES_DIR)/kernel/drivers/net/wl2/wl.o \ -,CONFIG_WL,,20,wl)) - $(eval $(call KMOD_template,LP,lp,\ $(MODULES_DIR)/kernel/drivers/parport/parport.o \ $(MODULES_DIR)/kernel/drivers/parport/parport_splink.o \ @@ -38,10 +34,10 @@ $(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked # Proprietary driver for BCM43xx ############################################### -LINUX_BINARY_DRIVER_SITE=http://openwrt.org/downloads/sources +LINUX_BINARY_DRIVER_SITE=http://downloads.openwrt.org/sources # proprietary driver, extracted from Linksys GPL sourcetree WRT54GS 4.70.6 -LINUX_BINARY_WL_DRIVER=kernel-binary-wl-0.6.tar.gz -LINUX_BINARY_WL_MD5SUM=4fc1d5b46bcb7a17d6d5dd31da9c8d7f +LINUX_BINARY_WL_DRIVER=kernel-binary-wl-0.7.tar.gz +LINUX_BINARY_WL_MD5SUM=ff50130914790cbae9b73a13513da5ee $(DL_DIR)/$(LINUX_BINARY_WL_DRIVER): $(SCRIPT_DIR)/download.pl $(DL_DIR) $(LINUX_BINARY_WL_DRIVER) $(LINUX_BINARY_WL_MD5SUM) $(LINUX_BINARY_DRIVER_SITE) @@ -56,18 +52,15 @@ $(LINUX_DIR)/.drivers-unpacked: $(LINUX_DIR)/.unpacked zcat $(DL_DIR)/$(LINUX_BINARY_WL_DRIVER) | tar -C $(BUILD_DIR) $(TAR_OPTIONS) - # copy binary wlan driver mkdir -p $(LINUX_DIR)/drivers/net/wl - $(CP) $(BUILD_DIR)/kernel-binary-wl/old/*.o $(LINUX_DIR)/drivers/net/wl - $(CP) $(BUILD_DIR)/kernel-binary-wl/new/*.o $(LINUX_DIR)/drivers/net/wl2 + $(CP) $(BUILD_DIR)/kernel-binary-wl/*.o $(LINUX_DIR)/drivers/net/wl touch $@ $(LINUX_DIR)/.drivers-installed: $(LINUX_DIR)/.modules_done mkdir -p $(LINUX_BUILD_DIR)/modules/lib/modules/2.4.32/kernel/drivers/net/wl - mkdir -p $(LINUX_BUILD_DIR)/modules/lib/modules/2.4.32/kernel/drivers/net/wl2 @-[ -f $(LINUX_BUILD_DIR)/modules/lib/modules/2.4.32/kernel/drivers/net/wl/wl.o ] || $(CP) $(LINUX_DIR)/drivers/net/wl/wl.o $(LINUX_BUILD_DIR)/modules/lib/modules/2.4.32/kernel/drivers/net/wl/ - @-[ -f $(LINUX_BUILD_DIR)/modules/lib/modules/2.4.32/kernel/drivers/net/wl2/wl.o ] || $(CP) $(LINUX_DIR)/drivers/net/wl2/wl.o $(LINUX_BUILD_DIR)/modules/lib/modules/2.4.32/kernel/drivers/net/wl2/ touch $@ linux-dirclean: drivers-clean drivers-clean: - rm -rf $(BUILD_DIR)/wl + rm -rf $(BUILD_DIR)/kernel-binary-wl diff --git a/target/linux/brcm-2.4/config b/target/linux/brcm-2.4/config index 9759b90f5f..c4cf5340ea 100644 --- a/target/linux/brcm-2.4/config +++ b/target/linux/brcm-2.4/config @@ -833,7 +833,6 @@ CONFIG_NET_RADIO=y # CONFIG_AIRO is not set # CONFIG_HERMES is not set CONFIG_WL=m -CONFIG_WL2=m # CONFIG_PLX_HERMES is not set # CONFIG_TMD_HERMES is not set # CONFIG_PCI_HERMES is not set diff --git a/target/linux/brcm-2.4/patches/001-bcm47xx.patch b/target/linux/brcm-2.4/patches/001-bcm47xx.patch index d662b4c015..af82c3c770 100644 --- a/target/linux/brcm-2.4/patches/001-bcm47xx.patch +++ b/target/linux/brcm-2.4/patches/001-bcm47xx.patch @@ -1,6 +1,6 @@ -diff -Naur linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile ---- linux.old/arch/mips/Makefile 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/arch/mips/Makefile 2006-04-06 15:34:15.000000000 +0200 +diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile +--- linux.old/arch/mips/Makefile 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/arch/mips/Makefile 2006-04-27 19:24:19.000000000 +0200 @@ -726,6 +726,19 @@ endif @@ -29,10 +29,10 @@ diff -Naur linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile archmrproper: @$(MAKEBOOT) mrproper -diff -Naur linux.old/arch/mips/bcm947xx/Makefile linux.dev/arch/mips/bcm947xx/Makefile +diff -urN linux.old/arch/mips/bcm947xx/Makefile linux.dev/arch/mips/bcm947xx/Makefile --- linux.old/arch/mips/bcm947xx/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/Makefile 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,15 @@ ++++ linux.dev/arch/mips/bcm947xx/Makefile 2006-05-02 17:46:22.000000000 +0200 +@@ -0,0 +1,17 @@ +# +# Makefile for the BCM947xx specific kernel interface routines +# under Linux. @@ -42,1216 +42,1489 @@ diff -Naur linux.old/arch/mips/bcm947xx/Makefile linux.dev/arch/mips/bcm947xx/Ma + +O_TARGET := bcm947xx.o + -+export-objs := nvram_linux.o setup.o ++export-objs := export.o +obj-y := prom.o setup.o time.o sbmips.o gpio.o +obj-y += nvram.o nvram_linux.o sflash.o cfe_env.o ++obj-y += sbutils.o bcmutils.o bcmsrom.o hndchipc.o +obj-$(CONFIG_PCI) += sbpci.o pcibios.o ++obj-y += export.o + +include $(TOPDIR)/Rules.make -diff -Naur linux.old/arch/mips/bcm947xx/cfe_env.c linux.dev/arch/mips/bcm947xx/cfe_env.c ---- linux.old/arch/mips/bcm947xx/cfe_env.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/cfe_env.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,234 @@ +diff -urN linux.old/arch/mips/bcm947xx/bcmsrom.c linux.dev/arch/mips/bcm947xx/bcmsrom.c +--- linux.old/arch/mips/bcm947xx/bcmsrom.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/bcmsrom.c 2006-04-27 20:32:48.000000000 +0200 +@@ -0,0 +1,1212 @@ +/* -+ * NVRAM variable manipulation (Linux kernel half) ++ * Misc useful routines to access NIC SROM/OTP . + * -+ * Copyright 2001-2003, Broadcom Corporation ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ ++ * $Id: bcmsrom.c,v 1.1.1.14 2006/04/15 01:28:25 michael Exp $ + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ +#include ++#include +#include -+#include +#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+#define NVRAM_SIZE (0x1ff0) -+static char _nvdata[NVRAM_SIZE] __initdata; -+static char _valuestr[256] __initdata; -+ -+/* -+ * TLV types. These codes are used in the "type-length-value" -+ * encoding of the items stored in the NVRAM device (flash or EEPROM) -+ * -+ * The layout of the flash/nvram is as follows: -+ * -+ * -+ * -+ * The type code of "ENV_TLV_TYPE_END" marks the end of the list. -+ * The "length" field marks the length of the data section, not -+ * including the type and length fields. -+ * -+ * Environment variables are stored as follows: -+ * -+ * = -+ * -+ * If bit 0 (low bit) is set, the length is an 8-bit value. -+ * If bit 0 (low bit) is clear, the length is a 16-bit value -+ * -+ * Bit 7 set indicates "user" TLVs. In this case, bit 0 still -+ * indicates the size of the length field. -+ * -+ * Flags are from the constants below: -+ * -+ */ -+#define ENV_LENGTH_16BITS 0x00 /* for low bit */ -+#define ENV_LENGTH_8BITS 0x01 ++/* debug/trace */ ++#if defined(WLTEST) ++#define BS_ERROR(args) printf args ++#else ++#define BS_ERROR(args) ++#endif /* BCMDBG_ERR || WLTEST */ + -+#define ENV_TYPE_USER 0x80 ++#define VARS_MAX 4096 /* should be reduced */ + -+#define ENV_CODE_SYS(n,l) (((n)<<1)|(l)) -+#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER) ++#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */ ++#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */ + -+/* -+ * The actual TLV types we support -+ */ ++static int initvars_srom_pci(void *sbh, void *curmap, char **vars, uint *count); ++static int initvars_cis_pcmcia(void *sbh, osl_t *osh, char **vars, uint *count); ++static int initvars_flash_sb(void *sbh, char **vars, uint *count); ++static int srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, char **vars, uint *count); ++static int sprom_cmd_pcmcia(osl_t *osh, uint8 cmd); ++static int sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data); ++static int sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data); ++static int sprom_read_pci(osl_t *osh, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, ++ bool check_crc); + -+#define ENV_TLV_TYPE_END 0x00 -+#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS) ++static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count); ++static int initvars_flash(osl_t *osh, char **vp, uint len, char *devpath); + +/* -+ * Environment variable flags ++ * Initialize local vars from the right source for this platform. ++ * Return 0 on success, nonzero on error. + */ ++int ++srom_var_init(void *sbh, uint bustype, void *curmap, osl_t *osh, char **vars, uint *count) ++{ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ if (vars == NULL || count == NULL) ++ return (0); + -+#define ENV_FLG_NORMAL 0x00 /* normal read/write */ -+#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */ -+#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */ ++ switch (BUSTYPE(bustype)) { ++ case SB_BUS: ++ case JTAG_BUS: ++ return initvars_flash_sb(sbh, vars, count); + -+#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */ -+#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */ ++ case PCI_BUS: ++ ASSERT(curmap); /* can not be NULL */ ++ return initvars_srom_pci(sbh, curmap, vars, count); + ++ case PCMCIA_BUS: ++ return initvars_cis_pcmcia(sbh, osh, vars, count); + -+/* ********************************************************************* -+ * _nvram_read(buffer,offset,length) -+ * -+ * Read data from the NVRAM device -+ * -+ * Input parameters: -+ * buffer - destination buffer -+ * offset - offset of data to read -+ * length - number of bytes to read -+ * -+ * Return value: -+ * number of bytes read, or <0 if error occured -+ ********************************************************************* */ -+static int -+_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length) -+{ -+ int i; -+ if (offset > NVRAM_SIZE) -+ return -1; + -+ for ( i = 0; i < length; i++) { -+ buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i]; -+ } -+ return length; ++ default: ++ ASSERT(0); ++ } ++ return (-1); +} + -+ -+static char* -+_strnchr(const char *dest,int c,size_t cnt) ++/* support only 16-bit word read from srom */ ++int ++srom_read(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf) +{ -+ while (*dest && (cnt > 0)) { -+ if (*dest == c) return (char *) dest; -+ dest++; -+ cnt--; -+ } -+ return NULL; -+} ++ void *srom; ++ uint i, off, nw; + ++ ASSERT(bustype == BUSTYPE(bustype)); + ++ /* check input - 16-bit access only */ ++ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2)) ++ return 1; + -+/* -+ * Core support API: Externally visible. -+ */ ++ off = byteoff / 2; ++ nw = nbytes / 2; + -+/* -+ * Get the value of an NVRAM variable -+ * @param name name of variable to get -+ * @return value of variable or NULL if undefined -+ */ ++ if (BUSTYPE(bustype) == PCI_BUS) { ++ if (!curmap) ++ return 1; ++ srom = (uchar*)curmap + PCI_BAR0_SPROM_OFFSET; ++ if (sprom_read_pci(osh, srom, off, buf, nw, FALSE)) ++ return 1; ++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ for (i = 0; i < nw; i++) { ++ if (sprom_read_pcmcia(osh, (uint16)(off + i), (uint16*)(buf + i))) ++ return 1; ++ } ++ } else { ++ return 1; ++ } + -+char* -+cfe_env_get(unsigned char *nv_buf, char* name) ++ return 0; ++} ++ ++/* support only 16-bit word write into srom */ ++int ++srom_write(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf) +{ -+ int size; -+ unsigned char *buffer; -+ unsigned char *ptr; -+ unsigned char *envval; -+ unsigned int reclen; -+ unsigned int rectype; -+ int offset; -+ int flg; -+ -+ size = NVRAM_SIZE; -+ buffer = &_nvdata[0]; ++ uint16 *srom; ++ uint i, nw, crc_range; ++ uint16 image[SPROM_SIZE]; ++ uint8 crc; ++ volatile uint32 val32; + -+ ptr = buffer; -+ offset = 0; ++ ASSERT(bustype == BUSTYPE(bustype)); + -+ /* Read the record type and length */ -+ if (_nvram_read(nv_buf, ptr,offset,1) != 1) { -+ goto error; -+ } -+ -+ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) { ++ /* check input - 16-bit access only */ ++ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2)) ++ return 1; + -+ /* Adjust pointer for TLV type */ -+ rectype = *(ptr); -+ offset++; -+ size--; ++ /* Are we writing the whole thing at once? */ ++ if ((byteoff == 0) && ++ ((nbytes == SPROM_SIZE) || ++ (nbytes == (SPROM_CRC_RANGE * 2)) || ++ (nbytes == (SROM4_WORDS * 2)))) { ++ crc_range = nbytes; ++ bcopy((void*)buf, (void*)image, nbytes); ++ nw = nbytes / 2; ++ } else { ++ if ((BUSTYPE(bustype) == PCMCIA_BUS) || (BUSTYPE(bustype) == SDIO_BUS)) ++ crc_range = SPROM_SIZE; ++ else ++ crc_range = SPROM_CRC_RANGE * 2; /* Tentative */ + -+ /* -+ * Read the length. It can be either 1 or 2 bytes -+ * depending on the code -+ */ -+ if (rectype & ENV_LENGTH_8BITS) { -+ /* Read the record type and length - 8 bits */ -+ if (_nvram_read(nv_buf, ptr,offset,1) != 1) { -+ goto error; -+ } -+ reclen = *(ptr); -+ size--; -+ offset++; -+ } -+ else { -+ /* Read the record type and length - 16 bits, MSB first */ -+ if (_nvram_read(nv_buf, ptr,offset,2) != 2) { -+ goto error; -+ } -+ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1); -+ size -= 2; -+ offset += 2; ++ nw = crc_range / 2; ++ /* read first 64 words from srom */ ++ if (srom_read(bustype, curmap, osh, 0, nw * 2, image)) ++ return 1; ++ if (image[SROM4_SIGN] == SROM4_SIGNATURE) { ++ crc_range = SROM4_WORDS; ++ nw = crc_range / 2; ++ if (srom_read(bustype, curmap, osh, 0, nw * 2, image)) ++ return 1; ++ } ++ /* make changes */ ++ bcopy((void*)buf, (void*)&image[byteoff / 2], nbytes); + } + -+ if (reclen > size) -+ break; /* should not happen, bad NVRAM */ ++ /* calculate crc */ ++ htol16_buf(image, crc_range); ++ crc = ~hndcrc8((uint8 *)image, crc_range - 1, CRC8_INIT_VALUE); ++ ltoh16_buf(image, crc_range); ++ image[(crc_range / 2) - 1] = (crc << 8) | (image[(crc_range / 2) - 1] & 0xff); + -+ switch (rectype) { -+ case ENV_TLV_TYPE_ENV: -+ /* Read the TLV data */ -+ if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen) -+ goto error; -+ flg = *ptr++; -+ envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1)); -+ if (envval) { -+ *envval++ = '\0'; -+ memcpy(_valuestr,envval,(reclen-1)-(envval-ptr)); -+ _valuestr[(reclen-1)-(envval-ptr)] = '\0'; -+#if 0 -+ printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr); -+#endif -+ if(!strcmp(ptr, name)){ -+ return _valuestr; -+ } -+ if((strlen(ptr) > 1) && !strcmp(&ptr[1], name)) -+ return _valuestr; -+ } -+ break; -+ -+ default: -+ /* Unknown TLV type, skip it. */ -+ break; -+ } -+ -+ /* -+ * Advance to next TLV -+ */ -+ -+ size -= (int)reclen; -+ offset += reclen; -+ -+ /* Read the next record type */ -+ ptr = buffer; -+ if (_nvram_read(nv_buf, ptr,offset,1) != 1) -+ goto error; ++ if (BUSTYPE(bustype) == PCI_BUS) { ++ srom = (uint16*)((uchar*)curmap + PCI_BAR0_SPROM_OFFSET); ++ /* enable writes to the SPROM */ ++ val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); ++ val32 |= SPROM_WRITEEN; ++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32); ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ /* write srom */ ++ for (i = 0; i < nw; i++) { ++ W_REG(osh, &srom[i], image[i]); ++ bcm_mdelay(WRITE_WORD_DELAY); ++ } ++ /* disable writes to the SPROM */ ++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & ++ ~SPROM_WRITEEN); ++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ /* enable writes to the SPROM */ ++ if (sprom_cmd_pcmcia(osh, SROM_WEN)) ++ return 1; ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ /* write srom */ ++ for (i = 0; i < nw; i++) { ++ sprom_write_pcmcia(osh, (uint16)(i), image[i]); ++ bcm_mdelay(WRITE_WORD_DELAY); ++ } ++ /* disable writes to the SPROM */ ++ if (sprom_cmd_pcmcia(osh, SROM_WDS)) ++ return 1; ++ } else { ++ return 1; + } + -+error: -+ return NULL; -+ ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ return 0; +} + -diff -Naur linux.old/arch/mips/bcm947xx/compressed/Makefile linux.dev/arch/mips/bcm947xx/compressed/Makefile ---- linux.old/arch/mips/bcm947xx/compressed/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/compressed/Makefile 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,33 @@ -+# -+# Makefile for Broadcom BCM947XX boards -+# -+# Copyright 2001-2003, Broadcom Corporation -+# All Rights Reserved. -+# -+# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+# -+# $Id: Makefile,v 1.2 2005/04/02 12:12:57 wbx Exp $ -+# -+ -+OBJCOPY_ARGS = -O binary -R .reginfo -R .note -R .comment -R .mdebug -S -+SYSTEM ?= $(TOPDIR)/vmlinux + -+all: vmlinuz ++static int ++srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, char **vars, uint *count) ++{ ++ char eabuf[32]; ++ char *vp, *base; ++ uint8 *cis, tup, tlen, sromrev = 1; ++ int i, j; ++ uint varsize; ++ bool ag_init = FALSE; ++ uint32 w32; + -+# Don't build dependencies, this may die if $(CC) isn't gcc -+dep: ++ ASSERT(vars); ++ ASSERT(count); + -+# Create a gzipped version named vmlinuz for compatibility -+vmlinuz: piggy -+ gzip -c9 $< > $@ ++ base = vp = MALLOC(osh, VARS_MAX); ++ ASSERT(vp); ++ if (!vp) ++ return -2; + -+piggy: $(SYSTEM) -+ $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ ++ while (ciscnt--) { ++ cis = *pcis++; ++ i = 0; ++ do { ++ tup = cis[i++]; ++ tlen = cis[i++]; ++ if ((i + tlen) >= CIS_SIZE) ++ break; + -+mrproper: clean ++ switch (tup) { ++ case CISTPL_MANFID: ++ vp += sprintf(vp, "manfid=%d", (cis[i + 1] << 8) + cis[i]); ++ vp++; ++ vp += sprintf(vp, "prodid=%d", (cis[i + 3] << 8) + cis[i + 2]); ++ vp++; ++ break; + -+clean: -+ rm -f vmlinuz piggy -diff -Naur linux.old/arch/mips/bcm947xx/generic/Makefile linux.dev/arch/mips/bcm947xx/generic/Makefile ---- linux.old/arch/mips/bcm947xx/generic/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/generic/Makefile 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,15 @@ -+# -+# Makefile for the BCM947xx specific kernel interface routines -+# under Linux. -+# ++ case CISTPL_FUNCE: ++ switch (cis[i]) { ++ case LAN_NID: ++ ASSERT(cis[i + 1] == 6); ++ bcm_ether_ntoa((struct ether_addr *)&cis[i + 2], eabuf); ++ vp += sprintf(vp, "il0macaddr=%s", eabuf); ++ vp++; ++ break; ++ case 1: /* SDIO Extended Data */ ++ vp += sprintf(vp, "sdmaxblk=%d", ++ (cis[i + 13] << 8) | cis[i + 12]); ++ vp++; ++ break; ++ } ++ break; + -+.S.s: -+ $(CPP) $(AFLAGS) $< -o $*.s -+.S.o: -+ $(CC) $(AFLAGS) -c $< -o $*.o ++ case CISTPL_CFTABLE: ++ vp += sprintf(vp, "regwindowsz=%d", (cis[i + 7] << 8) | cis[i + 6]); ++ vp++; ++ break; + -+O_TARGET := brcm.o ++ case CISTPL_BRCM_HNBU: ++ switch (cis[i]) { ++ case HNBU_SROMREV: ++ sromrev = cis[i + 1]; ++ break; + -+obj-y := int-handler.o irq.o ++ case HNBU_CHIPID: ++ vp += sprintf(vp, "vendid=%d", (cis[i + 2] << 8) + ++ cis[i + 1]); ++ vp++; ++ vp += sprintf(vp, "devid=%d", (cis[i + 4] << 8) + ++ cis[i + 3]); ++ vp++; ++ if (tlen == 7) { ++ vp += sprintf(vp, "chiprev=%d", ++ (cis[i + 6] << 8) + cis[i + 5]); ++ vp++; ++ } ++ break; + -+include $(TOPDIR)/Rules.make -diff -Naur linux.old/arch/mips/bcm947xx/generic/int-handler.S linux.dev/arch/mips/bcm947xx/generic/int-handler.S ---- linux.old/arch/mips/bcm947xx/generic/int-handler.S 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/generic/int-handler.S 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,51 @@ -+/* -+ * Generic interrupt handler for Broadcom MIPS boards -+ * -+ * Copyright 2004, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id: int-handler.S,v 1.1 2005/03/16 13:50:00 wbx Exp $ -+ */ ++ case HNBU_BOARDREV: ++ vp += sprintf(vp, "boardrev=%d", cis[i + 1]); ++ vp++; ++ break; + -+#include ++ case HNBU_AA: ++ vp += sprintf(vp, "aa2g=%d", cis[i + 1]); ++ vp++; ++ break; + -+#include -+#include -+#include -+#include ++ case HNBU_AG: ++ vp += sprintf(vp, "ag0=%d", cis[i + 1]); ++ vp++; ++ ag_init = TRUE; ++ break; + -+/* -+ * MIPS IRQ Source -+ * -------- ------ -+ * 0 Software (ignored) -+ * 1 Software (ignored) -+ * 2 Combined hardware interrupt (hw0) -+ * 3 Hardware -+ * 4 Hardware -+ * 5 Hardware -+ * 6 Hardware -+ * 7 R4k timer -+ */ ++ case HNBU_CC: ++ ASSERT(sromrev == 1); ++ vp += sprintf(vp, "cc=%d", cis[i + 1]); ++ vp++; ++ break; + -+ .text -+ .set noreorder -+ .set noat -+ .align 5 -+ NESTED(brcmIRQ, PT_SIZE, sp) -+ SAVE_ALL -+ CLI -+ .set at -+ .set noreorder ++ case HNBU_PAPARMS: ++ if (tlen == 2) { ++ ASSERT(sromrev == 1); ++ vp += sprintf(vp, "pa0maxpwr=%d", cis[i + 1]); ++ vp++; ++ } else if (tlen >= 9) { ++ if (tlen == 10) { ++ ASSERT(sromrev == 2); ++ vp += sprintf(vp, "opo=%d", cis[i + 9]); ++ vp++; ++ } else ++ ASSERT(tlen == 9); ++ ++ for (j = 0; j < 3; j++) { ++ vp += sprintf(vp, "pa0b%d=%d", j, ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ vp++; ++ } ++ vp += sprintf(vp, "pa0itssit=%d", cis[i + 7]); ++ vp++; ++ vp += sprintf(vp, "pa0maxpwr=%d", cis[i + 8]); ++ vp++; ++ } else ++ ASSERT(tlen >= 9); ++ break; + -+ jal brcm_irq_dispatch -+ move a0, sp ++ case HNBU_OEM: ++ ASSERT(sromrev == 1); ++ vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x", ++ cis[i + 1], cis[i + 2], ++ cis[i + 3], cis[i + 4], ++ cis[i + 5], cis[i + 6], ++ cis[i + 7], cis[i + 8]); ++ vp++; ++ break; + -+ j ret_from_irq -+ nop -+ -+ END(brcmIRQ) -diff -Naur linux.old/arch/mips/bcm947xx/generic/irq.c linux.dev/arch/mips/bcm947xx/generic/irq.c ---- linux.old/arch/mips/bcm947xx/generic/irq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/generic/irq.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,130 @@ -+/* -+ * Generic interrupt control functions for Broadcom MIPS boards -+ * -+ * Copyright 2004, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id: irq.c,v 1.1 2005/03/16 13:50:00 wbx Exp $ -+ */ ++ case HNBU_BOARDFLAGS: ++ w32 = (cis[i + 2] << 8) + cis[i + 1]; ++ if (tlen == 5) ++ w32 |= (cis[i + 4] << 24) + (cis[i + 3] << 16); ++ vp += sprintf(vp, "boardflags=0x%x", w32); ++ vp++; ++ break; + -+#include -+#include -+#include -+#include -+#include -+#include ++ case HNBU_LEDS: ++ if (cis[i + 1] != 0xff) { ++ vp += sprintf(vp, "ledbh0=%d", cis[i + 1]); ++ vp++; ++ } ++ if (cis[i + 2] != 0xff) { ++ vp += sprintf(vp, "ledbh1=%d", cis[i + 2]); ++ vp++; ++ } ++ if (cis[i + 3] != 0xff) { ++ vp += sprintf(vp, "ledbh2=%d", cis[i + 3]); ++ vp++; ++ } ++ if (cis[i + 4] != 0xff) { ++ vp += sprintf(vp, "ledbh3=%d", cis[i + 4]); ++ vp++; ++ } ++ break; + -+#include -+#include -+#include ++ case HNBU_CCODE: ++ { ++ char str[3]; ++ ASSERT(sromrev > 1); ++ str[0] = cis[i + 1]; ++ str[1] = cis[i + 2]; ++ str[2] = 0; ++ vp += sprintf(vp, "ccode=%s", str); ++ vp++; ++ vp += sprintf(vp, "cctl=0x%x", cis[i + 3]); ++ vp++; ++ break; ++ } + -+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) ++ case HNBU_CCKPO: ++ ASSERT(sromrev > 2); ++ vp += sprintf(vp, "cckpo=0x%x", ++ (cis[i + 2] << 8) | cis[i + 1]); ++ vp++; ++ break; + -+extern asmlinkage void brcmIRQ(void); -+extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); ++ case HNBU_OFDMPO: ++ ASSERT(sromrev > 2); ++ vp += sprintf(vp, "ofdmpo=0x%x", ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ vp++; ++ break; ++ } ++ break; + -+void -+brcm_irq_dispatch(struct pt_regs *regs) -+{ -+ u32 cause; ++ } ++ i += tlen; ++ } while (tup != 0xff); ++ } + -+ cause = read_c0_cause() & -+ read_c0_status() & -+ CAUSEF_IP; ++ /* Set the srom version */ ++ vp += sprintf(vp, "sromrev=%d", sromrev); ++ vp++; + -+#ifdef CONFIG_KERNPROF -+ change_c0_status(cause | 1, 1); -+#else -+ clear_c0_status(cause); -+#endif ++ /* if there is no antenna gain field, set default */ ++ if (ag_init == FALSE) { ++ ASSERT(sromrev == 1); ++ vp += sprintf(vp, "ag0=%d", 0xff); ++ vp++; ++ } + -+ if (cause & CAUSEF_IP7) -+ do_IRQ(7, regs); -+ if (cause & CAUSEF_IP2) -+ do_IRQ(2, regs); -+ if (cause & CAUSEF_IP3) -+ do_IRQ(3, regs); -+ if (cause & CAUSEF_IP4) -+ do_IRQ(4, regs); -+ if (cause & CAUSEF_IP5) -+ do_IRQ(5, regs); -+ if (cause & CAUSEF_IP6) -+ do_IRQ(6, regs); -+} ++ /* final nullbyte terminator */ ++ *vp++ = '\0'; ++ varsize = (uint)(vp - base); + -+static void -+enable_brcm_irq(unsigned int irq) -+{ -+ if (irq < 8) -+ set_c0_status(1 << (irq + 8)); -+ else -+ set_c0_status(IE_IRQ0); -+} ++ ASSERT((vp - base) < VARS_MAX); + -+static void -+disable_brcm_irq(unsigned int irq) -+{ -+ if (irq < 8) -+ clear_c0_status(1 << (irq + 8)); -+ else -+ clear_c0_status(IE_IRQ0); -+} ++ if (varsize == VARS_MAX) { ++ *vars = base; ++ } else { ++ vp = MALLOC(osh, varsize); ++ ASSERT(vp); ++ if (vp) ++ bcopy(base, vp, varsize); ++ MFREE(osh, base, VARS_MAX); ++ *vars = vp; ++ if (!vp) { ++ *count = 0; ++ return -2; ++ } ++ } ++ *count = varsize; + -+static void -+ack_brcm_irq(unsigned int irq) -+{ -+ /* Already done in brcm_irq_dispatch */ ++ return (0); +} + -+static unsigned int -+startup_brcm_irq(unsigned int irq) -+{ -+ enable_brcm_irq(irq); -+ -+ return 0; /* never anything pending */ -+} + -+static void -+end_brcm_irq(unsigned int irq) ++/* set PCMCIA sprom command register */ ++static int ++sprom_cmd_pcmcia(osl_t *osh, uint8 cmd) +{ -+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) -+ enable_brcm_irq(irq); -+} -+ -+static struct hw_interrupt_type brcm_irq_type = { -+ typename: "MIPS", -+ startup: startup_brcm_irq, -+ shutdown: disable_brcm_irq, -+ enable: enable_brcm_irq, -+ disable: disable_brcm_irq, -+ ack: ack_brcm_irq, -+ end: end_brcm_irq, -+ NULL -+}; ++ uint8 status = 0; ++ uint wait_cnt = 1000; + -+void __init -+init_IRQ(void) -+{ -+ int i; ++ /* write sprom command register */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_CS, &cmd, 1); + -+ for (i = 0; i < NR_IRQS; i++) { -+ irq_desc[i].status = IRQ_DISABLED; -+ irq_desc[i].action = 0; -+ irq_desc[i].depth = 1; -+ irq_desc[i].handler = &brcm_irq_type; ++ /* wait status */ ++ while (wait_cnt--) { ++ OSL_PCMCIA_READ_ATTR(osh, SROM_CS, &status, 1); ++ if (status & SROM_DONE) ++ return 0; + } + -+ set_except_vector(0, brcmIRQ); -+ change_c0_status(ST0_IM, ALLINTS); -+ -+#ifdef CONFIG_REMOTE_DEBUG -+ printk("Breaking into debugger...\n"); -+ set_debug_traps(); -+ breakpoint(); -+#endif ++ return 1; +} -diff -Naur linux.old/arch/mips/bcm947xx/gpio.c linux.dev/arch/mips/bcm947xx/gpio.c ---- linux.old/arch/mips/bcm947xx/gpio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/gpio.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,158 @@ -+/* -+ * GPIO char driver -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ -+ */ + -+#include -+#include -+#include -+#include -+#include ++/* read a word from the PCMCIA srom */ ++static int ++sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; + -+#include -+#include -+#include -+#include ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); + -+static sb_t *gpio_sbh; -+static int gpio_major; -+static devfs_handle_t gpio_dir; -+static struct { -+ char *name; -+ devfs_handle_t handle; -+} gpio_file[] = { -+ { "in", NULL }, -+ { "out", NULL }, -+ { "outen", NULL }, -+ { "control", NULL } -+}; ++ /* set address */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); + -+static int -+gpio_open(struct inode *inode, struct file * file) -+{ -+ if (MINOR(inode->i_rdev) > ARRAYSIZE(gpio_file)) -+ return -ENODEV; ++ /* do read */ ++ if (sprom_cmd_pcmcia(osh, SROM_READ)) ++ return 1; + -+ MOD_INC_USE_COUNT; ++ /* read data */ ++ data_h = data_l = 0; ++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAH, &data_h, 1); ++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAL, &data_l, 1); ++ ++ *data = (data_h << 8) | data_l; + return 0; +} + ++/* write a word to the PCMCIA srom */ +static int -+gpio_release(struct inode *inode, struct file * file) ++sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data) +{ -+ MOD_DEC_USE_COUNT; -+ return 0; -+} ++ uint8 addr_l, addr_h, data_l, data_h; + -+static ssize_t -+gpio_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ u32 val; ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ data_l = (uint8)(data & 0xff); ++ data_h = (uint8)((data >> 8) & 0xff); + -+ switch (MINOR(file->f_dentry->d_inode->i_rdev)) { -+ case 0: -+ val = sb_gpioin(gpio_sbh); -+ break; -+ case 1: -+ val = sb_gpioout(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY); -+ break; -+ case 2: -+ val = sb_gpioouten(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY); -+ break; -+ case 3: -+ val = sb_gpiocontrol(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY); -+ break; -+ default: -+ return -ENODEV; -+ } ++ /* set address */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); + -+ if (put_user(val, (u32 *) buf)) -+ return -EFAULT; ++ /* write data */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAH, &data_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAL, &data_l, 1); + -+ return sizeof(val); ++ /* do write */ ++ return sprom_cmd_pcmcia(osh, SROM_WRITE); +} + -+static ssize_t -+gpio_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ++/* ++ * Read in and validate sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++sprom_read_pci(osl_t *osh, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc) +{ -+ u32 val; ++ int err = 0; ++ uint i; + -+ if (get_user(val, (u32 *) buf)) -+ return -EFAULT; ++ /* read the sprom */ ++ for (i = 0; i < nwords; i++) ++ buf[i] = R_REG(osh, &sprom[wordoff + i]); + -+ switch (MINOR(file->f_dentry->d_inode->i_rdev)) { -+ case 0: -+ return -EACCES; -+ case 1: -+ sb_gpioout(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY); -+ break; -+ case 2: -+ sb_gpioouten(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY); -+ break; -+ case 3: -+ sb_gpiocontrol(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY); -+ break; -+ default: -+ return -ENODEV; ++ if (check_crc) { ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, nwords * 2); ++ if (hndcrc8((uint8*)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) ++ err = 1; ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, nwords * 2); + } + -+ return sizeof(val); ++ return err; +} + -+static struct file_operations gpio_fops = { -+ owner: THIS_MODULE, -+ open: gpio_open, -+ release: gpio_release, -+ read: gpio_read, -+ write: gpio_write, -+}; -+ -+static int __init -+gpio_init(void) -+{ -+ int i; ++/* ++* Create variable table from memory. ++* Return 0 on success, nonzero on error. ++*/ ++static int ++initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count) ++{ ++ int c = (int)(end - start); + -+ if (!(gpio_sbh = sb_kattach())) -+ return -ENODEV; ++ /* do it only when there is more than just the null string */ ++ if (c > 1) { ++ char *vp = MALLOC(osh, c); ++ ASSERT(vp); ++ if (!vp) ++ return BCME_NOMEM; ++ bcopy(start, vp, c); ++ *vars = vp; ++ *count = c; ++ } ++ else { ++ *vars = NULL; ++ *count = 0; ++ } + -+ sb_gpiosetcore(gpio_sbh); ++ return 0; ++} + -+ if ((gpio_major = devfs_register_chrdev(0, "gpio", &gpio_fops)) < 0) -+ return gpio_major; ++/* ++ * Find variables with from flash. 'base' points to the beginning ++ * of the table upon enter and to the end of the table upon exit when success. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++initvars_flash(osl_t *osh, char **base, uint len, char *devpath) ++{ ++ char *vp = *base; ++ char *flash; ++ int err; ++ char *s; ++ uint l, dl, copy_len; + -+ gpio_dir = devfs_mk_dir(NULL, "gpio", NULL); ++ /* allocate memory and read in flash */ ++ if (!(flash = MALLOC(osh, NVRAM_SPACE))) ++ return BCME_NOMEM; ++ if ((err = nvram_getall(flash, NVRAM_SPACE))) ++ goto exit; + -+ for (i = 0; i < ARRAYSIZE(gpio_file); i++) { -+ gpio_file[i].handle = devfs_register(gpio_dir, -+ gpio_file[i].name, -+ DEVFS_FL_DEFAULT, gpio_major, i, -+ S_IFCHR | S_IRUGO | S_IWUGO, -+ &gpio_fops, NULL); ++ /* grab vars with the prefix in name */ ++ dl = strlen(devpath); ++ for (s = flash; s && *s; s += l + 1) { ++ l = strlen(s); ++ ++ /* skip non-matching variable */ ++ if (strncmp(s, devpath, dl)) ++ continue; ++ ++ /* is there enough room to copy? */ ++ copy_len = l - dl + 1; ++ if (len < copy_len) { ++ err = BCME_BUFTOOSHORT; ++ goto exit; ++ } ++ ++ /* no prefix, just the name=value */ ++ strcpy(vp, &s[dl]); ++ vp += copy_len; ++ len -= copy_len; + } + -+ return 0; -+} ++ /* add null string as terminator */ ++ if (len < 1) { ++ err = BCME_BUFTOOSHORT; ++ goto exit; ++ } ++ *vp++ = '\0'; + -+static void __exit -+gpio_exit(void) -+{ -+ int i; ++ *base = vp; + -+ for (i = 0; i < ARRAYSIZE(gpio_file); i++) -+ devfs_unregister(gpio_file[i].handle); -+ devfs_unregister(gpio_dir); -+ devfs_unregister_chrdev(gpio_major, "gpio"); -+ sb_detach(gpio_sbh); ++exit: MFREE(osh, flash, NVRAM_SPACE); ++ return err; +} + -+module_init(gpio_init); -+module_exit(gpio_exit); -diff -Naur linux.old/arch/mips/bcm947xx/include/bcmdevs.h linux.dev/arch/mips/bcm947xx/include/bcmdevs.h ---- linux.old/arch/mips/bcm947xx/include/bcmdevs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/bcmdevs.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,391 @@ +/* -+ * Broadcom device-specific manifest constants. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ ++ * Initialize nonvolatile variable table from flash. ++ * Return 0 on success, nonzero on error. + */ ++static int ++initvars_flash_sb(void *sbh, char **vars, uint *count) ++{ ++ osl_t *osh = sb_osh(sbh); ++ char devpath[SB_DEVPATH_BUFSZ]; ++ char *vp, *base; ++ int err; + -+#ifndef _BCMDEVS_H -+#define _BCMDEVS_H ++ ASSERT(vars); ++ ASSERT(count); + ++ if ((err = sb_devpath(sbh, devpath, sizeof(devpath)))) ++ return err; + -+/* Known PCI vendor Id's */ -+#define VENDOR_EPIGRAM 0xfeda -+#define VENDOR_BROADCOM 0x14e4 -+#define VENDOR_3COM 0x10b7 -+#define VENDOR_NETGEAR 0x1385 -+#define VENDOR_DIAMOND 0x1092 -+#define VENDOR_DELL 0x1028 -+#define VENDOR_HP 0x0e11 -+#define VENDOR_APPLE 0x106b ++ base = vp = MALLOC(osh, VARS_MAX); ++ ASSERT(vp); ++ if (!vp) ++ return BCME_NOMEM; + -+/* PCI Device Id's */ -+#define BCM4210_DEVICE_ID 0x1072 /* never used */ -+#define BCM4211_DEVICE_ID 0x4211 -+#define BCM4230_DEVICE_ID 0x1086 /* never used */ -+#define BCM4231_DEVICE_ID 0x4231 ++ if ((err = initvars_flash(osh, &vp, VARS_MAX, devpath))) ++ goto err; + -+#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */ -+#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ -+#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ -+#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */ ++ err = initvars_table(osh, base, vp, vars, count); + -+#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ -+#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ ++err: MFREE(osh, base, VARS_MAX); ++ return err; ++} + -+#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ -+#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ ++#ifdef WLTEST ++char mfgsromvars[256]; ++char *defaultsromvars = "il0macaddr=00:11:22:33:44:51\0" ++ "et0macaddr=00:11:22:33:44:52\0" ++ "et1macaddr=00:11:22:33:44:53\0" ++ "boardtype=0xffff\0" ++ "boardrev=0x10\0" ++ "boardflags=8\0" ++ "sromrev=2\0" ++ "aa2g=3"; ++#define MFGSROM_DEFVARSLEN 147 /* default srom len */ ++#endif /* WL_TEST */ + -+#define BCM47XX_ILINE_ID 0x4711 /* 47xx iline20 */ -+#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */ -+#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */ -+#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */ -+#define BCM47XX_USB_ID 0x4715 /* 47xx usb */ -+#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */ -+#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */ -+#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */ -+#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */ -+#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */ -+#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */ ++/* ++ * Initialize nonvolatile variable table from sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++initvars_srom_pci(void *sbh, void *curmap, char **vars, uint *count) ++{ ++ uint16 w, *b; ++ uint8 sromrev = 0; ++ struct ether_addr ea; ++ char eabuf[32]; ++ uint32 w32; ++ int woff, i; ++ char *vp, *base; ++ osl_t *osh = sb_osh(sbh); ++ bool flash = FALSE; ++ char name[SB_DEVPATH_BUFSZ+16], *value; ++ char devpath[SB_DEVPATH_BUFSZ]; ++ int err; + -+#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ ++ /* ++ * Apply CRC over SROM content regardless SROM is present or not, ++ * and use variable sromrev's existance in flash to decide ++ * if we should return an error when CRC fails or read SROM variables ++ * from flash. ++ */ ++ b = MALLOC(osh, SROM_MAX); ++ ASSERT(b); ++ if (!b) ++ return -2; + -+#define BCM4610_DEVICE_ID 0x4610 /* 4610 primary function 0 */ -+#define BCM4610_ILINE_ID 0x4611 /* 4610 iline100 */ -+#define BCM4610_V90_ID 0x4612 /* 4610 v90 codec */ -+#define BCM4610_ENET_ID 0x4613 /* 4610 enet */ -+#define BCM4610_EXT_ID 0x4614 /* 4610 external i/f */ -+#define BCM4610_USB_ID 0x4615 /* 4610 usb */ ++ err = sprom_read_pci(osh, (void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b, ++ 64, TRUE); ++ if (err == 0) { ++ /* srom is good and is rev < 4 */ ++ /* top word of sprom contains version and crc8 */ ++ sromrev = b[63] & 0xff; ++ /* bcm4401 sroms misprogrammed */ ++ if (sromrev == 0x10) ++ sromrev = 1; ++ } else if (b[SROM4_SIGN] == SROM4_SIGNATURE) { ++ /* If sromrev >= 4, read more */ ++ err = sprom_read_pci(osh, (void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b, ++ SROM4_WORDS, TRUE); ++ sromrev = b[SROM4_WORDS - 1] & 0xff; ++ } ++ ++ if (err) { ++#ifdef WLTEST ++ BS_ERROR(("SROM Crc Error, so see if we could use a default\n")); ++ w32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); ++ if (w32 & SPROM_OTPIN_USE) { ++ BS_ERROR(("srom crc failed with OTP, use default vars....\n")); ++ vp = base = mfgsromvars; ++ if (sb_chip(sbh) == BCM4311_CHIP_ID) { ++ BS_ERROR(("setting the devid to be 4311\n")); ++ vp += sprintf(vp, "devid=0x4311"); ++ vp++; ++ } ++ bcopy(defaultsromvars, vp, MFGSROM_DEFVARSLEN); ++ vp += MFGSROM_DEFVARSLEN; ++ goto varsdone; ++ } else { ++ BS_ERROR(("srom crc failed with SPROM....\n")); ++#endif /* WLTEST */ ++ if ((err = sb_devpath(sbh, devpath, sizeof(devpath)))) ++ return err; ++ sprintf(name, "%ssromrev", devpath); ++ if (!(value = getvar(NULL, name))) ++ return (-1); ++ sromrev = (uint8)bcm_strtoul(value, NULL, 0); ++ flash = TRUE; ++#ifdef WLTEST ++ } ++#endif /* WLTEST */ ++ } + -+#define BCM4402_DEVICE_ID 0x4402 /* 4402 primary function 0 */ -+#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ -+#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ -+#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ ++ /* srom version check */ ++ if (sromrev > 4) ++ return (-2); + -+#define BCM4301_DEVICE_ID 0x4301 /* 4301 primary function 0 */ -+#define BCM4301_D11B_ID 0x4301 /* 4301 802.11b */ ++ ASSERT(vars); ++ ASSERT(count); + -+#define BCM4307_DEVICE_ID 0x4307 /* 4307 primary function 0 */ -+#define BCM4307_V90_ID 0x4305 /* 4307 v90 codec */ -+#define BCM4307_ENET_ID 0x4306 /* 4307 enet */ -+#define BCM4307_D11B_ID 0x4307 /* 4307 802.11b */ ++ base = vp = MALLOC(osh, VARS_MAX); ++ ASSERT(vp); ++ if (!vp) ++ return -2; + -+#define BCM4306_DEVICE_ID 0x4306 /* 4306 chipcommon chipid */ -+#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ -+#define BCM4306_D11G_ID2 0x4325 -+#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ -+#define BCM4306_UART_ID 0x4322 /* 4306 uart */ -+#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ -+#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ ++ /* read variables from flash */ ++ if (flash) { ++ if ((err = initvars_flash(osh, &vp, VARS_MAX, devpath))) ++ goto err; ++ goto varsdone; ++ } + -+#define BCM4309_PKG_ID 1 /* 4309 package id */ ++ vp += sprintf(vp, "sromrev=%d", sromrev); ++ vp++; + -+#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ -+#define BCM4303_PKG_ID 2 /* 4303 package id */ ++ if (sromrev >= 4) { ++ uint path, pathbase; ++ const uint pathbases[MAX_PATH] = {SROM4_PATH0, SROM4_PATH1, ++ SROM4_PATH2, SROM4_PATH3}; + -+#define BCM4310_DEVICE_ID 0x4310 /* 4310 chipcommon chipid */ -+#define BCM4310_D11B_ID 0x4311 /* 4310 802.11b */ -+#define BCM4310_UART_ID 0x4312 /* 4310 uart */ -+#define BCM4310_ENET_ID 0x4313 /* 4310 enet */ -+#define BCM4310_USB_ID 0x4315 /* 4310 usb */ ++ vp += sprintf(vp, "boardrev=%d", b[SROM4_BREV]); ++ vp++; + -+#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ -+#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ ++ vp += sprintf(vp, "boardflags=%d", (b[SROM4_BFL1] << 16) | b[SROM4_BFL0]); ++ vp++; + ++ vp += sprintf(vp, "boardflags2=%d", (b[SROM4_BFL3] << 16) | b[SROM4_BFL2]); ++ vp++; + -+#define BCM4704_DEVICE_ID 0x4704 /* 4704 chipcommon chipid */ -+#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ ++ /* The macaddr */ ++ ea.octet[0] = (b[SROM4_MACHI] >> 8) & 0xff; ++ ea.octet[1] = b[SROM4_MACHI] & 0xff; ++ ea.octet[2] = (b[SROM4_MACMID] >> 8) & 0xff; ++ ea.octet[3] = b[SROM4_MACMID] & 0xff; ++ ea.octet[4] = (b[SROM4_MACLO] >> 8) & 0xff; ++ ea.octet[5] = b[SROM4_MACLO] & 0xff; ++ bcm_ether_ntoa(&ea, eabuf); ++ vp += sprintf(vp, "macaddr=%s", eabuf); ++ vp++; + -+#define BCM4317_DEVICE_ID 0x4317 /* 4317 chip common chipid */ ++ w = b[SROM4_CCODE]; ++ if (w == 0) ++ vp += sprintf(vp, "ccode="); ++ else ++ vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff)); ++ vp++; ++ vp += sprintf(vp, "regrev=%d", b[SROM4_REGREV]); ++ vp++; + -+#define BCM4318_DEVICE_ID 0x4318 /* 4318 chip common chipid */ -+#define BCM4318_D11G_ID 0x4318 /* 4318 801.11b/g id */ -+#define BCM4318_D11DUAL_ID 0x4319 /* 4318 801.11a/b/g id */ -+#define BCM4318_JTAGM_ID 0x4331 /* 4318 jtagm device id */ ++ w = b[SROM4_LEDBH10]; ++ if ((w != 0) && (w != 0xffff)) { ++ /* ledbh0 */ ++ vp += sprintf(vp, "ledbh0=%d", (w & 0xff)); ++ vp++; + -+#define FPGA_JTAGM_ID 0x4330 /* ??? */ -+ -+/* Address map */ -+#define BCM4710_SDRAM 0x00000000 /* Physical SDRAM */ -+#define BCM4710_PCI_MEM 0x08000000 /* Host Mode PCI memory access space (64 MB) */ -+#define BCM4710_PCI_CFG 0x0c000000 /* Host Mode PCI configuration space (64 MB) */ -+#define BCM4710_PCI_DMA 0x40000000 /* Client Mode PCI memory access space (1 GB) */ -+#define BCM4710_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ -+#define BCM4710_ENUM 0x18000000 /* Beginning of core enumeration space */ ++ /* ledbh1 */ ++ vp += sprintf(vp, "ledbh1=%d", (w >> 8) & 0xff); ++ vp++; ++ } ++ w = b[SROM4_LEDBH32]; ++ if ((w != 0) && (w != 0xffff)) { ++ /* ledbh2 */ ++ vp += sprintf(vp, "ledbh2=%d", w & 0xff); ++ vp++; + -+/* Core register space */ -+#define BCM4710_REG_SDRAM 0x18000000 /* SDRAM core registers */ -+#define BCM4710_REG_ILINE20 0x18001000 /* InsideLine20 core registers */ -+#define BCM4710_REG_EMAC0 0x18002000 /* Ethernet MAC 0 core registers */ -+#define BCM4710_REG_CODEC 0x18003000 /* Codec core registers */ -+#define BCM4710_REG_USB 0x18004000 /* USB core registers */ -+#define BCM4710_REG_PCI 0x18005000 /* PCI core registers */ -+#define BCM4710_REG_MIPS 0x18006000 /* MIPS core registers */ -+#define BCM4710_REG_EXTIF 0x18007000 /* External Interface core registers */ -+#define BCM4710_REG_EMAC1 0x18008000 /* Ethernet MAC 1 core registers */ ++ /* ledbh3 */ ++ vp += sprintf(vp, "ledbh3=%d", (w >> 8) & 0xff); ++ vp++; ++ } ++ /* LED Powersave duty cycle (oncount >> 24) (offcount >> 8) */ ++ w = b[SROM4_LEDDC]; ++ w32 = ((uint32)((unsigned char)(w >> 8) & 0xff) << 24) | /* oncount */ ++ ((uint32)((unsigned char)(w & 0xff)) << 8); /* offcount */ ++ vp += sprintf(vp, "leddc=%d", w32); ++ vp++; + -+#define BCM4710_EXTIF 0x1f000000 /* External Interface base address */ -+#define BCM4710_PCMCIA_MEM 0x1f000000 /* External Interface PCMCIA memory access */ -+#define BCM4710_PCMCIA_IO 0x1f100000 /* PCMCIA I/O access */ -+#define BCM4710_PCMCIA_CONF 0x1f200000 /* PCMCIA configuration */ -+#define BCM4710_PROG 0x1f800000 /* Programable interface */ -+#define BCM4710_FLASH 0x1fc00000 /* Flash */ ++ w = b[SROM4_AA]; ++ vp += sprintf(vp, "aa2g=%d", w & SROM4_AA2G_MASK); ++ vp++; ++ vp += sprintf(vp, "aa5g=%d", w >> SROM4_AA5G_SHIFT); ++ vp++; + -+#define BCM4710_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */ ++ w = b[SROM4_AG10]; ++ vp += sprintf(vp, "ag0=%d", w & 0xff); ++ vp++; ++ vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff); ++ vp++; ++ w = b[SROM4_AG32]; ++ vp += sprintf(vp, "ag2=%d", w & 0xff); ++ vp++; ++ vp += sprintf(vp, "ag3=%d", (w >> 8) & 0xff); ++ vp++; + -+#define BCM4710_UART (BCM4710_REG_EXTIF + 0x00000300) ++ /* Fixed power indices when power control is disabled */ ++ for (i = 0; i < 2; i++) { ++ w = b[SROM4_TXPID2G + i]; ++ vp += sprintf(vp, "txpid2ga%d=%d", 2 * i, w & 0xff); ++ vp++; ++ vp += sprintf(vp, "txpid2ga%d=%d", (2 * i) + 1, (w >> 8) & 0xff); ++ vp++; ++ w = b[SROM4_TXPID5G + i]; ++ vp += sprintf(vp, "txpid5ga%d=%d", 2 * i, w & 0xff); ++ vp++; ++ vp += sprintf(vp, "txpid5ga%d=%d", (2 * i) + 1, (w >> 8) & 0xff); ++ vp++; ++ w = b[SROM4_TXPID5GL + i]; ++ vp += sprintf(vp, "txpid5gla%d=%d", 2 * i, w & 0xff); ++ vp++; ++ vp += sprintf(vp, "txpid5gla%d=%d", (2 * i) + 1, (w >> 8) & 0xff); ++ vp++; ++ w = b[SROM4_TXPID5GH + i]; ++ vp += sprintf(vp, "txpid5gha%d=%d", 2 * i, w & 0xff); ++ vp++; ++ vp += sprintf(vp, "txpid5gha%d=%d", (2 * i) + 1, (w >> 8) & 0xff); ++ vp++; ++ } + -+#define BCM4710_EUART (BCM4710_EXTIF + 0x00800000) -+#define BCM4710_LED (BCM4710_EXTIF + 0x00900000) ++ /* Per path variables */ ++ for (path = 0; path < MAX_PATH; path++) { ++ pathbase = pathbases[path]; ++ w = b[pathbase + SROM4_2G_ITT_MAXP]; ++ vp += sprintf(vp, "itt2ga%d=%d", path, w >> B2G_ITT_SHIFT); ++ vp++; ++ vp += sprintf(vp, "maxp2ga%d=%d", path, w & B2G_MAXP_MASK); ++ vp++; + -+#define BCM4712_DEVICE_ID 0x4712 /* 4712 chipcommon chipid */ -+#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ -+#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ -+#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ -+#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ ++ for (i = 0; i < 4; i++) { ++ vp += sprintf(vp, "pa2gw%da%d=%d", i, path, ++ b[pathbase + SROM4_2G_PA + i]); ++ vp++; ++ } + -+#define SDIOH_FPGA_ID 0x4380 /* sdio host fpga */ ++ w = b[pathbase + SROM4_5G_ITT_MAXP]; ++ vp += sprintf(vp, "itt5ga%d=%d", path, w >> B5G_ITT_SHIFT); ++ vp++; ++ vp += sprintf(vp, "maxp5ga%d=%d", path, w & B5G_MAXP_MASK); ++ vp++; + -+#define BCM5365_DEVICE_ID 0x5365 /* 5365 chipcommon chipid */ -+#define BCM5350_DEVICE_ID 0x5350 /* bcm5350 chipcommon chipid */ -+#define BCM5352_DEVICE_ID 0x5352 /* bcm5352 chipcommon chipid */ ++ w = b[pathbase + SROM4_5GLH_MAXP]; ++ vp += sprintf(vp, "maxp5lga%d=%d", path, w >> B5GL_MAXP_SHIFT); ++ vp++; ++ vp += sprintf(vp, "maxp5gha%d=%d", path, w & B5GH_MAXP_MASK); ++ vp++; + -+#define BCM4320_DEVICE_ID 0x4320 /* bcm4320 chipcommon chipid */ ++ for (i = 0; i < 4; i++) { ++ vp += sprintf(vp, "pa5gw%da%d=%d", i, path, ++ b[pathbase + SROM4_5G_PA + i]); ++ vp++; ++ vp += sprintf(vp, "pa5glw%da%d=%d", i, path, ++ b[pathbase + SROM4_5GL_PA + i]); ++ vp++; ++ vp += sprintf(vp, "pa5hgw%da%d=%d", i, path, ++ b[pathbase + SROM4_5GH_PA + i]); ++ vp++; ++ } ++ } + -+/* PCMCIA vendor Id's */ ++ vp += sprintf(vp, "cck2gpo=%d", b[SROM4_2G_CCKPO]); ++ vp++; + -+#define VENDOR_BROADCOM_PCMCIA 0x02d0 ++ w32 = ((uint32)b[SROM4_2G_OFDMPO + 1] << 16) | b[SROM4_2G_OFDMPO]; ++ vp += sprintf(vp, "ofdm2gpo=%d", w32); ++ vp++; + -+/* SDIO vendor Id's */ -+#define VENDOR_BROADCOM_SDIO 0x00BF ++ w32 = ((uint32)b[SROM4_5G_OFDMPO + 1] << 16) | b[SROM4_5G_OFDMPO]; ++ vp += sprintf(vp, "ofdm5gpo=%d", w32); ++ vp++; + ++ w32 = ((uint32)b[SROM4_5GL_OFDMPO + 1] << 16) | b[SROM4_5GL_OFDMPO]; ++ vp += sprintf(vp, "ofdm5glpo=%d", w32); ++ vp++; + -+/* boardflags */ -+#define BFL_BTCOEXIST 0x0001 /* This board implements Bluetooth coexistance */ -+#define BFL_PACTRL 0x0002 /* This board has gpio 9 controlling the PA */ -+#define BFL_AIRLINEMODE 0x0004 /* This board implements gpio13 radio disable indication */ -+#define BFL_ENETROBO 0x0010 /* This board has robo switch or core */ -+#define BFL_CCKHIPWR 0x0040 /* Can do high-power CCK transmission */ -+#define BFL_ENETADM 0x0080 /* This board has ADMtek switch */ -+#define BFL_ENETVLAN 0x0100 /* This board has vlan capability */ -+#define BFL_AFTERBURNER 0x0200 /* This board supports Afterburner mode */ -+#define BFL_NOPCI 0x0400 /* This board leaves PCI floating */ -+#define BFL_FEM 0x0800 /* This board supports the Front End Module */ -+#define BFL_EXTLNA 0x1000 /* This board has an external LNA */ -+#define BFL_HGPA 0x2000 /* This board has a high gain PA */ -+#define BFL_BTCMOD 0x4000 /* This board' BTCOEXIST is in the alternate gpios */ -+#define BFL_ALTIQ 0x8000 /* Alternate I/Q settings */ ++ w32 = ((uint32)b[SROM4_5GH_OFDMPO + 1] << 16) | b[SROM4_5GH_OFDMPO]; ++ vp += sprintf(vp, "ofdm5ghpo=%d", w32); ++ vp++; + -+/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ -+#define BOARD_GPIO_HWRAD_B 0x010 /* bit 4 is HWRAD input on 4301 */ -+#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistance Input */ -+#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistance Out */ -+#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistance Input */ -+#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistance Out */ -+#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ -+#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ -+#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ -+#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ -+#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ ++ for (i = 0; i < 8; i++) { ++ vp += sprintf(vp, "mcs2gpo%d=%d", i, b[SROM4_2G_MCSPO]); ++ vp++; ++ vp += sprintf(vp, "mcs5gpo%d=%d", i, b[SROM4_5G_MCSPO]); ++ vp++; ++ vp += sprintf(vp, "mcs5glpo%d=%d", i, b[SROM4_5GL_MCSPO]); ++ vp++; ++ vp += sprintf(vp, "mcs5ghpo%d=%d", i, b[SROM4_5GH_MCSPO]); ++ vp++; ++ } + -+/* Bus types */ -+#define SB_BUS 0 /* Silicon Backplane */ -+#define PCI_BUS 1 /* PCI target */ -+#define PCMCIA_BUS 2 /* PCMCIA target */ -+#define SDIO_BUS 3 /* SDIO target */ -+#define JTAG_BUS 4 /* JTAG */ ++ vp += sprintf(vp, "ccdpo%d=%d", i, b[SROM4_CCDPO]); ++ vp++; ++ vp += sprintf(vp, "stbcpo%d=%d", i, b[SROM4_STBCPO]); ++ vp++; ++ vp += sprintf(vp, "bw40po%d=%d", i, b[SROM4_BW40PO]); ++ vp++; ++ vp += sprintf(vp, "bwduppo%d=%d", i, b[SROM4_BWDUPPO]); ++ vp++; + -+/* Allows optimization for single-bus support */ -+#ifdef BCMBUSTYPE -+#define BUSTYPE(bus) (BCMBUSTYPE) -+#else -+#define BUSTYPE(bus) (bus) -+#endif ++ goto done; ++ } ++ if (sromrev >= 3) { ++ /* New section takes over the 3th hardware function space */ + -+/* power control defines */ -+#define PLL_DELAY 150 /* us pll on delay */ -+#define FREF_DELAY 200 /* us fref change delay */ -+#define MIN_SLOW_CLK 32 /* us Slow clock period */ -+#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ ++ /* Words 22+23 are 11a (mid) ofdm power offsets */ ++ w32 = ((uint32)b[23] << 16) | b[22]; ++ vp += sprintf(vp, "ofdmapo=%d", w32); ++ vp++; + -+/* Reference Board Types */ ++ /* Words 24+25 are 11a (low) ofdm power offsets */ ++ w32 = ((uint32)b[25] << 16) | b[24]; ++ vp += sprintf(vp, "ofdmalpo=%d", w32); ++ vp++; + -+#define BU4710_BOARD 0x0400 -+#define VSIM4710_BOARD 0x0401 -+#define QT4710_BOARD 0x0402 ++ /* Words 26+27 are 11a (high) ofdm power offsets */ ++ w32 = ((uint32)b[27] << 16) | b[26]; ++ vp += sprintf(vp, "ofdmahpo=%d", w32); ++ vp++; + -+#define BU4610_BOARD 0x0403 -+#define VSIM4610_BOARD 0x0404 ++ /* LED Powersave duty cycle (oncount >> 24) (offcount >> 8) */ ++ w32 = ((uint32)((unsigned char)(b[21] >> 8) & 0xff) << 24) | /* oncount */ ++ ((uint32)((unsigned char)(b[21] & 0xff)) << 8); /* offcount */ ++ vp += sprintf(vp, "leddc=%d", w32); + -+#define BU4307_BOARD 0x0405 -+#define BCM94301CB_BOARD 0x0406 -+#define BCM94301PC_BOARD 0x0406 /* Pcmcia 5v card */ -+#define BCM94301MP_BOARD 0x0407 -+#define BCM94307MP_BOARD 0x0408 -+#define BCMAP4307_BOARD 0x0409 ++ vp++; ++ } + -+#define BU4309_BOARD 0x040a -+#define BCM94309CB_BOARD 0x040b -+#define BCM94309MP_BOARD 0x040c -+#define BCM4309AP_BOARD 0x040d ++ if (sromrev >= 2) { ++ /* New section takes over the 4th hardware function space */ + -+#define BCM94302MP_BOARD 0x040e ++ /* Word 29 is max power 11a high/low */ ++ w = b[29]; ++ vp += sprintf(vp, "pa1himaxpwr=%d", w & 0xff); ++ vp++; ++ vp += sprintf(vp, "pa1lomaxpwr=%d", (w >> 8) & 0xff); ++ vp++; + -+#define VSIM4310_BOARD 0x040f -+#define BU4711_BOARD 0x0410 -+#define BCM94310U_BOARD 0x0411 -+#define BCM94310AP_BOARD 0x0412 -+#define BCM94310MP_BOARD 0x0414 ++ /* Words 30-32 set the 11alow pa settings, ++ * 33-35 are the 11ahigh ones. ++ */ ++ for (i = 0; i < 3; i++) { ++ vp += sprintf(vp, "pa1lob%d=%d", i, b[30 + i]); ++ vp++; ++ vp += sprintf(vp, "pa1hib%d=%d", i, b[33 + i]); ++ vp++; ++ } ++ w = b[59]; ++ if (w == 0) ++ vp += sprintf(vp, "ccode="); ++ else ++ vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff)); ++ vp++; + -+#define BU4306_BOARD 0x0416 -+#define BCM94306CB_BOARD 0x0417 -+#define BCM94306MP_BOARD 0x0418 ++ } + -+#define BCM94710D_BOARD 0x041a -+#define BCM94710R1_BOARD 0x041b -+#define BCM94710R4_BOARD 0x041c -+#define BCM94710AP_BOARD 0x041d ++ /* parameter section of sprom starts at byte offset 72 */ ++ woff = 72/2; + ++ /* first 6 bytes are il0macaddr */ ++ ea.octet[0] = (b[woff] >> 8) & 0xff; ++ ea.octet[1] = b[woff] & 0xff; ++ ea.octet[2] = (b[woff+1] >> 8) & 0xff; ++ ea.octet[3] = b[woff+1] & 0xff; ++ ea.octet[4] = (b[woff+2] >> 8) & 0xff; ++ ea.octet[5] = b[woff+2] & 0xff; ++ woff += 3; ++ bcm_ether_ntoa(&ea, eabuf); ++ vp += sprintf(vp, "il0macaddr=%s", eabuf); ++ vp++; + -+#define BU2050_BOARD 0x041f ++ /* next 6 bytes are et0macaddr */ ++ ea.octet[0] = (b[woff] >> 8) & 0xff; ++ ea.octet[1] = b[woff] & 0xff; ++ ea.octet[2] = (b[woff+1] >> 8) & 0xff; ++ ea.octet[3] = b[woff+1] & 0xff; ++ ea.octet[4] = (b[woff+2] >> 8) & 0xff; ++ ea.octet[5] = b[woff+2] & 0xff; ++ woff += 3; ++ bcm_ether_ntoa(&ea, eabuf); ++ vp += sprintf(vp, "et0macaddr=%s", eabuf); ++ vp++; + ++ /* next 6 bytes are et1macaddr */ ++ ea.octet[0] = (b[woff] >> 8) & 0xff; ++ ea.octet[1] = b[woff] & 0xff; ++ ea.octet[2] = (b[woff+1] >> 8) & 0xff; ++ ea.octet[3] = b[woff+1] & 0xff; ++ ea.octet[4] = (b[woff+2] >> 8) & 0xff; ++ ea.octet[5] = b[woff+2] & 0xff; ++ woff += 3; ++ bcm_ether_ntoa(&ea, eabuf); ++ vp += sprintf(vp, "et1macaddr=%s", eabuf); ++ vp++; + -+#define BCM94309G_BOARD 0x0421 ++ /* ++ * Enet phy settings one or two singles or a dual ++ * Bits 4-0 : MII address for enet0 (0x1f for not there) ++ * Bits 9-5 : MII address for enet1 (0x1f for not there) ++ * Bit 14 : Mdio for enet0 ++ * Bit 15 : Mdio for enet1 ++ */ ++ w = b[woff]; ++ vp += sprintf(vp, "et0phyaddr=%d", (w & 0x1f)); ++ vp++; ++ vp += sprintf(vp, "et1phyaddr=%d", ((w >> 5) & 0x1f)); ++ vp++; ++ vp += sprintf(vp, "et0mdcport=%d", ((w >> 14) & 0x1)); ++ vp++; ++ vp += sprintf(vp, "et1mdcport=%d", ((w >> 15) & 0x1)); ++ vp++; + -+#define BCM94301PC3_BOARD 0x0422 /* Pcmcia 3.3v card */ ++ /* Word 46 has board rev, antennas 0/1 & Country code/control */ ++ w = b[46]; ++ vp += sprintf(vp, "boardrev=%d", w & 0xff); ++ vp++; + -+#define BU4704_BOARD 0x0423 -+#define BU4702_BOARD 0x0424 ++ if (sromrev > 1) ++ vp += sprintf(vp, "cctl=%d", (w >> 8) & 0xf); ++ else ++ vp += sprintf(vp, "cc=%d", (w >> 8) & 0xf); ++ vp++; + -+#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */ ++ vp += sprintf(vp, "aa2g=%d", (w >> 12) & 0x3); ++ vp++; + -+#define BU4317_BOARD 0x0426 ++ vp += sprintf(vp, "aa5g=%d", (w >> 14) & 0x3); ++ vp++; + ++ /* Words 47-49 set the (wl) pa settings */ ++ woff = 47; + -+#define BCM94702MN_BOARD 0x0428 ++ for (i = 0; i < 3; i++) { ++ vp += sprintf(vp, "pa0b%d=%d", i, b[woff+i]); ++ vp++; ++ vp += sprintf(vp, "pa1b%d=%d", i, b[woff+i+6]); ++ vp++; ++ } + -+/* BCM4702 1U CompactPCI Board */ -+#define BCM94702CPCI_BOARD 0x0429 ++ /* ++ * Words 50-51 set the customer-configured wl led behavior. ++ * 8 bits/gpio pin. High bit: activehi=0, activelo=1; ++ * LED behavior values defined in wlioctl.h . ++ */ ++ w = b[50]; ++ if ((w != 0) && (w != 0xffff)) { ++ /* ledbh0 */ ++ vp += sprintf(vp, "ledbh0=%d", (w & 0xff)); ++ vp++; + -+/* BCM4702 with BCM95380 VLAN Router */ -+#define BCM95380RR_BOARD 0x042a ++ /* ledbh1 */ ++ vp += sprintf(vp, "ledbh1=%d", (w >> 8) & 0xff); ++ vp++; ++ } ++ w = b[51]; ++ if ((w != 0) && (w != 0xffff)) { ++ /* ledbh2 */ ++ vp += sprintf(vp, "ledbh2=%d", w & 0xff); ++ vp++; + -+/* cb4306 with SiGe PA */ -+#define BCM94306CBSG_BOARD 0x042b ++ /* ledbh */ ++ vp += sprintf(vp, "ledbh3=%d", (w >> 8) & 0xff); ++ vp++; ++ } + -+/* mp4301 with 2050 radio */ -+#define BCM94301MPL_BOARD 0x042c ++ /* Word 52 is max power 0/1 */ ++ w = b[52]; ++ vp += sprintf(vp, "pa0maxpwr=%d", w & 0xff); ++ vp++; ++ vp += sprintf(vp, "pa1maxpwr=%d", (w >> 8) & 0xff); ++ vp++; + -+/* cb4306 with SiGe PA */ -+#define PCSG94306_BOARD 0x042d ++ /* Word 56 is idle tssi target 0/1 */ ++ w = b[56]; ++ vp += sprintf(vp, "pa0itssit=%d", w & 0xff); ++ vp++; ++ vp += sprintf(vp, "pa1itssit=%d", (w >> 8) & 0xff); ++ vp++; + -+/* bu4704 with sdram */ -+#define BU4704SD_BOARD 0x042e ++ /* Word 57 is boardflags, if not programmed make it zero */ ++ w32 = (uint32)b[57]; ++ if (w32 == 0xffff) w32 = 0; ++ if (sromrev > 1) { ++ /* Word 28 is the high bits of boardflags */ ++ w32 |= (uint32)b[28] << 16; ++ } ++ vp += sprintf(vp, "boardflags=%d", w32); ++ vp++; + -+/* Dual 11a/11g Router */ -+#define BCM94704AGR_BOARD 0x042f ++ /* Word 58 is antenna gain 0/1 */ ++ w = b[58]; ++ vp += sprintf(vp, "ag0=%d", w & 0xff); ++ vp++; + -+/* 11a-only minipci */ -+#define BCM94308MP_BOARD 0x0430 ++ vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff); ++ vp++; + ++ if (sromrev == 1) { ++ /* set the oem string */ ++ vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x", ++ ((b[59] >> 8) & 0xff), (b[59] & 0xff), ++ ((b[60] >> 8) & 0xff), (b[60] & 0xff), ++ ((b[61] >> 8) & 0xff), (b[61] & 0xff), ++ ((b[62] >> 8) & 0xff), (b[62] & 0xff)); ++ vp++; ++ } else if (sromrev == 2) { ++ /* Word 60 OFDM tx power offset from CCK level */ ++ /* OFDM Power Offset - opo */ ++ vp += sprintf(vp, "opo=%d", b[60] & 0xff); ++ vp++; ++ } else { ++ /* Word 60: cck power offsets */ ++ vp += sprintf(vp, "cckpo=%d", b[60]); ++ vp++; + ++ /* Words 61+62: 11g ofdm power offsets */ ++ w32 = ((uint32)b[62] << 16) | b[61]; ++ vp += sprintf(vp, "ofdmgpo=%d", w32); ++ vp++; ++ } + -+/* BCM94317 boards */ -+#define BCM94317CB_BOARD 0x0440 -+#define BCM94317MP_BOARD 0x0441 -+#define BCM94317PCMCIA_BOARD 0x0442 -+#define BCM94317SDIO_BOARD 0x0443 ++ /* final nullbyte terminator */ ++done: *vp++ = '\0'; + -+#define BU4712_BOARD 0x0444 -+#define BU4712SD_BOARD 0x045d -+#define BU4712L_BOARD 0x045f ++ ASSERT((vp - base) <= VARS_MAX); + -+/* BCM4712 boards */ -+#define BCM94712AP_BOARD 0x0445 -+#define BCM94712P_BOARD 0x0446 ++varsdone: ++ err = initvars_table(osh, base, vp, vars, count); + -+/* BCM4318 boards */ -+#define BU4318_BOARD 0x0447 -+#define CB4318_BOARD 0x0448 -+#define MPG4318_BOARD 0x0449 -+#define MP4318_BOARD 0x044a -+#define SD4318_BOARD 0x044b ++err: ++#ifdef WLTEST ++ if (base != mfgsromvars) ++#endif ++ MFREE(osh, base, VARS_MAX); ++ MFREE(osh, b, SROM_MAX); ++ return err; ++} + -+/* BCM63XX boards */ -+#define BCM96338_BOARD 0x6338 -+#define BCM96345_BOARD 0x6345 -+#define BCM96348_BOARD 0x6348 ++/* ++ * Read the cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++initvars_cis_pcmcia(void *sbh, osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis = NULL; ++ int rc; ++ uint data_sz; + -+/* Another mp4306 with SiGe */ -+#define BCM94306P_BOARD 0x044c ++ data_sz = (sb_pcmciarev(sbh) == 1) ? (SPROM_SIZE * 2) : CIS_SIZE; + -+/* CF-like 4317 modules */ -+#define BCM94317CF_BOARD 0x044d ++ if ((cis = MALLOC(osh, data_sz)) == NULL) ++ return (-2); + -+/* mp4303 */ -+#define BCM94303MP_BOARD 0x044e ++ if (sb_pcmciarev(sbh) == 1) { ++ if (srom_read(PCMCIA_BUS, (void *)NULL, osh, 0, data_sz, (uint16 *)cis)) { ++ MFREE(osh, cis, data_sz); ++ return (-1); ++ } ++ /* fix up endianess for 16-bit data vs 8-bit parsing */ ++ ltoh16_buf((uint16 *)cis, data_sz); ++ } else ++ OSL_PCMCIA_READ_ATTR(osh, 0, cis, data_sz); + -+/* mpsgh4306 */ -+#define BCM94306MPSGH_BOARD 0x044f ++ rc = srom_parsecis(osh, &cis, 1, vars, count); + -+/* BRCM 4306 w/ Front End Modules */ -+#define BCM94306MPM 0x0450 -+#define BCM94306MPL 0x0453 ++ MFREE(osh, cis, data_sz); + -+/* 4712agr */ -+#define BCM94712AGR_BOARD 0x0451 ++ return (rc); ++} + -+/* The real CF 4317 board */ -+#define CFI4317_BOARD 0x0452 +diff -urN linux.old/arch/mips/bcm947xx/bcmutils.c linux.dev/arch/mips/bcm947xx/bcmutils.c +--- linux.old/arch/mips/bcm947xx/bcmutils.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/bcmutils.c 2006-04-28 00:34:02.000000000 +0200 +@@ -0,0 +1,247 @@ ++/* ++ * Misc useful OS-independent routines. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * $Id: bcmutils.c,v 1.1.1.12 2006/02/27 03:43:16 honor Exp $ ++ */ + -+/* pcmcia 4303 */ -+#define PC4303_BOARD 0x0454 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+/* 5350K */ -+#define BCM95350K_BOARD 0x0455 ++unsigned char bcm_ctype[] = { ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ ++ _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C, ++ _BCM_C, /* 8-15 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ ++ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ ++ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ ++ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ ++ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ ++ _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, ++ _BCM_U|_BCM_X, _BCM_U, /* 64-71 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ ++ _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, ++ _BCM_L|_BCM_X, _BCM_L, /* 96-103 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ ++ _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ ++}; + -+/* 5350R */ -+#define BCM95350R_BOARD 0x0456 + -+/* 4306mplna */ -+#define BCM94306MPLNA_BOARD 0x0457 ++ulong ++bcm_strtoul(char *cp, char **endp, uint base) ++{ ++ ulong result, value; ++ bool minus; + -+/* 4320 boards */ -+#define BU4320_BOARD 0x0458 -+#define BU4320S_BOARD 0x0459 -+#define BCM94320PH_BOARD 0x045a ++ minus = FALSE; + -+/* 4306mph */ -+#define BCM94306MPH_BOARD 0x045b ++ while (bcm_isspace(*cp)) ++ cp++; + -+/* 4306pciv */ -+#define BCM94306PCIV_BOARD 0x045c ++ if (cp[0] == '+') ++ cp++; ++ else if (cp[0] == '-') { ++ minus = TRUE; ++ cp++; ++ } + -+#define BU4712SD_BOARD 0x045d ++ if (base == 0) { ++ if (cp[0] == '0') { ++ if ((cp[1] == 'x') || (cp[1] == 'X')) { ++ base = 16; ++ cp = &cp[2]; ++ } else { ++ base = 8; ++ cp = &cp[1]; ++ } ++ } else ++ base = 10; ++ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { ++ cp = &cp[2]; ++ } + -+#define BCM94320PFLSH_BOARD 0x045e ++ result = 0; + -+#define BU4712L_BOARD 0x045f -+#define BCM94712LGR_BOARD 0x0460 -+#define BCM94320R_BOARD 0x0461 ++ while (bcm_isxdigit(*cp) && ++ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { ++ result = result*base + value; ++ cp++; ++ } + -+#define BU5352_BOARD 0x0462 ++ if (minus) ++ result = (ulong)(result * -1); + -+#define BCM94318MPGH_BOARD 0x0463 ++ if (endp) ++ *endp = (char *)cp; + ++ return (result); ++} + -+#define BCM95352GR_BOARD 0x0467 ++uchar ++bcm_toupper(uchar c) ++{ ++ if (bcm_islower(c)) ++ c -= 'a'-'A'; ++ return (c); ++} + -+/* bcm95351agr */ -+#define BCM95351AGR_BOARD 0x0470 ++char* ++bcm_ether_ntoa(struct ether_addr *ea, char *buf) ++{ ++ sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", ++ ea->octet[0]&0xff, ea->octet[1]&0xff, ea->octet[2]&0xff, ++ ea->octet[3]&0xff, ea->octet[4]&0xff, ea->octet[5]&0xff); ++ return (buf); ++} + -+/* # of GPIO pins */ -+#define GPIO_NUMPINS 16 + -+#endif /* _BCMDEVS_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/bcmendian.h linux.dev/arch/mips/bcm947xx/include/bcmendian.h ---- linux.old/arch/mips/bcm947xx/include/bcmendian.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/bcmendian.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,152 @@ +/* -+ * local version of endian.h - byte order defines -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ -+*/ -+ -+#ifndef _BCMENDIAN_H_ -+#define _BCMENDIAN_H_ ++ * Search the name=value vars for a specific one and return its value. ++ * Returns NULL if not found. ++ */ ++char* ++getvar(char *vars, char *name) ++{ ++ char *s; ++ int len; + -+#include ++ len = strlen(name); + -+/* Byte swap a 16 bit value */ -+#define BCMSWAP16(val) \ -+ ((uint16)( \ -+ (((uint16)(val) & (uint16)0x00ffU) << 8) | \ -+ (((uint16)(val) & (uint16)0xff00U) >> 8) )) -+ -+/* Byte swap a 32 bit value */ -+#define BCMSWAP32(val) \ -+ ((uint32)( \ -+ (((uint32)(val) & (uint32)0x000000ffUL) << 24) | \ -+ (((uint32)(val) & (uint32)0x0000ff00UL) << 8) | \ -+ (((uint32)(val) & (uint32)0x00ff0000UL) >> 8) | \ -+ (((uint32)(val) & (uint32)0xff000000UL) >> 24) )) -+ -+/* 2 Byte swap a 32 bit value */ -+#define BCMSWAP32BY16(val) \ -+ ((uint32)( \ -+ (((uint32)(val) & (uint32)0x0000ffffUL) << 16) | \ -+ (((uint32)(val) & (uint32)0xffff0000UL) >> 16) )) -+ ++ /* first look in vars[] */ ++ for (s = vars; s && *s;) { ++ /* CSTYLED */ ++ if ((memcmp(s, name, len) == 0) && (s[len] == '=')) ++ return (&s[len+1]); + -+static INLINE uint16 -+bcmswap16(uint16 val) -+{ -+ return BCMSWAP16(val); -+} ++ while (*s++) ++ ; ++ } + -+static INLINE uint32 -+bcmswap32(uint32 val) -+{ -+ return BCMSWAP32(val); ++ /* then query nvram */ ++ return (nvram_get(name)); +} + -+static INLINE uint32 -+bcmswap32by16(uint32 val) ++/* ++ * Search the vars for a specific one and return its value as ++ * an integer. Returns 0 if not found. ++ */ ++int ++getintvar(char *vars, char *name) +{ -+ return BCMSWAP32BY16(val); -+} ++ char *val; + -+/* buf - start of buffer of shorts to swap */ -+/* len - byte length of buffer */ -+static INLINE void -+bcmswap16_buf(uint16 *buf, uint len) -+{ -+ len = len/2; ++ if ((val = getvar(vars, name)) == NULL) ++ return (0); + -+ while(len--){ -+ *buf = bcmswap16(*buf); -+ buf++; -+ } ++ return (bcm_strtoul(val, NULL, 0)); +} + -+#ifndef hton16 -+#ifndef IL_BIGENDIAN -+#define HTON16(i) BCMSWAP16(i) -+#define hton16(i) bcmswap16(i) -+#define hton32(i) bcmswap32(i) -+#define ntoh16(i) bcmswap16(i) -+#define ntoh32(i) bcmswap32(i) -+#define ltoh16(i) (i) -+#define ltoh32(i) (i) -+#define htol16(i) (i) -+#define htol32(i) (i) -+#else -+#define HTON16(i) (i) -+#define hton16(i) (i) -+#define hton32(i) (i) -+#define ntoh16(i) (i) -+#define ntoh32(i) (i) -+#define ltoh16(i) bcmswap16(i) -+#define ltoh32(i) bcmswap32(i) -+#define htol16(i) bcmswap16(i) -+#define htol32(i) bcmswap32(i) -+#endif -+#endif + -+#ifndef IL_BIGENDIAN -+#define ltoh16_buf(buf, i) -+#define htol16_buf(buf, i) -+#else -+#define ltoh16_buf(buf, i) bcmswap16_buf((uint16*)buf, i) -+#define htol16_buf(buf, i) bcmswap16_buf((uint16*)buf, i) -+#endif ++/******************************************************************************* ++ * crc8 ++ * ++ * Computes a crc8 over the input data using the polynomial: ++ * ++ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 ++ * ++ * The caller provides the initial value (either CRC8_INIT_VALUE ++ * or the previous returned value) to allow for processing of ++ * discontiguous blocks of data. When generating the CRC the ++ * caller is responsible for complementing the final return value ++ * and inserting it into the byte stream. When checking, a final ++ * return value of CRC8_GOOD_VALUE indicates a valid CRC. ++ * ++ * Reference: Dallas Semiconductor Application Note 27 ++ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", ++ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., ++ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt ++ * ++ * **************************************************************************** ++ */ + -+/* -+* load 16-bit value from unaligned little endian byte array. -+*/ -+static INLINE uint16 -+ltoh16_ua(uint8 *bytes) -+{ -+ return (bytes[1]<<8)+bytes[0]; -+} ++static uint8 crc8_table[256] = { ++ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, ++ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, ++ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, ++ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, ++ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, ++ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, ++ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, ++ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, ++ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, ++ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, ++ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, ++ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, ++ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, ++ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, ++ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, ++ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, ++ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, ++ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, ++ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, ++ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, ++ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, ++ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, ++ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, ++ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, ++ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, ++ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, ++ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, ++ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, ++ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, ++ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, ++ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, ++ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F ++}; + -+/* -+* load 32-bit value from unaligned little endian byte array. -+*/ -+static INLINE uint32 -+ltoh32_ua(uint8 *bytes) -+{ -+ return (bytes[3]<<24)+(bytes[2]<<16)+(bytes[1]<<8)+bytes[0]; -+} ++#define CRC_INNER_LOOP(n, c, x) \ ++ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] + -+/* -+* load 16-bit value from unaligned big(network) endian byte array. -+*/ -+static INLINE uint16 -+ntoh16_ua(uint8 *bytes) ++uint8 ++hndcrc8( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint8 crc /* either CRC8_INIT_VALUE or previous return value */ ++) +{ -+ return (bytes[0]<<8)+bytes[1]; -+} ++ /* hard code the crc loop instead of using CRC_INNER_LOOP macro ++ * to avoid the undefined and unnecessary (uint8 >> 8) operation. ++ */ ++ while (nbytes-- > 0) ++ crc = crc8_table[(crc ^ *pdata++) & 0xff]; + -+/* -+* load 32-bit value from unaligned big(network) endian byte array. -+*/ -+static INLINE uint32 -+ntoh32_ua(uint8 *bytes) -+{ -+ return (bytes[0]<<24)+(bytes[1]<<16)+(bytes[2]<<8)+bytes[3]; ++ return crc; +} + -+#define ltoh_ua(ptr) ( \ -+ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \ -+ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] : \ -+ (((uint8 *)ptr)[3]<<24)+(((uint8 *)ptr)[2]<<16)+(((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] \ -+) -+ -+#define ntoh_ua(ptr) ( \ -+ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \ -+ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[0]<<8)+((uint8 *)ptr)[1] : \ -+ (((uint8 *)ptr)[0]<<24)+(((uint8 *)ptr)[1]<<16)+(((uint8 *)ptr)[2]<<8)+((uint8 *)ptr)[3] \ -+) + -+#endif /* _BCMENDIAN_H_ */ -diff -Naur linux.old/arch/mips/bcm947xx/include/bcmnvram.h linux.dev/arch/mips/bcm947xx/include/bcmnvram.h ---- linux.old/arch/mips/bcm947xx/include/bcmnvram.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/bcmnvram.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,141 @@ +diff -urN linux.old/arch/mips/bcm947xx/cfe_env.c linux.dev/arch/mips/bcm947xx/cfe_env.c +--- linux.old/arch/mips/bcm947xx/cfe_env.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/cfe_env.c 2006-04-27 19:24:19.000000000 +0200 +@@ -0,0 +1,234 @@ +/* -+ * NVRAM variable manipulation ++ * NVRAM variable manipulation (Linux kernel half) + * -+ * Copyright 2005, Broadcom Corporation ++ * Copyright 2001-2003, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -1262,477 +1535,543 @@ diff -Naur linux.old/arch/mips/bcm947xx/include/bcmnvram.h linux.dev/arch/mips/b + * $Id$ + */ + -+#ifndef _bcmnvram_h_ -+#define _bcmnvram_h_ -+ -+#ifndef _LANGUAGE_ASSEMBLY ++#include ++#include ++#include ++#include ++#include ++#include ++#include + +#include ++#include ++#include ++#include + -+struct nvram_header { -+ uint32 magic; -+ uint32 len; -+ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ -+ uint32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ -+ uint32 config_ncdl; /* ncdl values for memc */ -+}; -+ -+struct nvram_tuple { -+ char *name; -+ char *value; -+ struct nvram_tuple *next; -+}; -+ -+/* -+ * Initialize NVRAM access. May be unnecessary or undefined on certain -+ * platforms. -+ */ -+extern int BCMINIT(nvram_init)(void *sbh); ++#define NVRAM_SIZE (0x1ff0) ++static char _nvdata[NVRAM_SIZE] __initdata; ++static char _valuestr[256] __initdata; + +/* -+ * Disable NVRAM access. May be unnecessary or undefined on certain -+ * platforms. -+ */ -+extern void BCMINIT(nvram_exit)(void *sbh); -+ -+/* -+ * Get the value of an NVRAM variable. The pointer returned may be -+ * invalid after a set. -+ * @param name name of variable to get -+ * @return value of variable or NULL if undefined ++ * TLV types. These codes are used in the "type-length-value" ++ * encoding of the items stored in the NVRAM device (flash or EEPROM) ++ * ++ * The layout of the flash/nvram is as follows: ++ * ++ * ++ * ++ * The type code of "ENV_TLV_TYPE_END" marks the end of the list. ++ * The "length" field marks the length of the data section, not ++ * including the type and length fields. ++ * ++ * Environment variables are stored as follows: ++ * ++ * = ++ * ++ * If bit 0 (low bit) is set, the length is an 8-bit value. ++ * If bit 0 (low bit) is clear, the length is a 16-bit value ++ * ++ * Bit 7 set indicates "user" TLVs. In this case, bit 0 still ++ * indicates the size of the length field. ++ * ++ * Flags are from the constants below: ++ * + */ -+extern char * BCMINIT(nvram_get)(const char *name); ++#define ENV_LENGTH_16BITS 0x00 /* for low bit */ ++#define ENV_LENGTH_8BITS 0x01 + -+/* -+ * Read the reset GPIO value from the nvram and set the GPIO -+ * as input -+ */ -+extern int BCMINITFN(nvram_resetgpio_init)(void *sbh); ++#define ENV_TYPE_USER 0x80 + -+/* -+ * Get the value of an NVRAM variable. -+ * @param name name of variable to get -+ * @return value of variable or NUL if undefined -+ */ -+#define nvram_safe_get(name) (BCMINIT(nvram_get)(name) ? : "") ++#define ENV_CODE_SYS(n,l) (((n)<<1)|(l)) ++#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER) + +/* -+ * Match an NVRAM variable. -+ * @param name name of variable to match -+ * @param match value to compare against value of variable -+ * @return TRUE if variable is defined and its value is string equal -+ * to match or FALSE otherwise ++ * The actual TLV types we support + */ -+static INLINE int -+nvram_match(char *name, char *match) { -+ const char *value = BCMINIT(nvram_get)(name); -+ return (value && !strcmp(value, match)); -+} + -+/* -+ * Inversely match an NVRAM variable. -+ * @param name name of variable to match -+ * @param match value to compare against value of variable -+ * @return TRUE if variable is defined and its value is not string -+ * equal to invmatch or FALSE otherwise -+ */ -+static INLINE int -+nvram_invmatch(char *name, char *invmatch) { -+ const char *value = BCMINIT(nvram_get)(name); -+ return (value && strcmp(value, invmatch)); -+} ++#define ENV_TLV_TYPE_END 0x00 ++#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS) + +/* -+ * Set the value of an NVRAM variable. The name and value strings are -+ * copied into private storage. Pointers to previously set values -+ * may become invalid. The new value may be immediately -+ * retrieved but will not be permanently stored until a commit. -+ * @param name name of variable to set -+ * @param value value of variable -+ * @return 0 on success and errno on failure ++ * Environment variable flags + */ -+extern int BCMINIT(nvram_set)(const char *name, const char *value); + -+/* -+ * Unset an NVRAM variable. Pointers to previously set values -+ * remain valid until a set. -+ * @param name name of variable to unset -+ * @return 0 on success and errno on failure -+ * NOTE: use nvram_commit to commit this change to flash. -+ */ -+extern int BCMINIT(nvram_unset)(const char *name); ++#define ENV_FLG_NORMAL 0x00 /* normal read/write */ ++#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */ ++#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */ + -+/* -+ * Commit NVRAM variables to permanent storage. All pointers to values -+ * may be invalid after a commit. -+ * NVRAM values are undefined after a commit. -+ * @return 0 on success and errno on failure -+ */ -+extern int BCMINIT(nvram_commit)(void); ++#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */ ++#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */ + -+/* -+ * Get all NVRAM variables (format name=value\0 ... \0\0). -+ * @param buf buffer to store variables -+ * @param count size of buffer in bytes -+ * @return 0 on success and errno on failure -+ */ -+extern int BCMINIT(nvram_getall)(char *buf, int count); + -+#endif /* _LANGUAGE_ASSEMBLY */ ++/* ********************************************************************* ++ * _nvram_read(buffer,offset,length) ++ * ++ * Read data from the NVRAM device ++ * ++ * Input parameters: ++ * buffer - destination buffer ++ * offset - offset of data to read ++ * length - number of bytes to read ++ * ++ * Return value: ++ * number of bytes read, or <0 if error occured ++ ********************************************************************* */ ++static int ++_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length) ++{ ++ int i; ++ if (offset > NVRAM_SIZE) ++ return -1; + -+#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ -+#define NVRAM_VERSION 1 -+#define NVRAM_HEADER_SIZE 20 -+#define NVRAM_SPACE 0x8000 ++ for ( i = 0; i < length; i++) { ++ buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i]; ++ } ++ return length; ++} + -+#define NVRAM_MAX_VALUE_LEN 255 -+#define NVRAM_MAX_PARAM_LEN 64 + -+#endif /* _bcmnvram_h_ */ -diff -Naur linux.old/arch/mips/bcm947xx/include/bcmsrom.h linux.dev/arch/mips/bcm947xx/include/bcmsrom.h ---- linux.old/arch/mips/bcm947xx/include/bcmsrom.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/bcmsrom.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,23 @@ -+/* -+ * Misc useful routines to access NIC local SROM/OTP . -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ -+ */ ++static char* ++_strnchr(const char *dest,int c,size_t cnt) ++{ ++ while (*dest && (cnt > 0)) { ++ if (*dest == c) return (char *) dest; ++ dest++; ++ cnt--; ++ } ++ return NULL; ++} + -+#ifndef _bcmsrom_h_ -+#define _bcmsrom_h_ + -+extern int srom_var_init(void *sbh, uint bus, void *curmap, osl_t *osh, char **vars, int *count); + -+extern int srom_read(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf); -+extern int srom_write(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf); ++/* ++ * Core support API: Externally visible. ++ */ + -+#endif /* _bcmsrom_h_ */ -diff -Naur linux.old/arch/mips/bcm947xx/include/bcmutils.h linux.dev/arch/mips/bcm947xx/include/bcmutils.h ---- linux.old/arch/mips/bcm947xx/include/bcmutils.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/bcmutils.h 2006-04-06 17:07:30.000000000 +0200 -@@ -0,0 +1,287 @@ +/* -+ * Misc useful os-independent macros and functions. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ ++ * Get the value of an NVRAM variable ++ * @param name name of variable to get ++ * @return value of variable or NULL if undefined + */ + -+#ifndef _bcmutils_h_ -+#define _bcmutils_h_ ++char* ++cfe_env_get(unsigned char *nv_buf, char* name) ++{ ++ int size; ++ unsigned char *buffer; ++ unsigned char *ptr; ++ unsigned char *envval; ++ unsigned int reclen; ++ unsigned int rectype; ++ int offset; ++ int flg; ++ ++ size = NVRAM_SIZE; ++ buffer = &_nvdata[0]; + -+/*** driver-only section ***/ -+#ifdef BCMDRIVER -+#include ++ ptr = buffer; ++ offset = 0; + -+#define _BCM_U 0x01 /* upper */ -+#define _BCM_L 0x02 /* lower */ -+#define _BCM_D 0x04 /* digit */ -+#define _BCM_C 0x08 /* cntrl */ -+#define _BCM_P 0x10 /* punct */ -+#define _BCM_S 0x20 /* white space (space/lf/tab) */ -+#define _BCM_X 0x40 /* hex digit */ -+#define _BCM_SP 0x80 /* hard space (0x20) */ ++ /* Read the record type and length */ ++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) { ++ goto error; ++ } ++ ++ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) { + -+#define GPIO_PIN_NOTDEFINED 0x20 ++ /* Adjust pointer for TLV type */ ++ rectype = *(ptr); ++ offset++; ++ size--; + -+extern unsigned char bcm_ctype[]; -+#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) ++ /* ++ * Read the length. It can be either 1 or 2 bytes ++ * depending on the code ++ */ ++ if (rectype & ENV_LENGTH_8BITS) { ++ /* Read the record type and length - 8 bits */ ++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) { ++ goto error; ++ } ++ reclen = *(ptr); ++ size--; ++ offset++; ++ } ++ else { ++ /* Read the record type and length - 16 bits, MSB first */ ++ if (_nvram_read(nv_buf, ptr,offset,2) != 2) { ++ goto error; ++ } ++ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1); ++ size -= 2; ++ offset += 2; ++ } + -+#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) -+#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) -+#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) -+#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) -+#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) -+#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) -+#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) -+#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) -+#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) -+#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) -+#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) -+ -+/* -+ * Spin at most 'us' microseconds while 'exp' is true. -+ * Caller should explicitly test 'exp' when this completes -+ * and take appropriate error action if 'exp' is still true. -+ */ -+#define SPINWAIT(exp, us) { \ -+ uint countdown = (us) + 9; \ -+ while ((exp) && (countdown >= 10)) {\ -+ OSL_DELAY(10); \ -+ countdown -= 10; \ -+ } \ -+} -+ -+/* string */ -+extern uint bcm_atoi(char *s); -+extern uchar bcm_toupper(uchar c); -+extern ulong bcm_strtoul(char *cp, char **endp, uint base); -+extern char *bcmstrstr(char *haystack, char *needle); -+extern char *bcmstrcat(char *dest, const char *src); -+extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); -+/* ethernet address */ -+extern char *bcm_ether_ntoa(char *ea, char *buf); -+extern int bcm_ether_atoe(char *p, char *ea); -+/* delay */ -+extern void bcm_mdelay(uint ms); -+/* variable access */ -+extern char *getvar(char *vars, char *name); -+extern int getintvar(char *vars, char *name); -+extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); -+#define bcmlog(fmt, a1, a2) -+#define bcmdumplog(buf, size) *buf = '\0' -+#define bcmdumplogent(buf, idx) -1 ++ if (reclen > size) ++ break; /* should not happen, bad NVRAM */ + -+#endif /* #ifdef BCMDRIVER */ ++ switch (rectype) { ++ case ENV_TLV_TYPE_ENV: ++ /* Read the TLV data */ ++ if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen) ++ goto error; ++ flg = *ptr++; ++ envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1)); ++ if (envval) { ++ *envval++ = '\0'; ++ memcpy(_valuestr,envval,(reclen-1)-(envval-ptr)); ++ _valuestr[(reclen-1)-(envval-ptr)] = '\0'; ++#if 0 ++ printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr); ++#endif ++ if(!strcmp(ptr, name)){ ++ return _valuestr; ++ } ++ if((strlen(ptr) > 1) && !strcmp(&ptr[1], name)) ++ return _valuestr; ++ } ++ break; ++ ++ default: ++ /* Unknown TLV type, skip it. */ ++ break; ++ } + -+/*** driver/apps-shared section ***/ ++ /* ++ * Advance to next TLV ++ */ ++ ++ size -= (int)reclen; ++ offset += reclen; + -+#define BCME_STRLEN 64 -+#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) ++ /* Read the next record type */ ++ ptr = buffer; ++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) ++ goto error; ++ } + ++error: ++ return NULL; + -+/* -+ * error codes could be added but the defined ones shouldn't be changed/deleted -+ * these error codes are exposed to the user code -+ * when ever a new error code is added to this list -+ * please update errorstring table with the related error string and -+ * update osl files with os specific errorcode map -+*/ ++} + -+#define BCME_ERROR -1 /* Error generic */ -+#define BCME_BADARG -2 /* Bad Argument */ -+#define BCME_BADOPTION -3 /* Bad option */ -+#define BCME_NOTUP -4 /* Not up */ -+#define BCME_NOTDOWN -5 /* Not down */ -+#define BCME_NOTAP -6 /* Not AP */ -+#define BCME_NOTSTA -7 /* Not STA */ -+#define BCME_BADKEYIDX -8 /* BAD Key Index */ -+#define BCME_RADIOOFF -9 /* Radio Off */ -+#define BCME_NOTBANDLOCKED -10 /* Not bandlocked */ -+#define BCME_NOCLK -11 /* No Clock*/ -+#define BCME_BADRATESET -12 /* BAD RateSet*/ -+#define BCME_BADBAND -13 /* BAD Band */ -+#define BCME_BUFTOOSHORT -14 /* Buffer too short */ -+#define BCME_BUFTOOLONG -15 /* Buffer too Long */ -+#define BCME_BUSY -16 /* Busy*/ -+#define BCME_NOTASSOCIATED -17 /* Not associated*/ -+#define BCME_BADSSIDLEN -18 /* BAD SSID Len */ -+#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel*/ -+#define BCME_BADCHAN -20 /* BAD Channel */ -+#define BCME_BADADDR -21 /* BAD Address*/ -+#define BCME_NORESOURCE -22 /* No resources*/ -+#define BCME_UNSUPPORTED -23 /* Unsupported*/ -+#define BCME_BADLEN -24 /* Bad Length*/ -+#define BCME_NOTREADY -25 /* Not ready Yet*/ -+#define BCME_EPERM -26 /* Not Permitted */ -+#define BCME_NOMEM -27 /* No Memory */ -+#define BCME_ASSOCIATED -28 /* Associated */ -+#define BCME_RANGE -29 /* Range Error*/ -+#define BCME_NOTFOUND -30 /* Not found */ -+#define BCME_LAST BCME_NOTFOUND +diff -urN linux.old/arch/mips/bcm947xx/compressed/Makefile linux.dev/arch/mips/bcm947xx/compressed/Makefile +--- linux.old/arch/mips/bcm947xx/compressed/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/compressed/Makefile 2006-04-27 19:24:19.000000000 +0200 +@@ -0,0 +1,33 @@ ++# ++# Makefile for Broadcom BCM947XX boards ++# ++# Copyright 2001-2003, Broadcom Corporation ++# All Rights Reserved. ++# ++# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++# ++# $Id: Makefile,v 1.2 2005/04/02 12:12:57 wbx Exp $ ++# + -+#ifndef ABS -+#define ABS(a) (((a)<0)?-(a):(a)) -+#endif ++OBJCOPY_ARGS = -O binary -R .reginfo -R .note -R .comment -R .mdebug -S ++SYSTEM ?= $(TOPDIR)/vmlinux + -+#ifndef MIN -+#define MIN(a, b) (((a)<(b))?(a):(b)) -+#endif ++all: vmlinuz + -+#ifndef MAX -+#define MAX(a, b) (((a)>(b))?(a):(b)) -+#endif ++# Don't build dependencies, this may die if $(CC) isn't gcc ++dep: + -+#define CEIL(x, y) (((x) + ((y)-1)) / (y)) -+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) -+#define ISALIGNED(a, x) (((a) & ((x)-1)) == 0) -+#define ISPOWEROF2(x) ((((x)-1)&(x))==0) -+#define VALID_MASK(mask) !((mask) & ((mask) + 1)) -+#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) -+#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) ++# Create a gzipped version named vmlinuz for compatibility ++vmlinuz: piggy ++ gzip -c9 $< > $@ + -+/* bit map related macros */ -+#ifndef setbit -+#define NBBY 8 /* 8 bits per byte */ -+#define setbit(a,i) (((uint8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY)) -+#define clrbit(a,i) (((uint8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) -+#define isset(a,i) (((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) -+#define isclr(a,i) ((((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -+#endif ++piggy: $(SYSTEM) ++ $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ + -+#define NBITS(type) (sizeof(type) * 8) -+#define NBITVAL(bits) (1 << (bits)) -+#define MAXBITVAL(bits) ((1 << (bits)) - 1) ++mrproper: clean + -+/* crc defines */ -+#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ -+#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ -+#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ -+#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ -+#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ -+#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ ++clean: ++ rm -f vmlinuz piggy +diff -urN linux.old/arch/mips/bcm947xx/export.c linux.dev/arch/mips/bcm947xx/export.c +--- linux.old/arch/mips/bcm947xx/export.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/export.c 2006-04-28 02:57:34.000000000 +0200 +@@ -0,0 +1,62 @@ ++#include + -+/* bcm_format_flags() bit description structure */ -+typedef struct bcm_bit_desc { -+ uint32 bit; -+ char* name; -+} bcm_bit_desc_t; ++#define _export(n) \ ++ void n(void); \ ++ EXPORT_SYMBOL(n); ++ ++_export(bcm947xx_sbh) ++ ++_export(sb_attach) ++_export(sb_boardtype) ++_export(sb_boardvendor) ++_export(sb_btcgpiowar) ++_export(sb_bus) ++_export(sb_chip) ++_export(sb_chiprev) ++_export(sb_chipcrev) ++_export(sb_chippkg) ++_export(sb_clkctl_clk) ++_export(sb_clkctl_fast_pwrup_delay) ++_export(sb_clkctl_init) ++_export(sb_clkctl_xtal) ++_export(sb_core_disable) ++_export(sb_core_reset) ++_export(sb_core_tofixup) ++_export(sb_coreflags) ++_export(sb_coreflagshi) ++_export(sb_coreidx) ++_export(sb_corerev) ++_export(sb_coreunit) ++_export(sb_detach) ++_export(sb_deviceremoved) ++_export(sb_gpiocontrol) ++_export(sb_gpioled) ++_export(sb_gpioin) ++_export(sb_gpioout) ++_export(sb_gpioouten) ++_export(sb_gpiotimerval) ++_export(sb_iscoreup) ++_export(sb_pci_setup) ++_export(sb_pcirev) ++_export(sb_pcmcia_init) ++_export(sb_pcmciarev) ++_export(sb_register_intr_callback) ++_export(sb_setcore) ++_export(sb_war16165) ++_export(sb_osh) ++ ++_export(getvar) ++_export(getintvar) ++_export(bcm_strtoul) ++_export(bcm_ctype) ++_export(bcm_toupper) ++_export(bcm_ether_ntoa) ++ ++_export(nvram_get) ++_export(nvram_getall) ++_export(nvram_set) ++_export(nvram_unset) ++_export(nvram_commit) ++ ++_export(srom_read) ++_export(srom_write) +diff -urN linux.old/arch/mips/bcm947xx/generic/Makefile linux.dev/arch/mips/bcm947xx/generic/Makefile +--- linux.old/arch/mips/bcm947xx/generic/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/generic/Makefile 2006-04-27 19:24:19.000000000 +0200 +@@ -0,0 +1,15 @@ ++# ++# Makefile for the BCM947xx specific kernel interface routines ++# under Linux. ++# + -+/* tag_ID/length/value_buffer tuple */ -+typedef struct bcm_tlv { -+ uint8 id; -+ uint8 len; -+ uint8 data[1]; -+} bcm_tlv_t; ++.S.s: ++ $(CPP) $(AFLAGS) $< -o $*.s ++.S.o: ++ $(CC) $(AFLAGS) -c $< -o $*.o + -+/* Check that bcm_tlv_t fits into the given buflen */ -+#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) ++O_TARGET := brcm.o + -+/* buffer length for ethernet address from bcm_ether_ntoa() */ -+#define ETHER_ADDR_STR_LEN 18 ++obj-y := int-handler.o irq.o + -+/* unaligned load and store macros */ -+#ifdef IL_BIGENDIAN -+static INLINE uint32 -+load32_ua(uint8 *a) -+{ -+ return ((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]); -+} ++include $(TOPDIR)/Rules.make +diff -urN linux.old/arch/mips/bcm947xx/generic/int-handler.S linux.dev/arch/mips/bcm947xx/generic/int-handler.S +--- linux.old/arch/mips/bcm947xx/generic/int-handler.S 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/generic/int-handler.S 2006-04-27 19:24:19.000000000 +0200 +@@ -0,0 +1,51 @@ ++/* ++ * Generic interrupt handler for Broadcom MIPS boards ++ * ++ * Copyright 2004, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: int-handler.S,v 1.1 2005/03/16 13:50:00 wbx Exp $ ++ */ + -+static INLINE void -+store32_ua(uint8 *a, uint32 v) -+{ -+ a[0] = (v >> 24) & 0xff; -+ a[1] = (v >> 16) & 0xff; -+ a[2] = (v >> 8) & 0xff; -+ a[3] = v & 0xff; -+} ++#include + -+static INLINE uint16 -+load16_ua(uint8 *a) -+{ -+ return ((a[0] << 8) | a[1]); -+} ++#include ++#include ++#include ++#include + -+static INLINE void -+store16_ua(uint8 *a, uint16 v) -+{ -+ a[0] = (v >> 8) & 0xff; -+ a[1] = v & 0xff; -+} ++/* ++ * MIPS IRQ Source ++ * -------- ------ ++ * 0 Software (ignored) ++ * 1 Software (ignored) ++ * 2 Combined hardware interrupt (hw0) ++ * 3 Hardware ++ * 4 Hardware ++ * 5 Hardware ++ * 6 Hardware ++ * 7 R4k timer ++ */ + -+#else ++ .text ++ .set noreorder ++ .set noat ++ .align 5 ++ NESTED(brcmIRQ, PT_SIZE, sp) ++ SAVE_ALL ++ CLI ++ .set at ++ .set noreorder + -+static INLINE uint32 -+load32_ua(uint8 *a) -+{ -+ return ((a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]); -+} ++ jal brcm_irq_dispatch ++ move a0, sp + -+static INLINE void -+store32_ua(uint8 *a, uint32 v) -+{ -+ a[3] = (v >> 24) & 0xff; -+ a[2] = (v >> 16) & 0xff; -+ a[1] = (v >> 8) & 0xff; -+ a[0] = v & 0xff; -+} ++ j ret_from_irq ++ nop ++ ++ END(brcmIRQ) +diff -urN linux.old/arch/mips/bcm947xx/generic/irq.c linux.dev/arch/mips/bcm947xx/generic/irq.c +--- linux.old/arch/mips/bcm947xx/generic/irq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/generic/irq.c 2006-04-27 19:24:19.000000000 +0200 +@@ -0,0 +1,130 @@ ++/* ++ * Generic interrupt control functions for Broadcom MIPS boards ++ * ++ * Copyright 2004, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: irq.c,v 1.1 2005/03/16 13:50:00 wbx Exp $ ++ */ + -+static INLINE uint16 -+load16_ua(uint8 *a) ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) ++ ++extern asmlinkage void brcmIRQ(void); ++extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); ++ ++void ++brcm_irq_dispatch(struct pt_regs *regs) +{ -+ return ((a[1] << 8) | a[0]); ++ u32 cause; ++ ++ cause = read_c0_cause() & ++ read_c0_status() & ++ CAUSEF_IP; ++ ++#ifdef CONFIG_KERNPROF ++ change_c0_status(cause | 1, 1); ++#else ++ clear_c0_status(cause); ++#endif ++ ++ if (cause & CAUSEF_IP7) ++ do_IRQ(7, regs); ++ if (cause & CAUSEF_IP2) ++ do_IRQ(2, regs); ++ if (cause & CAUSEF_IP3) ++ do_IRQ(3, regs); ++ if (cause & CAUSEF_IP4) ++ do_IRQ(4, regs); ++ if (cause & CAUSEF_IP5) ++ do_IRQ(5, regs); ++ if (cause & CAUSEF_IP6) ++ do_IRQ(6, regs); +} + -+static INLINE void -+store16_ua(uint8 *a, uint16 v) ++static void ++enable_brcm_irq(unsigned int irq) +{ -+ a[1] = (v >> 8) & 0xff; -+ a[0] = v & 0xff; ++ if (irq < 8) ++ set_c0_status(1 << (irq + 8)); ++ else ++ set_c0_status(IE_IRQ0); +} + -+#endif ++static void ++disable_brcm_irq(unsigned int irq) ++{ ++ if (irq < 8) ++ clear_c0_status(1 << (irq + 8)); ++ else ++ clear_c0_status(IE_IRQ0); ++} + -+/* externs */ -+/* crc */ -+extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc); -+extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc); -+extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc); -+/* format/print */ -+/* IE parsing */ -+extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen); -+extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); -+extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key); ++static void ++ack_brcm_irq(unsigned int irq) ++{ ++ /* Already done in brcm_irq_dispatch */ ++} + -+/* bcmerror*/ -+extern const char *bcmerrorstr(int bcmerror); ++static unsigned int ++startup_brcm_irq(unsigned int irq) ++{ ++ enable_brcm_irq(irq); + -+/* multi-bool data type: set of bools, mbool is true if any is set */ -+typedef uint32 mbool; -+#define mboolset(mb, bit) (mb |= bit) /* set one bool */ -+#define mboolclr(mb, bit) (mb &= ~bit) /* clear one bool */ -+#define mboolisset(mb, bit) ((mb & bit) != 0) /* TRUE if one bool is set */ -+#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) ++ return 0; /* never anything pending */ ++} + -+/* power conversion */ -+extern uint16 bcm_qdbm_to_mw(uint8 qdbm); -+extern uint8 bcm_mw_to_qdbm(uint16 mw); ++static void ++end_brcm_irq(unsigned int irq) ++{ ++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) ++ enable_brcm_irq(irq); ++} + -+/* generic datastruct to help dump routines */ -+struct fielddesc { -+ char *nameandfmt; -+ uint32 offset; -+ uint32 len; ++static struct hw_interrupt_type brcm_irq_type = { ++ typename: "MIPS", ++ startup: startup_brcm_irq, ++ shutdown: disable_brcm_irq, ++ enable: enable_brcm_irq, ++ disable: disable_brcm_irq, ++ ack: ack_brcm_irq, ++ end: end_brcm_irq, ++ NULL +}; + -+typedef uint32 (*readreg_rtn)(void *arg0, void *arg1, uint32 offset); -+extern uint bcmdumpfields(readreg_rtn func_ptr, void *arg0, void *arg1, struct fielddesc *str, char *buf, uint32 bufsize); ++void __init ++init_IRQ(void) ++{ ++ int i; + -+extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); ++ for (i = 0; i < NR_IRQS; i++) { ++ irq_desc[i].status = IRQ_DISABLED; ++ irq_desc[i].action = 0; ++ irq_desc[i].depth = 1; ++ irq_desc[i].handler = &brcm_irq_type; ++ } + -+#endif /* _bcmutils_h_ */ -diff -Naur linux.old/arch/mips/bcm947xx/include/hndmips.h linux.dev/arch/mips/bcm947xx/include/hndmips.h ---- linux.old/arch/mips/bcm947xx/include/hndmips.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/hndmips.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,16 @@ -+/* -+ * Alternate include file for HND sbmips.h since CFE also ships with -+ * a sbmips.h. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ -+ */ ++ set_except_vector(0, brcmIRQ); ++ change_c0_status(ST0_IM, ALLINTS); + -+#include "sbmips.h" -diff -Naur linux.old/arch/mips/bcm947xx/include/linux_osl.h linux.dev/arch/mips/bcm947xx/include/linux_osl.h ---- linux.old/arch/mips/bcm947xx/include/linux_osl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/linux_osl.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,371 @@ ++#ifdef CONFIG_REMOTE_DEBUG ++ printk("Breaking into debugger...\n"); ++ set_debug_traps(); ++ breakpoint(); ++#endif ++} +diff -urN linux.old/arch/mips/bcm947xx/gpio.c linux.dev/arch/mips/bcm947xx/gpio.c +--- linux.old/arch/mips/bcm947xx/gpio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/gpio.c 2006-04-27 23:09:33.000000000 +0200 +@@ -0,0 +1,159 @@ +/* -+ * Linux OS Independent Layer ++ * GPIO char driver + * + * Copyright 2005, Broadcom Corporation + * All Rights Reserved. @@ -1745,3037 +2084,2324 @@ diff -Naur linux.old/arch/mips/bcm947xx/include/linux_osl.h linux.dev/arch/mips/ + * $Id$ + */ + -+#ifndef _linux_osl_h_ -+#define _linux_osl_h_ ++#include ++#include ++#include ++#include ++#include + +#include ++#include ++#include ++#include ++#include + -+/* use current 2.4.x calling conventions */ -+#include -+ -+/* assert and panic */ -+#ifdef __GNUC__ -+#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -+#if GCC_VERSION > 30100 -+#define ASSERT(exp) do {} while (0) -+#else -+/* ASSERT could causes segmentation fault on GCC3.1, use empty instead*/ -+#define ASSERT(exp) -+#endif -+#endif -+ -+/* microsecond delay */ -+#define OSL_DELAY(usec) osl_delay(usec) -+extern void osl_delay(uint usec); -+ -+/* PCMCIA attribute space access macros */ -+#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) -+struct pcmcia_dev { -+ dev_link_t link; /* PCMCIA device pointer */ -+ dev_node_t node; /* PCMCIA node structure */ -+ void *base; /* Mapped attribute memory window */ -+ size_t size; /* Size of window */ -+ void *drv; /* Driver data */ ++static sb_t *gpio_sbh; ++static int gpio_major; ++static devfs_handle_t gpio_dir; ++static struct { ++ char *name; ++ devfs_handle_t handle; ++} gpio_file[] = { ++ { "in", NULL }, ++ { "out", NULL }, ++ { "outen", NULL }, ++ { "control", NULL } +}; -+#endif -+#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \ -+ osl_pcmcia_read_attr((osh), (offset), (buf), (size)) -+#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \ -+ osl_pcmcia_write_attr((osh), (offset), (buf), (size)) -+extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size); -+extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size); -+ -+/* PCI configuration space access macros */ -+#define OSL_PCI_READ_CONFIG(osh, offset, size) \ -+ osl_pci_read_config((osh), (offset), (size)) -+#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ -+ osl_pci_write_config((osh), (offset), (size), (val)) -+extern uint32 osl_pci_read_config(osl_t *osh, uint size, uint offset); -+extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val); + -+/* PCI device bus # and slot # */ -+#define OSL_PCI_BUS(osh) osl_pci_bus(osh) -+#define OSL_PCI_SLOT(osh) osl_pci_slot(osh) -+extern uint osl_pci_bus(osl_t *osh); -+extern uint osl_pci_slot(osl_t *osh); ++static int ++gpio_open(struct inode *inode, struct file * file) ++{ ++ if (MINOR(inode->i_rdev) > ARRAYSIZE(gpio_file)) ++ return -ENODEV; + -+/* OSL initialization */ -+extern osl_t *osl_attach(void *pdev); -+extern void osl_detach(osl_t *osh); ++ MOD_INC_USE_COUNT; ++ return 0; ++} + -+/* host/bus architecture-specific byte swap */ -+#define BUS_SWAP32(v) (v) ++static int ++gpio_release(struct inode *inode, struct file * file) ++{ ++ MOD_DEC_USE_COUNT; ++ return 0; ++} + -+/* general purpose memory allocation */ ++static ssize_t ++gpio_read(struct file *file, char *buf, size_t count, loff_t *ppos) ++{ ++ u32 val; + -+#if defined(BCMDBG_MEM) ++ switch (MINOR(file->f_dentry->d_inode->i_rdev)) { ++ case 0: ++ val = sb_gpioin(gpio_sbh); ++ break; ++ case 1: ++ val = sb_gpioout(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY); ++ break; ++ case 2: ++ val = sb_gpioouten(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY); ++ break; ++ case 3: ++ val = sb_gpiocontrol(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY); ++ break; ++ default: ++ return -ENODEV; ++ } + -+#define MALLOC(osh, size) osl_debug_malloc((osh), (size), __LINE__, __FILE__) -+#define MFREE(osh, addr, size) osl_debug_mfree((osh), (addr), (size), __LINE__, __FILE__) -+#define MALLOCED(osh) osl_malloced((osh)) -+#define MALLOC_DUMP(osh, buf, sz) osl_debug_memdump((osh), (buf), (sz)) -+extern void *osl_debug_malloc(osl_t *osh, uint size, int line, char* file); -+extern void osl_debug_mfree(osl_t *osh, void *addr, uint size, int line, char* file); -+extern char *osl_debug_memdump(osl_t *osh, char *buf, uint sz); ++ if (put_user(val, (u32 *) buf)) ++ return -EFAULT; + -+#else ++ return sizeof(val); ++} + -+#define MALLOC(osh, size) osl_malloc((osh), (size)) -+#define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size)) -+#define MALLOCED(osh) osl_malloced((osh)) ++static ssize_t ++gpio_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ++{ ++ u32 val; + -+#endif /* BCMDBG_MEM */ -+ -+#define MALLOC_FAILED(osh) osl_malloc_failed((osh)) -+ -+extern void *osl_malloc(osl_t *osh, uint size); -+extern void osl_mfree(osl_t *osh, void *addr, uint size); -+extern uint osl_malloced(osl_t *osh); -+extern uint osl_malloc_failed(osl_t *osh); -+ -+/* allocate/free shared (dma-able) consistent memory */ -+#define DMA_CONSISTENT_ALIGN PAGE_SIZE -+#define DMA_ALLOC_CONSISTENT(osh, size, pap) \ -+ osl_dma_alloc_consistent((osh), (size), (pap)) -+#define DMA_FREE_CONSISTENT(osh, va, size, pa) \ -+ osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) -+extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap); -+extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); -+ -+/* map/unmap direction */ -+#define DMA_TX 1 -+#define DMA_RX 2 -+ -+/* map/unmap shared (dma-able) memory */ -+#define DMA_MAP(osh, va, size, direction, p) \ -+ osl_dma_map((osh), (va), (size), (direction)) -+#define DMA_UNMAP(osh, pa, size, direction, p) \ -+ osl_dma_unmap((osh), (pa), (size), (direction)) -+extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction); -+extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); -+ -+/* register access macros */ -+#if defined(BCMJTAG) -+#include -+#define R_REG(r) bcmjtag_read(NULL, (uint32)(r), sizeof (*(r))) -+#define W_REG(r, v) bcmjtag_write(NULL, (uint32)(r), (uint32)(v), sizeof (*(r))) -+#endif -+ -+/* -+ * BINOSL selects the slightly slower function-call-based binary compatible osl. -+ * Macros expand to calls to functions defined in linux_osl.c . -+ */ -+#ifndef BINOSL -+ -+/* string library, kernel mode */ -+#define printf(fmt, args...) printk(fmt, ## args) -+#include -+#include -+ -+/* register access macros */ -+#if !defined(BCMJTAG) -+#ifndef IL_BIGENDIAN -+#define R_REG(r) ( \ -+ sizeof(*(r)) == sizeof(uint8) ? readb((volatile uint8*)(r)) : \ -+ sizeof(*(r)) == sizeof(uint16) ? readw((volatile uint16*)(r)) : \ -+ readl((volatile uint32*)(r)) \ -+) -+#define W_REG(r, v) do { \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \ -+ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \ -+ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ -+ } \ -+} while (0) -+#else /* IL_BIGENDIAN */ -+#define R_REG(r) ({ \ -+ __typeof(*(r)) __osl_v; \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): __osl_v = readb((volatile uint8*)((uint32)r^3)); break; \ -+ case sizeof(uint16): __osl_v = readw((volatile uint16*)((uint32)r^2)); break; \ -+ case sizeof(uint32): __osl_v = readl((volatile uint32*)(r)); break; \ -+ } \ -+ __osl_v; \ -+}) -+#define W_REG(r, v) do { \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)((uint32)r^3)); break; \ -+ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)((uint32)r^2)); break; \ -+ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ -+ } \ -+} while (0) -+#endif -+#endif -+ -+#define AND_REG(r, v) W_REG((r), R_REG(r) & (v)) -+#define OR_REG(r, v) W_REG((r), R_REG(r) | (v)) -+ -+/* bcopy, bcmp, and bzero */ -+#define bcopy(src, dst, len) memcpy((dst), (src), (len)) -+#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) -+#define bzero(b, len) memset((b), '\0', (len)) -+ -+/* uncached virtual address */ -+#ifdef mips -+#define OSL_UNCACHED(va) KSEG1ADDR((va)) -+#include -+#else -+#define OSL_UNCACHED(va) (va) -+#endif -+ -+/* get processor cycle count */ -+#if defined(mips) -+#define OSL_GETCYCLES(x) ((x) = read_c0_count() * 2) -+#elif defined(__i386__) -+#define OSL_GETCYCLES(x) rdtscl((x)) -+#else -+#define OSL_GETCYCLES(x) ((x) = 0) -+#endif -+ -+/* dereference an address that may cause a bus exception */ -+#ifdef mips -+#if defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17)) -+#define BUSPROBE(val, addr) panic("get_dbe() will not fixup a bus exception when compiled into a module") -+#else -+#define BUSPROBE(val, addr) get_dbe((val), (addr)) -+#include -+#endif -+#else -+#define BUSPROBE(val, addr) ({ (val) = R_REG((addr)); 0; }) -+#endif -+ -+/* map/unmap physical to virtual I/O */ -+#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) -+#define REG_UNMAP(va) iounmap((void *)(va)) -+ -+/* shared (dma-able) memory access macros */ -+#define R_SM(r) *(r) -+#define W_SM(r, v) (*(r) = (v)) -+#define BZERO_SM(r, len) memset((r), '\0', (len)) -+ -+/* packet primitives */ -+#define PKTGET(osh, len, send) osl_pktget((osh), (len), (send)) -+#define PKTFREE(osh, skb, send) osl_pktfree((skb)) -+#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) -+#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) -+#define PKTHEADROOM(osh, skb) (PKTDATA(osh,skb)-(((struct sk_buff*)(skb))->head)) -+#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) -+#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) -+#define PKTSETNEXT(skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) -+#define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len)) -+#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) -+#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) -+#define PKTDUP(osh, skb) skb_clone((struct sk_buff*)(skb), GFP_ATOMIC) -+#define PKTCOOKIE(skb) ((void*)((struct sk_buff*)(skb))->csum) -+#define PKTSETCOOKIE(skb, x) (((struct sk_buff*)(skb))->csum = (uint)(x)) -+#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) -+#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) -+#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) -+#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) -+extern void *osl_pktget(osl_t *osh, uint len, bool send); -+extern void osl_pktfree(void *skb); -+ -+#else /* BINOSL */ -+ -+/* string library */ -+#ifndef LINUX_OSL -+#undef printf -+#define printf(fmt, args...) osl_printf((fmt), ## args) -+#undef sprintf -+#define sprintf(buf, fmt, args...) osl_sprintf((buf), (fmt), ## args) -+#undef strcmp -+#define strcmp(s1, s2) osl_strcmp((s1), (s2)) -+#undef strncmp -+#define strncmp(s1, s2, n) osl_strncmp((s1), (s2), (n)) -+#undef strlen -+#define strlen(s) osl_strlen((s)) -+#undef strcpy -+#define strcpy(d, s) osl_strcpy((d), (s)) -+#undef strncpy -+#define strncpy(d, s, n) osl_strncpy((d), (s), (n)) -+#endif -+extern int osl_printf(const char *format, ...); -+extern int osl_sprintf(char *buf, const char *format, ...); -+extern int osl_strcmp(const char *s1, const char *s2); -+extern int osl_strncmp(const char *s1, const char *s2, uint n); -+extern int osl_strlen(const char *s); -+extern char* osl_strcpy(char *d, const char *s); -+extern char* osl_strncpy(char *d, const char *s, uint n); ++ if (get_user(val, (u32 *) buf)) ++ return -EFAULT; + -+/* register access macros */ -+#if !defined(BCMJTAG) -+#define R_REG(r) ( \ -+ sizeof(*(r)) == sizeof(uint8) ? osl_readb((volatile uint8*)(r)) : \ -+ sizeof(*(r)) == sizeof(uint16) ? osl_readw((volatile uint16*)(r)) : \ -+ osl_readl((volatile uint32*)(r)) \ -+) -+#define W_REG(r, v) do { \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(uint8): osl_writeb((uint8)(v), (volatile uint8*)(r)); break; \ -+ case sizeof(uint16): osl_writew((uint16)(v), (volatile uint16*)(r)); break; \ -+ case sizeof(uint32): osl_writel((uint32)(v), (volatile uint32*)(r)); break; \ -+ } \ -+} while (0) -+#endif ++ switch (MINOR(file->f_dentry->d_inode->i_rdev)) { ++ case 0: ++ return -EACCES; ++ case 1: ++ sb_gpioout(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY); ++ break; ++ case 2: ++ sb_gpioouten(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY); ++ break; ++ case 3: ++ sb_gpiocontrol(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY); ++ break; ++ default: ++ return -ENODEV; ++ } + -+#define AND_REG(r, v) W_REG((r), R_REG(r) & (v)) -+#define OR_REG(r, v) W_REG((r), R_REG(r) | (v)) -+extern uint8 osl_readb(volatile uint8 *r); -+extern uint16 osl_readw(volatile uint16 *r); -+extern uint32 osl_readl(volatile uint32 *r); -+extern void osl_writeb(uint8 v, volatile uint8 *r); -+extern void osl_writew(uint16 v, volatile uint16 *r); -+extern void osl_writel(uint32 v, volatile uint32 *r); ++ return sizeof(val); ++} + -+/* bcopy, bcmp, and bzero */ -+extern void bcopy(const void *src, void *dst, int len); -+extern int bcmp(const void *b1, const void *b2, int len); -+extern void bzero(void *b, int len); ++static struct file_operations gpio_fops = { ++ owner: THIS_MODULE, ++ open: gpio_open, ++ release: gpio_release, ++ read: gpio_read, ++ write: gpio_write, ++}; + -+/* uncached virtual address */ -+#define OSL_UNCACHED(va) osl_uncached((va)) -+extern void *osl_uncached(void *va); ++static int __init ++gpio_init(void) ++{ ++ int i; + -+/* get processor cycle count */ -+#define OSL_GETCYCLES(x) ((x) = osl_getcycles()) -+extern uint osl_getcycles(void); ++ if (!(gpio_sbh = sb_kattach())) ++ return -ENODEV; + -+/* dereference an address that may target abort */ -+#define BUSPROBE(val, addr) osl_busprobe(&(val), (addr)) -+extern int osl_busprobe(uint32 *val, uint32 addr); ++ sb_gpiosetcore(gpio_sbh); + -+/* map/unmap physical to virtual */ -+#define REG_MAP(pa, size) osl_reg_map((pa), (size)) -+#define REG_UNMAP(va) osl_reg_unmap((va)) -+extern void *osl_reg_map(uint32 pa, uint size); -+extern void osl_reg_unmap(void *va); ++ if ((gpio_major = devfs_register_chrdev(0, "gpio", &gpio_fops)) < 0) ++ return gpio_major; + -+/* shared (dma-able) memory access macros */ -+#define R_SM(r) *(r) -+#define W_SM(r, v) (*(r) = (v)) -+#define BZERO_SM(r, len) bzero((r), (len)) ++ gpio_dir = devfs_mk_dir(NULL, "gpio", NULL); + -+/* packet primitives */ -+#define PKTGET(osh, len, send) osl_pktget((osh), (len), (send)) -+#define PKTFREE(osh, skb, send) osl_pktfree((skb)) -+#define PKTDATA(osh, skb) osl_pktdata((osh), (skb)) -+#define PKTLEN(osh, skb) osl_pktlen((osh), (skb)) -+#define PKTHEADROOM(osh, skb) osl_pktheadroom((osh), (skb)) -+#define PKTTAILROOM(osh, skb) osl_pkttailroom((osh), (skb)) -+#define PKTNEXT(osh, skb) osl_pktnext((osh), (skb)) -+#define PKTSETNEXT(skb, x) osl_pktsetnext((skb), (x)) -+#define PKTSETLEN(osh, skb, len) osl_pktsetlen((osh), (skb), (len)) -+#define PKTPUSH(osh, skb, bytes) osl_pktpush((osh), (skb), (bytes)) -+#define PKTPULL(osh, skb, bytes) osl_pktpull((osh), (skb), (bytes)) -+#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) -+#define PKTCOOKIE(skb) osl_pktcookie((skb)) -+#define PKTSETCOOKIE(skb, x) osl_pktsetcookie((skb), (x)) -+#define PKTLINK(skb) osl_pktlink((skb)) -+#define PKTSETLINK(skb, x) osl_pktsetlink((skb), (x)) -+#define PKTPRIO(skb) osl_pktprio((skb)) -+#define PKTSETPRIO(skb, x) osl_pktsetprio((skb), (x)) -+extern void *osl_pktget(osl_t *osh, uint len, bool send); -+extern void osl_pktfree(void *skb); -+extern uchar *osl_pktdata(osl_t *osh, void *skb); -+extern uint osl_pktlen(osl_t *osh, void *skb); -+extern uint osl_pktheadroom(osl_t *osh, void *skb); -+extern uint osl_pkttailroom(osl_t *osh, void *skb); -+extern void *osl_pktnext(osl_t *osh, void *skb); -+extern void osl_pktsetnext(void *skb, void *x); -+extern void osl_pktsetlen(osl_t *osh, void *skb, uint len); -+extern uchar *osl_pktpush(osl_t *osh, void *skb, int bytes); -+extern uchar *osl_pktpull(osl_t *osh, void *skb, int bytes); -+extern void *osl_pktdup(osl_t *osh, void *skb); -+extern void *osl_pktcookie(void *skb); -+extern void osl_pktsetcookie(void *skb, void *x); -+extern void *osl_pktlink(void *skb); -+extern void osl_pktsetlink(void *skb, void *x); -+extern uint osl_pktprio(void *skb); -+extern void osl_pktsetprio(void *skb, uint x); ++ for (i = 0; i < ARRAYSIZE(gpio_file); i++) { ++ gpio_file[i].handle = devfs_register(gpio_dir, ++ gpio_file[i].name, ++ DEVFS_FL_DEFAULT, gpio_major, i, ++ S_IFCHR | S_IRUGO | S_IWUGO, ++ &gpio_fops, NULL); ++ } + -+#endif /* BINOSL */ ++ return 0; ++} + -+#define OSL_ERROR(bcmerror) osl_error(bcmerror) -+extern int osl_error(int bcmerror); ++static void __exit ++gpio_exit(void) ++{ ++ int i; + -+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ -+#define PKTBUFSZ 2048 ++ for (i = 0; i < ARRAYSIZE(gpio_file); i++) ++ devfs_unregister(gpio_file[i].handle); ++ devfs_unregister(gpio_dir); ++ devfs_unregister_chrdev(gpio_major, "gpio"); ++ sb_detach(gpio_sbh); ++} + -+#endif /* _linux_osl_h_ */ -diff -Naur linux.old/arch/mips/bcm947xx/include/linuxver.h linux.dev/arch/mips/bcm947xx/include/linuxver.h ---- linux.old/arch/mips/bcm947xx/include/linuxver.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/linuxver.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,411 @@ ++module_init(gpio_init); ++module_exit(gpio_exit); +diff -urN linux.old/arch/mips/bcm947xx/hndchipc.c linux.dev/arch/mips/bcm947xx/hndchipc.c +--- linux.old/arch/mips/bcm947xx/hndchipc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/hndchipc.c 2006-04-28 00:33:05.000000000 +0200 +@@ -0,0 +1,158 @@ +/* -+ * Linux-specific abstractions to gain some independence from linux kernel versions. -+ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. ++ * BCM47XX support code for some chipcommon (old extif) facilities (uart) + * -+ * Copyright 2005, Broadcom Corporation ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ ++ * ++ * $Id: hndchipc.c,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ + */ + -+#ifndef _linuxver_h_ -+#define _linuxver_h_ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+#include -+#include ++/* ++ * Returns TRUE if an external UART exists at the given base ++ * register. ++ */ ++static bool ++BCMINITFN(serial_exists)(osl_t *osh, uint8 *regs) ++{ ++ uint8 save_mcr, status1; + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)) -+/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */ -+#ifdef __UNDEF_NO_VERSION__ -+#undef __NO_VERSION__ -+#else -+#define __NO_VERSION__ -+#endif -+#endif ++ save_mcr = R_REG(osh, ®s[UART_MCR]); ++ W_REG(osh, ®s[UART_MCR], UART_MCR_LOOP | 0x0a); ++ status1 = R_REG(osh, ®s[UART_MSR]) & 0xf0; ++ W_REG(osh, ®s[UART_MCR], save_mcr); + -+#if defined(MODULE) && defined(MODVERSIONS) -+#include -+#endif ++ return (status1 == 0x90); ++} + -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -+#include -+#endif ++/* ++ * Initializes UART access. The callback function will be called once ++ * per found UART. ++ */ ++void ++BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, ++ uint reg_shift)) ++{ ++ osl_t *osh; ++ void *regs; ++ ulong base; ++ uint irq; ++ int i, n; + ++ osh = sb_osh(sbh); + -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -+#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") -+#define module_param_string(_name_, _string_, _size_, _perm_) MODULE_PARM(_string_, "c" __MODULE_STRING(_size_)) -+#endif ++ if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) { ++ extifregs_t *eir = (extifregs_t *) regs; ++ sbconfig_t *sb; + -+/* linux/malloc.h is deprecated, use linux/slab.h instead. */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9)) -+#include -+#else -+#include -+#endif ++ /* Determine external UART register base */ ++ sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF); ++ base = EXTIF_CFGIF_BASE(sb_base(R_REG(osh, &sb->sbadmatch1))); + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++ /* Determine IRQ */ ++ irq = sb_irq(sbh); + -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)) -+#include -+#else -+#include -+#ifndef work_struct -+#define work_struct tq_struct -+#endif -+#ifndef INIT_WORK -+#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data)) -+#endif -+#ifndef schedule_work -+#define schedule_work(_work) schedule_task((_work)) -+#endif -+#ifndef flush_scheduled_work -+#define flush_scheduled_work() flush_scheduled_tasks() -+#endif -+#endif ++ /* Disable GPIO interrupt initially */ ++ W_REG(osh, &eir->gpiointpolarity, 0); ++ W_REG(osh, &eir->gpiointmask, 0); + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) -+/* Some distributions have their own 2.6.x compatibility layers */ -+#ifndef IRQ_NONE -+typedef void irqreturn_t; -+#define IRQ_NONE -+#define IRQ_HANDLED -+#define IRQ_RETVAL(x) -+#endif -+#else -+typedef irqreturn_t (*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); -+#endif ++ /* Search for external UARTs */ ++ n = 2; ++ for (i = 0; i < 2; i++) { ++ regs = (void *) REG_MAP(base + (i * 8), 8); ++ if (serial_exists(osh, regs)) { ++ /* Set GPIO 1 to be the external UART IRQ */ ++ W_REG(osh, &eir->gpiointmask, 2); ++ /* XXXDetermine external UART clock */ ++ if (add) ++ add(regs, irq, 13500000, 0); ++ } ++ } + -+#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) ++ /* Add internal UART if enabled */ ++ if (R_REG(osh, &eir->corecontrol) & CC_UE) ++ if (add) ++ add((void *) &eir->uartdata, irq, sb_clock(sbh), 2); ++ } else if ((regs = sb_setcore(sbh, SB_CC, 0))) { ++ chipcregs_t *cc = (chipcregs_t *) regs; ++ uint32 rev, cap, pll, baud_base, div; + -+#include -+#include -+#include -+#include -+#include -+#include ++ /* Determine core revision and capabilities */ ++ rev = sb_corerev(sbh); ++ cap = R_REG(osh, &cc->capabilities); ++ pll = cap & CAP_PLL_MASK; + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)) -+/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which -+ * does this, but it's not in 2.4 so we do our own for now. */ -+static inline void -+cs_error(client_handle_t handle, int func, int ret) -+{ -+ error_info_t err = { func, ret }; -+ CardServices(ReportError, handle, &err); -+} -+#endif ++ /* Determine IRQ */ ++ irq = sb_irq(sbh); + -+#endif /* CONFIG_PCMCIA */ ++ if (pll == PLL_TYPE1) { ++ /* PLL clock */ ++ baud_base = sb_clock_rate(pll, ++ R_REG(osh, &cc->clockcontrol_n), ++ R_REG(osh, &cc->clockcontrol_m2)); ++ div = 1; ++ } else { ++ /* Fixed ALP clock */ ++ if (rev >= 11 && rev != 15) { ++ baud_base = 20000000; ++ div = 1; ++ /* Set the override bit so we don't divide it */ ++ W_REG(osh, &cc->corecontrol, CC_UARTCLKO); ++ } ++ /* Internal backplane clock */ ++ else if (rev >= 3) { ++ baud_base = sb_clock(sbh); ++ div = 2; /* Minimum divisor */ ++ W_REG(osh, &cc->clkdiv, ++ ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div)); ++ } ++ /* Fixed internal backplane clock */ ++ else { ++ baud_base = 88000000; ++ div = 48; ++ } + -+#ifndef __exit -+#define __exit -+#endif -+#ifndef __devexit -+#define __devexit -+#endif -+#ifndef __devinit -+#define __devinit __init -+#endif -+#ifndef __devinitdata -+#define __devinitdata -+#endif -+#ifndef __devexit_p -+#define __devexit_p(x) x -+#endif ++ /* Clock source depends on strapping if UartClkOverride is unset */ ++ if ((rev > 0) && ++ ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) { ++ if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) { ++ /* Internal divided backplane clock */ ++ baud_base /= div; ++ } else { ++ /* Assume external clock of 1.8432 MHz */ ++ baud_base = 1843200; ++ } ++ } ++ } + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) ++ /* Add internal UARTs */ ++ n = cap & CAP_UARTS_MASK; ++ for (i = 0; i < n; i++) { ++ /* Register offset changed after revision 0 */ ++ if (rev) ++ regs = (void *)((ulong) &cc->uart0data + (i * 256)); ++ else ++ regs = (void *)((ulong) &cc->uart0data + (i * 8)); + -+#define pci_get_drvdata(dev) (dev)->sysdata -+#define pci_set_drvdata(dev, value) (dev)->sysdata=(value) ++ if (add) ++ add(regs, irq, baud_base, 0); ++ } ++ } ++} + +diff -urN linux.old/arch/mips/bcm947xx/include/bcm4710.h linux.dev/arch/mips/bcm947xx/include/bcm4710.h +--- linux.old/arch/mips/bcm947xx/include/bcm4710.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/bcm4710.h 2006-04-27 22:30:01.000000000 +0200 +@@ -0,0 +1,91 @@ +/* -+ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration ++ * BCM4710 address space map and definitions ++ * Think twice before adding to this file, this is not the kitchen sink ++ * These definitions are not guaranteed for all 47xx chips, only the 4710 ++ * ++ * Copyright 2004, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: bcm4710.h,v 1.3 2004/09/27 07:23:30 tallest Exp $ + */ + -+struct pci_device_id { -+ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ -+ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ -+ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ -+ unsigned long driver_data; /* Data private to the driver */ -+}; -+ -+struct pci_driver { -+ struct list_head node; -+ char *name; -+ const struct pci_device_id *id_table; /* NULL if wants all devices */ -+ int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ -+ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ -+ void (*suspend)(struct pci_dev *dev); /* Device suspended */ -+ void (*resume)(struct pci_dev *dev); /* Device woken up */ -+}; -+ -+#define MODULE_DEVICE_TABLE(type, name) -+#define PCI_ANY_ID (~0) ++#ifndef _bcm4710_h_ ++#define _bcm4710_h_ + -+/* compatpci.c */ -+#define pci_module_init pci_register_driver -+extern int pci_register_driver(struct pci_driver *drv); -+extern void pci_unregister_driver(struct pci_driver *drv); ++/* Address map */ ++#define BCM4710_SDRAM 0x00000000 /* Physical SDRAM */ ++#define BCM4710_PCI_MEM 0x08000000 /* Host Mode PCI memory access space (64 MB) */ ++#define BCM4710_PCI_CFG 0x0c000000 /* Host Mode PCI configuration space (64 MB) */ ++#define BCM4710_PCI_DMA 0x40000000 /* Client Mode PCI memory access space (1 GB) */ ++#define BCM4710_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ ++#define BCM4710_ENUM 0x18000000 /* Beginning of core enumeration space */ + -+#endif /* PCI registration */ ++/* Core register space */ ++#define BCM4710_REG_SDRAM 0x18000000 /* SDRAM core registers */ ++#define BCM4710_REG_ILINE20 0x18001000 /* InsideLine20 core registers */ ++#define BCM4710_REG_EMAC0 0x18002000 /* Ethernet MAC 0 core registers */ ++#define BCM4710_REG_CODEC 0x18003000 /* Codec core registers */ ++#define BCM4710_REG_USB 0x18004000 /* USB core registers */ ++#define BCM4710_REG_PCI 0x18005000 /* PCI core registers */ ++#define BCM4710_REG_MIPS 0x18006000 /* MIPS core registers */ ++#define BCM4710_REG_EXTIF 0x18007000 /* External Interface core registers */ ++#define BCM4710_REG_EMAC1 0x18008000 /* Ethernet MAC 1 core registers */ ++ ++#define BCM4710_EXTIF 0x1f000000 /* External Interface base address */ ++#define BCM4710_PCMCIA_MEM 0x1f000000 /* External Interface PCMCIA memory access */ ++#define BCM4710_PCMCIA_IO 0x1f100000 /* PCMCIA I/O access */ ++#define BCM4710_PCMCIA_CONF 0x1f200000 /* PCMCIA configuration */ ++#define BCM4710_PROG 0x1f800000 /* Programable interface */ ++#define BCM4710_FLASH 0x1fc00000 /* Flash */ ++ ++#define BCM4710_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */ ++ ++#define BCM4710_UART (BCM4710_REG_EXTIF + 0x00000300) ++ ++#define BCM4710_EUART (BCM4710_EXTIF + 0x00800000) ++#define BCM4710_LED (BCM4710_EXTIF + 0x00900000) ++ ++#define SBFLAG_PCI 0 ++#define SBFLAG_ENET0 1 ++#define SBFLAG_ILINE20 2 ++#define SBFLAG_CODEC 3 ++#define SBFLAG_USB 4 ++#define SBFLAG_EXTIF 5 ++#define SBFLAG_ENET1 6 + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) -+#ifdef MODULE -+#define module_init(x) int init_module(void) { return x(); } -+#define module_exit(x) void cleanup_module(void) { x(); } ++#ifdef CONFIG_HWSIM ++#define BCM4710_TRACE(trval) do { *((int *)0xa0000f18) = (trval); } while (0) +#else -+#define module_init(x) __initcall(x); -+#define module_exit(x) __exitcall(x); -+#endif ++#define BCM4710_TRACE(trval) +#endif + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48)) -+#define list_for_each(pos, head) \ -+ for (pos = (head)->next; pos != (head); pos = pos->next) -+#endif + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)) -+#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)]) -+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,44)) -+#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) -+#endif ++/* BCM94702 CPCI -ExtIF used for LocalBus devs */ + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,23)) -+#define pci_enable_device(dev) do { } while (0) -+#endif ++#define BCM94702_CPCI_RESET_ADDR BCM4710_EXTIF ++#define BCM94702_CPCI_BOARDID_ADDR (BCM4710_EXTIF | 0x4000) ++#define BCM94702_CPCI_DOC_ADDR (BCM4710_EXTIF | 0x6000) ++#define BCM94702_DOC_ADDR BCM94702_CPCI_DOC_ADDR ++#define BCM94702_CPCI_LED_ADDR (BCM4710_EXTIF | 0xc000) ++#define BCM94702_CPCI_NVRAM_ADDR (BCM4710_EXTIF | 0xe000) ++#define BCM94702_CPCI_NVRAM_SIZE 0x1ff0 /* 8K NVRAM : DS1743/STM48txx*/ ++#define BCM94702_CPCI_TOD_REG_BASE (BCM94702_CPCI_NVRAM_ADDR | 0x1ff0) + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14)) -+#define net_device device -+#endif ++#define LED_REG(x) \ ++ (*(volatile unsigned char *) (KSEG1ADDR(BCM94702_CPCI_LED_ADDR) + (x))) + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,42)) ++/* ++ * Reset function implemented in PLD. Read or write should trigger hard reset ++ */ ++#define SYS_HARD_RESET() \ ++ { for (;;) \ ++ *( (volatile unsigned char *)\ ++ KSEG1ADDR(BCM94702_CPCI_RESET_ADDR) ) = 0x80; \ ++ } + ++#endif /* _bcm4710_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/bcmdefs.h linux.dev/arch/mips/bcm947xx/include/bcmdefs.h +--- linux.old/arch/mips/bcm947xx/include/bcmdefs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/bcmdefs.h 2006-04-27 20:12:21.000000000 +0200 +@@ -0,0 +1,106 @@ +/* -+ * DMA mapping ++ * Misc system wide definitions + * -+ * See linux/Documentation/DMA-mapping.txt ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * $Id: bcmdefs.h,v 1.1.1.3 2006/04/08 06:13:39 honor Exp $ + */ + -+#ifndef PCI_DMA_TODEVICE -+#define PCI_DMA_TODEVICE 1 -+#define PCI_DMA_FROMDEVICE 2 ++#ifndef _bcmdefs_h_ ++#define _bcmdefs_h_ ++ ++/* ++ * One doesn't need to include this file explicitly, gets included automatically if ++ * typedefs.h is included. ++ */ ++ ++/* Reclaiming text and data : ++ * The following macros specify special linker sections that can be reclaimed ++ * after a system is considered 'up'. ++ */ ++#if defined(__GNUC__) && defined(BCMRECLAIM) ++extern bool bcmreclaimed; ++#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini." #_data))) _data ++#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini." #_fn))) _fn ++#else /* #if defined(__GNUC__) && defined(BCMRECLAIM) */ ++#define BCMINITDATA(_data) _data ++#define BCMINITFN(_fn) _fn ++#define bcmreclaimed 0 ++#endif /* #if defined(__GNUC__) && defined(BCMRECLAIM) */ ++ ++/* Reclaim uninit functions if BCMNODOWN is defined */ ++/* and if they are not already removed by -gc-sections */ ++#ifdef BCMNODOWN ++#define BCMUNINITFN(_fn) BCMINITFN(_fn) ++#else ++#define BCMUNINITFN(_fn) _fn +#endif + -+typedef u32 dma_addr_t; ++#ifdef BCMRECLAIM ++#define CONST ++#else ++#define CONST const ++#endif /* BCMRECLAIM */ + -+/* Pure 2^n version of get_order */ -+static inline int get_order(unsigned long size) -+{ -+ int order; ++/* Compatibility with old-style BCMRECLAIM */ ++#define BCMINIT(_id) _id + -+ size = (size-1) >> (PAGE_SHIFT-1); -+ order = -1; -+ do { -+ size >>= 1; -+ order++; -+ } while (size); -+ return order; -+} + -+static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, -+ dma_addr_t *dma_handle) -+{ -+ void *ret; -+ int gfp = GFP_ATOMIC | GFP_DMA; ++/* Put some library data/code into ROM to reduce RAM requirements */ ++#if defined(__GNUC__) && defined(BCMROMOFFLOAD) ++#define BCMROMDATA(_data) __attribute__ ((__section__ (".datarom." #_data))) _data ++#define BCMROMFN(_fn) __attribute__ ((__section__ (".textrom." #_fn))) _fn ++#else ++#define BCMROMDATA(_data) _data ++#define BCMROMFN(_fn) _fn ++#endif + -+ ret = (void *)__get_free_pages(gfp, get_order(size)); ++/* Bus types */ ++#define SB_BUS 0 /* Silicon Backplane */ ++#define PCI_BUS 1 /* PCI target */ ++#define PCMCIA_BUS 2 /* PCMCIA target */ ++#define SDIO_BUS 3 /* SDIO target */ ++#define JTAG_BUS 4 /* JTAG */ ++#define NO_BUS 0xFF /* Bus that does not support R/W REG */ + -+ if (ret != NULL) { -+ memset(ret, 0, size); -+ *dma_handle = virt_to_bus(ret); -+ } -+ return ret; -+} -+static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, -+ void *vaddr, dma_addr_t dma_handle) -+{ -+ free_pages((unsigned long)vaddr, get_order(size)); -+} -+#ifdef ILSIM -+extern uint pci_map_single(void *dev, void *va, uint size, int direction); -+extern void pci_unmap_single(void *dev, uint pa, uint size, int direction); ++/* Allows optimization for single-bus support */ ++#ifdef BCMBUSTYPE ++#define BUSTYPE(bus) (BCMBUSTYPE) +#else -+#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) -+#define pci_unmap_single(cookie, address, size, dir) ++#define BUSTYPE(bus) (bus) +#endif + -+#endif /* DMA mapping */ ++/* Defines for DMA Address Width - Shared between OSL and HNDDMA */ ++#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ ++#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */ ++#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */ + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)) ++#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */ ++#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */ ++#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */ ++#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */ + -+#define dev_kfree_skb_any(a) dev_kfree_skb(a) -+#define netif_down(dev) do { (dev)->start = 0; } while(0) ++/* packet headroom necessary to accomodate the largest header in the system, (i.e TXOFF). ++ * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. ++ * There is a compile time check in wlc.c which ensure that this value is at least as big ++ * as TXOFF. This value is used in dma_rxfill (hnddma.c). ++ */ ++#define BCMEXTRAHDROOM 160 ++ ++/* Headroom required for dongle-to-host communication. Packets allocated ++ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should ++ * leave this much room in front for low-level message headers which may ++ * be needed to get across the dongle bus to the host. (These messages ++ * don't go over the network, so room for the full WL header above would ++ * be a waste.) ++ */ ++#define BCMDONGLEHDRSZ 8 + -+/* pcmcia-cs provides its own netdevice compatibility layer */ -+#ifndef _COMPAT_NETDEVICE_H + ++ ++#endif /* _bcmdefs_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/bcmdevs.h linux.dev/arch/mips/bcm947xx/include/bcmdevs.h +--- linux.old/arch/mips/bcm947xx/include/bcmdevs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/bcmdevs.h 2006-04-27 22:30:25.000000000 +0200 +@@ -0,0 +1,369 @@ +/* -+ * SoftNet ++ * Broadcom device-specific manifest constants. + * -+ * For pre-softnet kernels we need to tell the upper layer not to -+ * re-enter start_xmit() while we are in there. However softnet -+ * guarantees not to enter while we are in there so there is no need -+ * to do the netif_stop_queue() dance unless the transmit queue really -+ * gets stuck. This should also improve performance according to tests -+ * done by Aman Singla. ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * $Id: bcmdevs.h,v 1.1.1.17 2006/04/15 01:29:08 michael Exp $ + */ + -+#define dev_kfree_skb_irq(a) dev_kfree_skb(a) -+#define netif_wake_queue(dev) do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while(0) -+#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy) ++#ifndef _BCMDEVS_H ++#define _BCMDEVS_H + -+static inline void netif_start_queue(struct net_device *dev) -+{ -+ dev->tbusy = 0; -+ dev->interrupt = 0; -+ dev->start = 1; -+} ++#include "bcm4710.h" + -+#define netif_queue_stopped(dev) (dev)->tbusy -+#define netif_running(dev) (dev)->start ++/* Known PCI vendor Id's */ ++#define VENDOR_EPIGRAM 0xfeda ++#define VENDOR_BROADCOM 0x14e4 ++#define VENDOR_3COM 0x10b7 ++#define VENDOR_NETGEAR 0x1385 ++#define VENDOR_DIAMOND 0x1092 ++#define VENDOR_DELL 0x1028 ++#define VENDOR_HP 0x0e11 ++#define VENDOR_APPLE 0x106b + -+#endif /* _COMPAT_NETDEVICE_H */ ++/* PCI Device Id's */ ++#define BCM4210_DEVICE_ID 0x1072 /* never used */ ++#define BCM4211_DEVICE_ID 0x4211 ++#define BCM4230_DEVICE_ID 0x1086 /* never used */ ++#define BCM4231_DEVICE_ID 0x4231 + -+#define netif_device_attach(dev) netif_start_queue(dev) -+#define netif_device_detach(dev) netif_stop_queue(dev) ++#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */ ++#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ ++#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ ++#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */ + -+/* 2.4.x renamed bottom halves to tasklets */ -+#define tasklet_struct tq_struct -+static inline void tasklet_schedule(struct tasklet_struct *tasklet) -+{ -+ queue_task(tasklet, &tq_immediate); -+ mark_bh(IMMEDIATE_BH); -+} ++#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ ++#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ + -+static inline void tasklet_init(struct tasklet_struct *tasklet, -+ void (*func)(unsigned long), -+ unsigned long data) -+{ -+ tasklet->next = NULL; -+ tasklet->sync = 0; -+ tasklet->routine = (void (*)(void *))func; -+ tasklet->data = (void *)data; -+} -+#define tasklet_kill(tasklet) {do{} while(0);} ++#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ ++#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ + -+/* 2.4.x introduced del_timer_sync() */ -+#define del_timer_sync(timer) del_timer(timer) ++#define BCM47XX_ILINE_ID 0x4711 /* 47xx iline20 */ ++#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */ ++#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */ ++#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */ ++#define BCM47XX_USB_ID 0x4715 /* 47xx usb */ ++#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */ ++#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */ ++#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */ ++#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */ ++#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */ ++#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */ ++#define BCM47XX_ATA100_ID 0x471d /* 47xx parallel ATA */ ++#define BCM47XX_SATAXOR_ID 0x471e /* 47xx serial ATA & XOR DMA */ ++#define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */ + -+#else ++#define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */ ++#define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */ + -+#define netif_down(dev) ++#define BCM4710_CHIP_ID 0x4710 /* 4710 chipid returned by sb_chip() */ ++#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ + -+#endif /* SoftNet */ ++#define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ ++#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ ++#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ ++#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)) ++#define BCM4306_CHIP_ID 0x4306 /* 4306 chipcommon chipid */ ++#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ ++#define BCM4306_D11G_ID2 0x4325 ++#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ ++#define BCM4306_UART_ID 0x4322 /* 4306 uart */ ++#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ ++#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ + -+/* -+ * Emit code to initialise a tq_struct's routine and data pointers -+ */ -+#define PREPARE_TQUEUE(_tq, _routine, _data) \ -+ do { \ -+ (_tq)->routine = _routine; \ -+ (_tq)->data = _data; \ -+ } while (0) ++#define BCM4309_PKG_ID 1 /* 4309 package id */ + -+/* -+ * Emit code to initialise all of a tq_struct -+ */ -+#define INIT_TQUEUE(_tq, _routine, _data) \ -+ do { \ -+ INIT_LIST_HEAD(&(_tq)->list); \ -+ (_tq)->sync = 0; \ -+ PREPARE_TQUEUE((_tq), (_routine), (_data)); \ -+ } while (0) ++#define BCM4311_CHIP_ID 0x4311 /* 4311 PCIe 802.11a/b/g */ ++#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */ ++#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */ ++#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */ + -+#endif ++#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ ++#define BCM4303_PKG_ID 2 /* 4303 package id */ + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6)) ++#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ ++#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ + -+/* Power management related routines */ ++#define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ ++#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ + -+static inline int -+pci_save_state(struct pci_dev *dev, u32 *buffer) -+{ -+ int i; -+ if (buffer) { -+ for (i = 0; i < 16; i++) -+ pci_read_config_dword(dev, i * 4,&buffer[i]); -+ } -+ return 0; -+} ++#define BCM4318_CHIP_ID 0x4318 /* 4318 chip common chipid */ ++#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */ ++#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */ ++#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */ + -+static inline int -+pci_restore_state(struct pci_dev *dev, u32 *buffer) -+{ -+ int i; ++#define BCM4321_CHIP_ID 0x4321 /* 4321 chip common chipid */ ++#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */ ++#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Hgz band id */ ++#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */ + -+ if (buffer) { -+ for (i = 0; i < 16; i++) -+ pci_write_config_dword(dev,i * 4, buffer[i]); -+ } -+ /* -+ * otherwise, write the context information we know from bootup. -+ * This works around a problem where warm-booting from Windows -+ * combined with a D3(hot)->D0 transition causes PCI config -+ * header data to be forgotten. -+ */ -+ else { -+ for (i = 0; i < 6; i ++) -+ pci_write_config_dword(dev, -+ PCI_BASE_ADDRESS_0 + (i * 4), -+ pci_resource_start(dev, i)); -+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); -+ } -+ return 0; -+} ++#define BCM4331_CHIP_ID 0x4331 /* 4331 chip common chipid */ ++#define BCM4331_D11N2G_ID 0x4330 /* 4331 802.11n 2.4Ghz band id */ ++#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ ++#define BCM4331_D11N5G_ID 0x4332 /* 4331 802.11n 5Ghz band id */ + -+#endif /* PCI power management */ ++#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */ ++#define HDLSIM_PKG_ID 14 /* HDL simulator package id */ ++#define HWSIM_PKG_ID 15 /* Hardware simulator package id */ + -+/* Old cp0 access macros deprecated in 2.4.19 */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)) -+#define read_c0_count() read_32bit_cp0_register(CP0_COUNT) -+#endif ++#define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */ ++#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ ++#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ ++#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ ++#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ + -+/* Module refcount handled internally in 2.6.x */ -+#ifndef SET_MODULE_OWNER -+#define SET_MODULE_OWNER(dev) do {} while (0) -+#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT -+#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT -+#else -+#define OLD_MOD_INC_USE_COUNT do {} while (0) -+#define OLD_MOD_DEC_USE_COUNT do {} while (0) -+#endif ++#define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */ ++#define BCM5350_CHIP_ID 0x5350 /* bcm5350 chipcommon chipid */ ++#define BCM5352_CHIP_ID 0x5352 /* bcm5352 chipcommon chipid */ + -+#ifndef SET_NETDEV_DEV -+#define SET_NETDEV_DEV(net, pdev) do {} while (0) -+#endif ++#define BCM4320_CHIP_ID 0x4320 /* bcm4320 chipcommon chipid */ + -+#ifndef HAVE_FREE_NETDEV -+#define free_netdev(dev) kfree(dev) -+#endif ++#define BCM4328_CHIP_ID 0x4328 /* bcm4328 chipcommon chipid */ + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) -+/* struct packet_type redefined in 2.6.x */ -+#define af_packet_priv data -+#endif ++#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */ ++#define BCM43XX_JTAGM_ID 0x43f1 /* 43xx jtagm device id */ ++#define BCM43XXOLD_JTAGM_ID 0x4331 /* 43xx old jtagm device id */ + -+#endif /* _linuxver_h_ */ -diff -Naur linux.old/arch/mips/bcm947xx/include/mipsinc.h linux.dev/arch/mips/bcm947xx/include/mipsinc.h ---- linux.old/arch/mips/bcm947xx/include/mipsinc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/mipsinc.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,552 @@ -+/* -+ * HND Run Time Environment for standalone MIPS programs. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ -+ */ ++#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */ ++#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */ + -+#ifndef _MISPINC_H -+#define _MISPINC_H ++#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */ + ++#define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */ + -+/* MIPS defines */ ++/* PCMCIA vendor Id's */ + -+#ifdef _LANGUAGE_ASSEMBLY ++#define VENDOR_BROADCOM_PCMCIA 0x02d0 + -+/* -+ * Symbolic register names for 32 bit ABI -+ */ -+#define zero $0 /* wired zero */ -+#define AT $1 /* assembler temp - uppercase because of ".set at" */ -+#define v0 $2 /* return value */ -+#define v1 $3 -+#define a0 $4 /* argument registers */ -+#define a1 $5 -+#define a2 $6 -+#define a3 $7 -+#define t0 $8 /* caller saved */ -+#define t1 $9 -+#define t2 $10 -+#define t3 $11 -+#define t4 $12 -+#define t5 $13 -+#define t6 $14 -+#define t7 $15 -+#define s0 $16 /* callee saved */ -+#define s1 $17 -+#define s2 $18 -+#define s3 $19 -+#define s4 $20 -+#define s5 $21 -+#define s6 $22 -+#define s7 $23 -+#define t8 $24 /* caller saved */ -+#define t9 $25 -+#define jp $25 /* PIC jump register */ -+#define k0 $26 /* kernel scratch */ -+#define k1 $27 -+#define gp $28 /* global pointer */ -+#define sp $29 /* stack pointer */ -+#define fp $30 /* frame pointer */ -+#define s8 $30 /* same like fp! */ -+#define ra $31 /* return address */ ++/* SDIO vendor Id's */ ++#define VENDOR_BROADCOM_SDIO 0x00BF + + -+/* -+ * CP0 Registers -+ */ ++/* boardflags */ ++#define BFL_BTCOEXIST 0x0001 /* This board implements Bluetooth coexistance */ ++#define BFL_PACTRL 0x0002 /* This board has gpio 9 controlling the PA */ ++#define BFL_AIRLINEMODE 0x0004 /* This board implements gpio13 radio disable indication */ ++#define BFL_ENETROBO 0x0010 /* This board has robo switch or core */ ++#define BFL_CCKHIPWR 0x0040 /* Can do high-power CCK transmission */ ++#define BFL_ENETADM 0x0080 /* This board has ADMtek switch */ ++#define BFL_ENETVLAN 0x0100 /* This board has vlan capability */ ++#define BFL_AFTERBURNER 0x0200 /* This board supports Afterburner mode */ ++#define BFL_NOPCI 0x0400 /* This board leaves PCI floating */ ++#define BFL_FEM 0x0800 /* This board supports the Front End Module */ ++#define BFL_EXTLNA 0x1000 /* This board has an external LNA */ ++#define BFL_HGPA 0x2000 /* This board has a high gain PA */ ++#define BFL_BTCMOD 0x4000 /* This board' BTCOEXIST is in the alternate gpios */ ++#define BFL_ALTIQ 0x8000 /* Alternate I/Q settings */ + -+#define C0_INX $0 -+#define C0_RAND $1 -+#define C0_TLBLO0 $2 -+#define C0_TLBLO C0_TLBLO0 -+#define C0_TLBLO1 $3 -+#define C0_CTEXT $4 -+#define C0_PGMASK $5 -+#define C0_WIRED $6 -+#define C0_BADVADDR $8 -+#define C0_COUNT $9 -+#define C0_TLBHI $10 -+#define C0_COMPARE $11 -+#define C0_SR $12 -+#define C0_STATUS C0_SR -+#define C0_CAUSE $13 -+#define C0_EPC $14 -+#define C0_PRID $15 -+#define C0_CONFIG $16 -+#define C0_LLADDR $17 -+#define C0_WATCHLO $18 -+#define C0_WATCHHI $19 -+#define C0_XCTEXT $20 -+#define C0_DIAGNOSTIC $22 -+#define C0_BROADCOM C0_DIAGNOSTIC -+#define C0_PERFORMANCE $25 -+#define C0_ECC $26 -+#define C0_CACHEERR $27 -+#define C0_TAGLO $28 -+#define C0_TAGHI $29 -+#define C0_ERREPC $30 -+#define C0_DESAVE $31 ++/* boardflags2 */ ++#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* This board has an external rxbb regulator */ ++#define BFL2_SSWITCH_AVAIL 0x00000002 /* This board has a superswitch for > 2 antennas */ ++#define BFL2_TXPWRCTRL_EN 0x00000004 /* This board permits TX Power Control to be enabled */ + -+/* -+ * LEAF - declare leaf routine -+ */ -+#define LEAF(symbol) \ -+ .globl symbol; \ -+ .align 2; \ -+ .type symbol,@function; \ -+ .ent symbol,0; \ -+symbol: .frame sp,0,ra ++/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ ++#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistance Input */ ++#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistance Out */ ++#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistance Input */ ++#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistance Out */ ++#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ ++#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ ++#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ ++#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ ++#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ + -+/* -+ * END - mark end of function -+ */ -+#define END(function) \ -+ .end function; \ -+ .size function,.-function ++/* power control defines */ ++#define PLL_DELAY 150 /* us pll on delay */ ++#define FREF_DELAY 200 /* us fref change delay */ ++#define MIN_SLOW_CLK 32 /* us Slow clock period */ ++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ + -+#define _ULCAST_ ++/* Reference Board Types */ + -+#else ++#define BU4710_BOARD 0x0400 ++#define VSIM4710_BOARD 0x0401 ++#define QT4710_BOARD 0x0402 + -+/* -+ * The following macros are especially useful for __asm__ -+ * inline assembler. -+ */ -+#ifndef __STR -+#define __STR(x) #x -+#endif -+#ifndef STR -+#define STR(x) __STR(x) -+#endif ++#define BU4309_BOARD 0x040a ++#define BCM94309CB_BOARD 0x040b ++#define BCM94309MP_BOARD 0x040c ++#define BCM4309AP_BOARD 0x040d + -+#define _ULCAST_ (unsigned long) ++#define BCM94302MP_BOARD 0x040e + ++#define BU4306_BOARD 0x0416 ++#define BCM94306CB_BOARD 0x0417 ++#define BCM94306MP_BOARD 0x0418 + -+/* -+ * CP0 Registers -+ */ ++#define BCM94710D_BOARD 0x041a ++#define BCM94710R1_BOARD 0x041b ++#define BCM94710R4_BOARD 0x041c ++#define BCM94710AP_BOARD 0x041d + -+#define C0_INX 0 /* CP0: TLB Index */ -+#define C0_RAND 1 /* CP0: TLB Random */ -+#define C0_TLBLO0 2 /* CP0: TLB EntryLo0 */ -+#define C0_TLBLO C0_TLBLO0 /* CP0: TLB EntryLo0 */ -+#define C0_TLBLO1 3 /* CP0: TLB EntryLo1 */ -+#define C0_CTEXT 4 /* CP0: Context */ -+#define C0_PGMASK 5 /* CP0: TLB PageMask */ -+#define C0_WIRED 6 /* CP0: TLB Wired */ -+#define C0_BADVADDR 8 /* CP0: Bad Virtual Address */ -+#define C0_COUNT 9 /* CP0: Count */ -+#define C0_TLBHI 10 /* CP0: TLB EntryHi */ -+#define C0_COMPARE 11 /* CP0: Compare */ -+#define C0_SR 12 /* CP0: Processor Status */ -+#define C0_STATUS C0_SR /* CP0: Processor Status */ -+#define C0_CAUSE 13 /* CP0: Exception Cause */ -+#define C0_EPC 14 /* CP0: Exception PC */ -+#define C0_PRID 15 /* CP0: Processor Revision Indentifier */ -+#define C0_CONFIG 16 /* CP0: Config */ -+#define C0_LLADDR 17 /* CP0: LLAddr */ -+#define C0_WATCHLO 18 /* CP0: WatchpointLo */ -+#define C0_WATCHHI 19 /* CP0: WatchpointHi */ -+#define C0_XCTEXT 20 /* CP0: XContext */ -+#define C0_DIAGNOSTIC 22 /* CP0: Diagnostic */ -+#define C0_BROADCOM C0_DIAGNOSTIC /* CP0: Broadcom Register */ -+#define C0_PERFORMANCE 25 /* CP0: Performance Counter/Control Registers */ -+#define C0_ECC 26 /* CP0: ECC */ -+#define C0_CACHEERR 27 /* CP0: CacheErr */ -+#define C0_TAGLO 28 /* CP0: TagLo */ -+#define C0_TAGHI 29 /* CP0: TagHi */ -+#define C0_ERREPC 30 /* CP0: ErrorEPC */ -+#define C0_DESAVE 31 /* CP0: DebugSave */ ++#define BU2050_BOARD 0x041f + -+#endif /* _LANGUAGE_ASSEMBLY */ + -+/* -+ * Memory segments (32bit kernel mode addresses) -+ */ -+#undef KUSEG -+#undef KSEG0 -+#undef KSEG1 -+#undef KSEG2 -+#undef KSEG3 -+#define KUSEG 0x00000000 -+#define KSEG0 0x80000000 -+#define KSEG1 0xa0000000 -+#define KSEG2 0xc0000000 -+#define KSEG3 0xe0000000 -+#define PHYSADDR_MASK 0x1fffffff ++#define BCM94309G_BOARD 0x0421 + -+/* -+ * Map an address to a certain kernel segment -+ */ -+#undef PHYSADDR -+#undef KSEG0ADDR -+#undef KSEG1ADDR -+#undef KSEG2ADDR -+#undef KSEG3ADDR ++#define BU4704_BOARD 0x0423 ++#define BU4702_BOARD 0x0424 + -+#define PHYSADDR(a) (_ULCAST_(a) & PHYSADDR_MASK) -+#define KSEG0ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG0) -+#define KSEG1ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG1) -+#define KSEG2ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG2) -+#define KSEG3ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG3) ++#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */ + + -+#ifndef Index_Invalidate_I -+/* -+ * Cache Operations -+ */ -+#define Index_Invalidate_I 0x00 -+#define Index_Writeback_Inv_D 0x01 -+#define Index_Invalidate_SI 0x02 -+#define Index_Writeback_Inv_SD 0x03 -+#define Index_Load_Tag_I 0x04 -+#define Index_Load_Tag_D 0x05 -+#define Index_Load_Tag_SI 0x06 -+#define Index_Load_Tag_SD 0x07 -+#define Index_Store_Tag_I 0x08 -+#define Index_Store_Tag_D 0x09 -+#define Index_Store_Tag_SI 0x0A -+#define Index_Store_Tag_SD 0x0B -+#define Create_Dirty_Excl_D 0x0d -+#define Create_Dirty_Excl_SD 0x0f -+#define Hit_Invalidate_I 0x10 -+#define Hit_Invalidate_D 0x11 -+#define Hit_Invalidate_SI 0x12 -+#define Hit_Invalidate_SD 0x13 -+#define Fill_I 0x14 -+#define Hit_Writeback_Inv_D 0x15 -+ /* 0x16 is unused */ -+#define Hit_Writeback_Inv_SD 0x17 -+#define R5K_Page_Invalidate_S 0x17 -+#define Hit_Writeback_I 0x18 -+#define Hit_Writeback_D 0x19 -+ /* 0x1a is unused */ -+#define Hit_Writeback_SD 0x1b -+ /* 0x1c is unused */ -+ /* 0x1e is unused */ -+#define Hit_Set_Virtual_SI 0x1e -+#define Hit_Set_Virtual_SD 0x1f -+#endif ++#define BCM94702MN_BOARD 0x0428 + ++/* BCM4702 1U CompactPCI Board */ ++#define BCM94702CPCI_BOARD 0x0429 + -+/* -+ * R4x00 interrupt enable / cause bits -+ */ -+#define IE_SW0 (_ULCAST_(1) << 8) -+#define IE_SW1 (_ULCAST_(1) << 9) -+#define IE_IRQ0 (_ULCAST_(1) << 10) -+#define IE_IRQ1 (_ULCAST_(1) << 11) -+#define IE_IRQ2 (_ULCAST_(1) << 12) -+#define IE_IRQ3 (_ULCAST_(1) << 13) -+#define IE_IRQ4 (_ULCAST_(1) << 14) -+#define IE_IRQ5 (_ULCAST_(1) << 15) ++/* BCM4702 with BCM95380 VLAN Router */ ++#define BCM95380RR_BOARD 0x042a + -+#ifndef ST0_UM -+/* -+ * Bitfields in the mips32 cp0 status register -+ */ -+#define ST0_IE 0x00000001 -+#define ST0_EXL 0x00000002 -+#define ST0_ERL 0x00000004 -+#define ST0_UM 0x00000010 -+#define ST0_SWINT0 0x00000100 -+#define ST0_SWINT1 0x00000200 -+#define ST0_HWINT0 0x00000400 -+#define ST0_HWINT1 0x00000800 -+#define ST0_HWINT2 0x00001000 -+#define ST0_HWINT3 0x00002000 -+#define ST0_HWINT4 0x00004000 -+#define ST0_HWINT5 0x00008000 -+#define ST0_IM 0x0000ff00 -+#define ST0_NMI 0x00080000 -+#define ST0_SR 0x00100000 -+#define ST0_TS 0x00200000 -+#define ST0_BEV 0x00400000 -+#define ST0_RE 0x02000000 -+#define ST0_RP 0x08000000 -+#define ST0_CU 0xf0000000 -+#define ST0_CU0 0x10000000 -+#define ST0_CU1 0x20000000 -+#define ST0_CU2 0x40000000 -+#define ST0_CU3 0x80000000 -+#endif ++/* cb4306 with SiGe PA */ ++#define BCM94306CBSG_BOARD 0x042b + ++/* cb4306 with SiGe PA */ ++#define PCSG94306_BOARD 0x042d + -+/* -+ * Bitfields in the mips32 cp0 cause register -+ */ -+#define C_EXC 0x0000007c -+#define C_EXC_SHIFT 2 -+#define C_INT 0x0000ff00 -+#define C_INT_SHIFT 8 -+#define C_SW0 (_ULCAST_(1) << 8) -+#define C_SW1 (_ULCAST_(1) << 9) -+#define C_IRQ0 (_ULCAST_(1) << 10) -+#define C_IRQ1 (_ULCAST_(1) << 11) -+#define C_IRQ2 (_ULCAST_(1) << 12) -+#define C_IRQ3 (_ULCAST_(1) << 13) -+#define C_IRQ4 (_ULCAST_(1) << 14) -+#define C_IRQ5 (_ULCAST_(1) << 15) -+#define C_WP 0x00400000 -+#define C_IV 0x00800000 -+#define C_CE 0x30000000 -+#define C_CE_SHIFT 28 -+#define C_BD 0x80000000 ++/* bu4704 with sdram */ ++#define BU4704SD_BOARD 0x042e + -+/* Values in C_EXC */ -+#define EXC_INT 0 -+#define EXC_TLBM 1 -+#define EXC_TLBL 2 -+#define EXC_TLBS 3 -+#define EXC_AEL 4 -+#define EXC_AES 5 -+#define EXC_IBE 6 -+#define EXC_DBE 7 -+#define EXC_SYS 8 -+#define EXC_BPT 9 -+#define EXC_RI 10 -+#define EXC_CU 11 -+#define EXC_OV 12 -+#define EXC_TR 13 -+#define EXC_WATCH 23 -+#define EXC_MCHK 24 ++/* Dual 11a/11g Router */ ++#define BCM94704AGR_BOARD 0x042f + ++/* 11a-only minipci */ ++#define BCM94308MP_BOARD 0x0430 + -+/* -+ * Bits in the cp0 config register. -+ */ -+#define CONF_CM_CACHABLE_NO_WA 0 -+#define CONF_CM_CACHABLE_WA 1 -+#define CONF_CM_UNCACHED 2 -+#define CONF_CM_CACHABLE_NONCOHERENT 3 -+#define CONF_CM_CACHABLE_CE 4 -+#define CONF_CM_CACHABLE_COW 5 -+#define CONF_CM_CACHABLE_CUW 6 -+#define CONF_CM_CACHABLE_ACCELERATED 7 -+#define CONF_CM_CMASK 7 -+#define CONF_CU (_ULCAST_(1) << 3) -+#define CONF_DB (_ULCAST_(1) << 4) -+#define CONF_IB (_ULCAST_(1) << 5) -+#define CONF_SE (_ULCAST_(1) << 12) -+#define CONF_SC (_ULCAST_(1) << 17) -+#define CONF_AC (_ULCAST_(1) << 23) -+#define CONF_HALT (_ULCAST_(1) << 25) + + -+/* -+ * Bits in the cp0 config register select 1. -+ */ -+#define CONF1_FP 0x00000001 /* FPU present */ -+#define CONF1_EP 0x00000002 /* EJTAG present */ -+#define CONF1_CA 0x00000004 /* mips16 implemented */ -+#define CONF1_WR 0x00000008 /* Watch registers present */ -+#define CONF1_PC 0x00000010 /* Performance counters present */ -+#define CONF1_DA_SHIFT 7 /* D$ associativity */ -+#define CONF1_DA_MASK 0x00000380 -+#define CONF1_DA_BASE 1 -+#define CONF1_DL_SHIFT 10 /* D$ line size */ -+#define CONF1_DL_MASK 0x00001c00 -+#define CONF1_DL_BASE 2 -+#define CONF1_DS_SHIFT 13 /* D$ sets/way */ -+#define CONF1_DS_MASK 0x0000e000 -+#define CONF1_DS_BASE 64 -+#define CONF1_IA_SHIFT 16 /* I$ associativity */ -+#define CONF1_IA_MASK 0x00070000 -+#define CONF1_IA_BASE 1 -+#define CONF1_IL_SHIFT 19 /* I$ line size */ -+#define CONF1_IL_MASK 0x00380000 -+#define CONF1_IL_BASE 2 -+#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */ -+#define CONF1_IS_MASK 0x01c00000 -+#define CONF1_IS_BASE 64 -+#define CONF1_MS_MASK 0x7e000000 /* Number of tlb entries */ -+#define CONF1_MS_SHIFT 25 ++#define BU4712_BOARD 0x0444 ++#define BU4712SD_BOARD 0x045d ++#define BU4712L_BOARD 0x045f + -+/* PRID register */ -+#define PRID_COPT_MASK 0xff000000 -+#define PRID_COMP_MASK 0x00ff0000 -+#define PRID_IMP_MASK 0x0000ff00 -+#define PRID_REV_MASK 0x000000ff ++/* BCM4712 boards */ ++#define BCM94712AP_BOARD 0x0445 ++#define BCM94712P_BOARD 0x0446 + -+#define PRID_COMP_LEGACY 0x000000 -+#define PRID_COMP_MIPS 0x010000 -+#define PRID_COMP_BROADCOM 0x020000 -+#define PRID_COMP_ALCHEMY 0x030000 -+#define PRID_COMP_SIBYTE 0x040000 -+#define PRID_IMP_BCM4710 0x4000 -+#define PRID_IMP_BCM3302 0x9000 -+#define PRID_IMP_BCM3303 0x9100 ++/* BCM4318 boards */ ++#define BU4318_BOARD 0x0447 ++#define CB4318_BOARD 0x0448 ++#define MPG4318_BOARD 0x0449 ++#define MP4318_BOARD 0x044a ++#define SD4318_BOARD 0x044b + -+#define PRID_IMP_UNKNOWN 0xff00 ++/* BCM63XX boards */ ++#define BCM96338_BOARD 0x6338 ++#define BCM96348_BOARD 0x6348 + -+#define BCM330X(id) \ -+ (((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) \ -+ || ((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == (PRID_COMP_BROADCOM | PRID_IMP_BCM3303))) ++/* Another mp4306 with SiGe */ ++#define BCM94306P_BOARD 0x044c + -+/* Bits in C0_BROADCOM */ -+#define BRCM_PFC_AVAIL 0x20000000 /* PFC is available */ -+#define BRCM_DC_ENABLE 0x40000000 /* Enable Data $ */ -+#define BRCM_IC_ENABLE 0x80000000 /* Enable Instruction $ */ -+#define BRCM_PFC_ENABLE 0x00400000 /* Obsolete? Enable PFC (at least on 4310) */ ++/* mp4303 */ ++#define BCM94303MP_BOARD 0x044e + -+/* PreFetch Cache aka Read Ahead Cache */ ++/* mpsgh4306 */ ++#define BCM94306MPSGH_BOARD 0x044f + -+#define PFC_CR0 0xff400000 /* control reg 0 */ -+#define PFC_CR1 0xff400004 /* control reg 1 */ ++/* BRCM 4306 w/ Front End Modules */ ++#define BCM94306MPM 0x0450 ++#define BCM94306MPL 0x0453 + -+/* PFC operations */ -+#define PFC_I 0x00000001 /* Enable PFC use for instructions */ -+#define PFC_D 0x00000002 /* Enable PFC use for data */ -+#define PFC_PFI 0x00000004 /* Enable seq. prefetch for instructions */ -+#define PFC_PFD 0x00000008 /* Enable seq. prefetch for data */ -+#define PFC_CINV 0x00000010 /* Enable selective (i/d) cacheop flushing */ -+#define PFC_NCH 0x00000020 /* Disable flushing based on cacheops */ -+#define PFC_DPF 0x00000040 /* Enable directional prefetching */ -+#define PFC_FLUSH 0x00000100 /* Flush the PFC */ -+#define PFC_BRR 0x40000000 /* Bus error indication */ -+#define PFC_PWR 0x80000000 /* Disable power saving (clock gating) */ ++/* 4712agr */ ++#define BCM94712AGR_BOARD 0x0451 + -+/* Handy defaults */ -+#define PFC_DISABLED 0 -+#define PFC_AUTO 0xffffffff /* auto select the default mode */ -+#define PFC_INST (PFC_I | PFC_PFI | PFC_CINV) -+#define PFC_INST_NOPF (PFC_I | PFC_CINV) -+#define PFC_DATA (PFC_D | PFC_PFD | PFC_CINV) -+#define PFC_DATA_NOPF (PFC_D | PFC_CINV) -+#define PFC_I_AND_D (PFC_INST | PFC_DATA) -+#define PFC_I_AND_D_NOPF (PFC_INST_NOPF | PFC_DATA_NOPF) ++/* pcmcia 4303 */ ++#define PC4303_BOARD 0x0454 + ++/* 5350K */ ++#define BCM95350K_BOARD 0x0455 + -+/* -+ * These are the UART port assignments, expressed as offsets from the base -+ * register. These assignments should hold for any serial port based on -+ * a 8250, 16450, or 16550(A). -+ */ ++/* 5350R */ ++#define BCM95350R_BOARD 0x0456 + -+#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ -+#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ -+#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ -+#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ -+#define UART_LCR 3 /* Out: Line Control Register */ -+#define UART_MCR 4 /* Out: Modem Control Register */ -+#define UART_LSR 5 /* In: Line Status Register */ -+#define UART_MSR 6 /* In: Modem Status Register */ -+#define UART_SCR 7 /* I/O: Scratch Register */ -+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ -+#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ -+#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ -+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ -+#define UART_LSR_RXRDY 0x01 /* Receiver ready */ ++/* 4306mplna */ ++#define BCM94306MPLNA_BOARD 0x0457 + ++/* 4320 boards */ ++#define BU4320_BOARD 0x0458 ++#define BU4320S_BOARD 0x0459 ++#define BCM94320PH_BOARD 0x045a + -+#ifndef _LANGUAGE_ASSEMBLY ++/* 4306mph */ ++#define BCM94306MPH_BOARD 0x045b + -+/* -+ * Macros to access the system control coprocessor -+ */ ++/* 4306pciv */ ++#define BCM94306PCIV_BOARD 0x045c + -+#define MFC0(source, sel) \ -+({ \ -+ int __res; \ -+ __asm__ __volatile__( \ -+ ".set\tnoreorder\n\t" \ -+ ".set\tnoat\n\t" \ -+ ".word\t"STR(0x40010000 | ((source)<<11) | (sel))"\n\t" \ -+ "move\t%0,$1\n\t" \ -+ ".set\tat\n\t" \ -+ ".set\treorder" \ -+ :"=r" (__res) \ -+ : \ -+ :"$1"); \ -+ __res; \ -+}) ++#define BU4712SD_BOARD 0x045d + -+#define MTC0(source, sel, value) \ -+do { \ -+ __asm__ __volatile__( \ -+ ".set\tnoreorder\n\t" \ -+ ".set\tnoat\n\t" \ -+ "move\t$1,%z0\n\t" \ -+ ".word\t"STR(0x40810000 | ((source)<<11) | (sel))"\n\t" \ -+ ".set\tat\n\t" \ -+ ".set\treorder" \ -+ : \ -+ :"jr" (value) \ -+ :"$1"); \ -+} while (0) ++#define BCM94320PFLSH_BOARD 0x045e + -+#define get_c0_count() \ -+({ \ -+ int __res; \ -+ __asm__ __volatile__( \ -+ ".set\tnoreorder\n\t" \ -+ ".set\tnoat\n\t" \ -+ "mfc0\t%0,$9\n\t" \ -+ ".set\tat\n\t" \ -+ ".set\treorder" \ -+ :"=r" (__res)); \ -+ __res; \ -+}) ++#define BU4712L_BOARD 0x045f ++#define BCM94712LGR_BOARD 0x0460 ++#define BCM94320R_BOARD 0x0461 + -+static INLINE void icache_probe(uint32 config1, uint *size, uint *lsize) -+{ -+ uint lsz, sets, ways; ++#define BU5352_BOARD 0x0462 + -+ /* Instruction Cache Size = Associativity * Line Size * Sets Per Way */ -+ if ((lsz = ((config1 & CONF1_IL_MASK) >> CONF1_IL_SHIFT))) -+ lsz = CONF1_IL_BASE << lsz; -+ sets = CONF1_IS_BASE << ((config1 & CONF1_IS_MASK) >> CONF1_IS_SHIFT); -+ ways = CONF1_IA_BASE + ((config1 & CONF1_IA_MASK) >> CONF1_IA_SHIFT); -+ *size = lsz * sets * ways; -+ *lsize = lsz; -+} ++#define BCM94318MPGH_BOARD 0x0463 + -+static INLINE void dcache_probe(uint32 config1, uint *size, uint *lsize) -+{ -+ uint lsz, sets, ways; ++#define BU4311_BOARD 0x0464 ++#define BCM94311MC_BOARD 0x0465 ++#define BCM94311MCAG_BOARD 0x0466 + -+ /* Data Cache Size = Associativity * Line Size * Sets Per Way */ -+ if ((lsz = ((config1 & CONF1_DL_MASK) >> CONF1_DL_SHIFT))) -+ lsz = CONF1_DL_BASE << lsz; -+ sets = CONF1_DS_BASE << ((config1 & CONF1_DS_MASK) >> CONF1_DS_SHIFT); -+ ways = CONF1_DA_BASE + ((config1 & CONF1_DA_MASK) >> CONF1_DA_SHIFT); -+ *size = lsz * sets * ways; -+ *lsize = lsz; -+} ++#define BCM95352GR_BOARD 0x0467 + -+#define cache_op(base, op) \ -+ __asm__ __volatile__(" \ -+ .set noreorder; \ -+ .set mips3; \ -+ cache %1, (%0); \ -+ .set mips0; \ -+ .set reorder" \ -+ : \ -+ : "r" (base), \ -+ "i" (op)); ++/* bcm95351agr */ ++#define BCM95351AGR_BOARD 0x0470 + -+#define cache_unroll4(base, delta, op) \ -+ __asm__ __volatile__(" \ -+ .set noreorder; \ -+ .set mips3; \ -+ cache %1,0(%0); \ -+ cache %1,delta(%0); \ -+ cache %1,(2 * delta)(%0); \ -+ cache %1,(3 * delta)(%0); \ -+ .set mips0; \ -+ .set reorder" \ -+ : \ -+ : "r" (base), \ -+ "i" (op)); ++/* bcm94704mpcb */ ++#define BCM94704MPCB_BOARD 0x0472 + -+#endif /* !_LANGUAGE_ASSEMBLY */ ++/* 4785 boards */ ++#define BU4785_BOARD 0x0478 + -+#endif /* _MISPINC_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/osl.h linux.dev/arch/mips/bcm947xx/include/osl.h ---- linux.old/arch/mips/bcm947xx/include/osl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/osl.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,42 @@ -+/* -+ * OS Abstraction Layer -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ ++/* 4321 boards */ ++#define BU4321_BOARD 0x046b ++#define BU4321E_BOARD 0x047c ++#define MP4321_BOARD 0x046c ++#define CB2_4321_BOARD 0x046d ++#define MC4321_BOARD 0x046e + -+#ifndef _osl_h_ -+#define _osl_h_ ++/* # of GPIO pins */ ++#define GPIO_NUMPINS 16 + -+/* osl handle type forward declaration */ -+typedef struct os_handle osl_t; ++/* radio ID codes */ ++#define NORADIO_ID 0xe4f5 ++#define NORADIO_IDCODE 0x4e4f5246 + -+#if defined(linux) -+#include -+#elif defined(NDIS) -+#include -+#elif defined(_CFE_) -+#include -+#elif defined(_HNDRTE_) -+#include -+#elif defined(_MINOSL_) -+#include -+#elif PMON -+#include -+#elif defined(MACOSX) -+#include -+#else -+#error "Unsupported OSL requested" -+#endif ++#define BCM2050_ID 0x2050 ++#define BCM2050_IDCODE 0x02050000 ++#define BCM2050A0_IDCODE 0x1205017f ++#define BCM2050A1_IDCODE 0x2205017f ++#define BCM2050R8_IDCODE 0x8205017f + -+/* handy */ -+#define SET_REG(r, mask, val) W_REG((r), ((R_REG(r) & ~(mask)) | (val))) -+#define MAXPRIO 7 /* 0-7 */ ++#define BCM2055_ID 0x2055 ++#define BCM2055_IDCODE 0x02055000 ++#define BCM2055A0_IDCODE 0x1205517f + -+#endif /* _osl_h_ */ -diff -Naur linux.old/arch/mips/bcm947xx/include/pcicfg.h linux.dev/arch/mips/bcm947xx/include/pcicfg.h ---- linux.old/arch/mips/bcm947xx/include/pcicfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/pcicfg.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,451 @@ ++#define BCM2060_ID 0x2060 ++#define BCM2060_IDCODE 0x02060000 ++#define BCM2060WW_IDCODE 0x1206017f ++ ++#define BCM2062_ID 0x2062 ++#define BCM2062_IDCODE 0x02062000 ++#define BCM2062A0_IDCODE 0x0206217f ++ ++/* parts of an idcode: */ ++#define IDCODE_MFG_MASK 0x00000fff ++#define IDCODE_MFG_SHIFT 0 ++#define IDCODE_ID_MASK 0x0ffff000 ++#define IDCODE_ID_SHIFT 12 ++#define IDCODE_REV_MASK 0xf0000000 ++#define IDCODE_REV_SHIFT 28 ++ ++#endif /* _BCMDEVS_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/bcmdevs1.h linux.dev/arch/mips/bcm947xx/include/bcmdevs1.h +--- linux.old/arch/mips/bcm947xx/include/bcmdevs1.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/bcmdevs1.h 2006-05-02 04:32:03.000000000 +0200 +@@ -0,0 +1,391 @@ +/* -+ * pcicfg.h: PCI configuration constants and structures. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * Broadcom device-specific manifest constants. + * ++ * Copyright 2005, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * $Id$ + */ + -+#ifndef _h_pci_ -+#define _h_pci_ -+ -+/* The following inside ifndef's so we don't collide with NTDDK.H */ -+#ifndef PCI_MAX_BUS -+#define PCI_MAX_BUS 0x100 -+#endif -+#ifndef PCI_MAX_DEVICES -+#define PCI_MAX_DEVICES 0x20 -+#endif -+#ifndef PCI_MAX_FUNCTION -+#define PCI_MAX_FUNCTION 0x8 -+#endif ++#ifndef _BCMDEVS_H ++#define _BCMDEVS_H + -+#ifndef PCI_INVALID_VENDORID -+#define PCI_INVALID_VENDORID 0xffff -+#endif -+#ifndef PCI_INVALID_DEVICEID -+#define PCI_INVALID_DEVICEID 0xffff -+#endif + ++/* Known PCI vendor Id's */ ++#define VENDOR_EPIGRAM 0xfeda ++#define VENDOR_BROADCOM 0x14e4 ++#define VENDOR_3COM 0x10b7 ++#define VENDOR_NETGEAR 0x1385 ++#define VENDOR_DIAMOND 0x1092 ++#define VENDOR_DELL 0x1028 ++#define VENDOR_HP 0x0e11 ++#define VENDOR_APPLE 0x106b + -+/* Convert between bus-slot-function-register and config addresses */ ++/* PCI Device Id's */ ++#define BCM4210_DEVICE_ID 0x1072 /* never used */ ++#define BCM4211_DEVICE_ID 0x4211 ++#define BCM4230_DEVICE_ID 0x1086 /* never used */ ++#define BCM4231_DEVICE_ID 0x4231 + -+#define PCICFG_BUS_SHIFT 16 /* Bus shift */ -+#define PCICFG_SLOT_SHIFT 11 /* Slot shift */ -+#define PCICFG_FUN_SHIFT 8 /* Function shift */ -+#define PCICFG_OFF_SHIFT 0 /* Register shift */ ++#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */ ++#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ ++#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ ++#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */ + -+#define PCICFG_BUS_MASK 0xff /* Bus mask */ -+#define PCICFG_SLOT_MASK 0x1f /* Slot mask */ -+#define PCICFG_FUN_MASK 7 /* Function mask */ -+#define PCICFG_OFF_MASK 0xff /* Bus mask */ ++#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ ++#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ + -+#define PCI_CONFIG_ADDR(b, s, f, o) \ -+ ((((b) & PCICFG_BUS_MASK) << PCICFG_BUS_SHIFT) \ -+ | (((s) & PCICFG_SLOT_MASK) << PCICFG_SLOT_SHIFT) \ -+ | (((f) & PCICFG_FUN_MASK) << PCICFG_FUN_SHIFT) \ -+ | (((o) & PCICFG_OFF_MASK) << PCICFG_OFF_SHIFT)) ++#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ ++#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ + -+#define PCI_CONFIG_BUS(a) (((a) >> PCICFG_BUS_SHIFT) & PCICFG_BUS_MASK) -+#define PCI_CONFIG_SLOT(a) (((a) >> PCICFG_SLOT_SHIFT) & PCICFG_SLOT_MASK) -+#define PCI_CONFIG_FUN(a) (((a) >> PCICFG_FUN_SHIFT) & PCICFG_FUN_MASK) -+#define PCI_CONFIG_OFF(a) (((a) >> PCICFG_OFF_SHIFT) & PCICFG_OFF_MASK) ++#define BCM47XX_ILINE_ID 0x4711 /* 47xx iline20 */ ++#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */ ++#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */ ++#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */ ++#define BCM47XX_USB_ID 0x4715 /* 47xx usb */ ++#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */ ++#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */ ++#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */ ++#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */ ++#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */ ++#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */ + -+/* PCIE Config space accessing MACROS*/ ++#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ + -+#define PCIECFG_BUS_SHIFT 24 /* Bus shift */ -+#define PCIECFG_SLOT_SHIFT 19 /* Slot/Device shift */ -+#define PCIECFG_FUN_SHIFT 16 /* Function shift */ -+#define PCIECFG_OFF_SHIFT 0 /* Register shift */ ++#define BCM4610_DEVICE_ID 0x4610 /* 4610 primary function 0 */ ++#define BCM4610_ILINE_ID 0x4611 /* 4610 iline100 */ ++#define BCM4610_V90_ID 0x4612 /* 4610 v90 codec */ ++#define BCM4610_ENET_ID 0x4613 /* 4610 enet */ ++#define BCM4610_EXT_ID 0x4614 /* 4610 external i/f */ ++#define BCM4610_USB_ID 0x4615 /* 4610 usb */ + -+#define PCIECFG_BUS_MASK 0xff /* Bus mask */ -+#define PCIECFG_SLOT_MASK 0x1f /* Slot/Device mask */ -+#define PCIECFG_FUN_MASK 7 /* Function mask */ -+#define PCIECFG_OFF_MASK 0x3ff /* Register mask */ ++#define BCM4402_DEVICE_ID 0x4402 /* 4402 primary function 0 */ ++#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ ++#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ ++#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ + -+#define PCIE_CONFIG_ADDR(b, s, f, o) \ -+ ((((b) & PCIECFG_BUS_MASK) << PCIECFG_BUS_SHIFT) \ -+ | (((s) & PCIECFG_SLOT_MASK) << PCIECFG_SLOT_SHIFT) \ -+ | (((f) & PCIECFG_FUN_MASK) << PCIECFG_FUN_SHIFT) \ -+ | (((o) & PCIECFG_OFF_MASK) << PCIECFG_OFF_SHIFT)) ++#define BCM4301_DEVICE_ID 0x4301 /* 4301 primary function 0 */ ++#define BCM4301_D11B_ID 0x4301 /* 4301 802.11b */ + -+#define PCIE_CONFIG_BUS(a) (((a) >> PCIECFG_BUS_SHIFT) & PCIECFG_BUS_MASK) -+#define PCIE_CONFIG_SLOT(a) (((a) >> PCIECFG_SLOT_SHIFT) & PCIECFG_SLOT_MASK) -+#define PCIE_CONFIG_FUN(a) (((a) >> PCIECFG_FUN_SHIFT) & PCIECFG_FUN_MASK) -+#define PCIE_CONFIG_OFF(a) (((a) >> PCIECFG_OFF_SHIFT) & PCIECFG_OFF_MASK) ++#define BCM4307_DEVICE_ID 0x4307 /* 4307 primary function 0 */ ++#define BCM4307_V90_ID 0x4305 /* 4307 v90 codec */ ++#define BCM4307_ENET_ID 0x4306 /* 4307 enet */ ++#define BCM4307_D11B_ID 0x4307 /* 4307 802.11b */ + -+ -+/* The actual config space */ ++#define BCM4306_DEVICE_ID 0x4306 /* 4306 chipcommon chipid */ ++#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ ++#define BCM4306_D11G_ID2 0x4325 ++#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ ++#define BCM4306_UART_ID 0x4322 /* 4306 uart */ ++#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ ++#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ + -+#define PCI_BAR_MAX 6 ++#define BCM4309_PKG_ID 1 /* 4309 package id */ + -+#define PCI_ROM_BAR 8 ++#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ ++#define BCM4303_PKG_ID 2 /* 4303 package id */ + -+#define PCR_RSVDA_MAX 2 ++#define BCM4310_DEVICE_ID 0x4310 /* 4310 chipcommon chipid */ ++#define BCM4310_D11B_ID 0x4311 /* 4310 802.11b */ ++#define BCM4310_UART_ID 0x4312 /* 4310 uart */ ++#define BCM4310_ENET_ID 0x4313 /* 4310 enet */ ++#define BCM4310_USB_ID 0x4315 /* 4310 usb */ + -+/* pci config status reg has a bit to indicate that capability ptr is present*/ ++#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ ++#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ + -+#define PCI_CAPPTR_PRESENT 0x0010 + -+typedef struct _pci_config_regs { -+ unsigned short vendor; -+ unsigned short device; -+ unsigned short command; -+ unsigned short status; -+ unsigned char rev_id; -+ unsigned char prog_if; -+ unsigned char sub_class; -+ unsigned char base_class; -+ unsigned char cache_line_size; -+ unsigned char latency_timer; -+ unsigned char header_type; -+ unsigned char bist; -+ unsigned long base[PCI_BAR_MAX]; -+ unsigned long cardbus_cis; -+ unsigned short subsys_vendor; -+ unsigned short subsys_id; -+ unsigned long baserom; -+ unsigned long rsvd_a[PCR_RSVDA_MAX]; -+ unsigned char int_line; -+ unsigned char int_pin; -+ unsigned char min_gnt; -+ unsigned char max_lat; -+ unsigned char dev_dep[192]; -+} pci_config_regs; ++#define BCM4704_DEVICE_ID 0x4704 /* 4704 chipcommon chipid */ ++#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ + -+#define SZPCR (sizeof (pci_config_regs)) -+#define MINSZPCR 64 /* offsetof (dev_dep[0] */ ++#define BCM4317_DEVICE_ID 0x4317 /* 4317 chip common chipid */ + -+/* A structure for the config registers is nice, but in most -+ * systems the config space is not memory mapped, so we need -+ * filed offsetts. :-( -+ */ -+#define PCI_CFG_VID 0 -+#define PCI_CFG_DID 2 -+#define PCI_CFG_CMD 4 -+#define PCI_CFG_STAT 6 -+#define PCI_CFG_REV 8 -+#define PCI_CFG_PROGIF 9 -+#define PCI_CFG_SUBCL 0xa -+#define PCI_CFG_BASECL 0xb -+#define PCI_CFG_CLSZ 0xc -+#define PCI_CFG_LATTIM 0xd -+#define PCI_CFG_HDR 0xe -+#define PCI_CFG_BIST 0xf -+#define PCI_CFG_BAR0 0x10 -+#define PCI_CFG_BAR1 0x14 -+#define PCI_CFG_BAR2 0x18 -+#define PCI_CFG_BAR3 0x1c -+#define PCI_CFG_BAR4 0x20 -+#define PCI_CFG_BAR5 0x24 -+#define PCI_CFG_CIS 0x28 -+#define PCI_CFG_SVID 0x2c -+#define PCI_CFG_SSID 0x2e -+#define PCI_CFG_ROMBAR 0x30 -+#define PCI_CFG_CAPPTR 0x34 -+#define PCI_CFG_INT 0x3c -+#define PCI_CFG_PIN 0x3d -+#define PCI_CFG_MINGNT 0x3e -+#define PCI_CFG_MAXLAT 0x3f ++#define BCM4318_DEVICE_ID 0x4318 /* 4318 chip common chipid */ ++#define BCM4318_D11G_ID 0x4318 /* 4318 801.11b/g id */ ++#define BCM4318_D11DUAL_ID 0x4319 /* 4318 801.11a/b/g id */ ++#define BCM4318_JTAGM_ID 0x4331 /* 4318 jtagm device id */ + -+/* Classes and subclasses */ ++#define FPGA_JTAGM_ID 0x4330 /* ??? */ + -+typedef enum { -+ PCI_CLASS_OLD = 0, -+ PCI_CLASS_DASDI, -+ PCI_CLASS_NET, -+ PCI_CLASS_DISPLAY, -+ PCI_CLASS_MMEDIA, -+ PCI_CLASS_MEMORY, -+ PCI_CLASS_BRIDGE, -+ PCI_CLASS_COMM, -+ PCI_CLASS_BASE, -+ PCI_CLASS_INPUT, -+ PCI_CLASS_DOCK, -+ PCI_CLASS_CPU, -+ PCI_CLASS_SERIAL, -+ PCI_CLASS_INTELLIGENT = 0xe, -+ PCI_CLASS_SATELLITE, -+ PCI_CLASS_CRYPT, -+ PCI_CLASS_DSP, -+ PCI_CLASS_MAX -+} pci_classes; ++/* Address map */ ++#define BCM4710_SDRAM 0x00000000 /* Physical SDRAM */ ++#define BCM4710_PCI_MEM 0x08000000 /* Host Mode PCI memory access space (64 MB) */ ++#define BCM4710_PCI_CFG 0x0c000000 /* Host Mode PCI configuration space (64 MB) */ ++#define BCM4710_PCI_DMA 0x40000000 /* Client Mode PCI memory access space (1 GB) */ ++#define BCM4710_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ ++#define BCM4710_ENUM 0x18000000 /* Beginning of core enumeration space */ + -+typedef enum { -+ PCI_DASDI_SCSI, -+ PCI_DASDI_IDE, -+ PCI_DASDI_FLOPPY, -+ PCI_DASDI_IPI, -+ PCI_DASDI_RAID, -+ PCI_DASDI_OTHER = 0x80 -+} pci_dasdi_subclasses; ++/* Core register space */ ++#define BCM4710_REG_SDRAM 0x18000000 /* SDRAM core registers */ ++#define BCM4710_REG_ILINE20 0x18001000 /* InsideLine20 core registers */ ++#define BCM4710_REG_EMAC0 0x18002000 /* Ethernet MAC 0 core registers */ ++#define BCM4710_REG_CODEC 0x18003000 /* Codec core registers */ ++#define BCM4710_REG_USB 0x18004000 /* USB core registers */ ++#define BCM4710_REG_PCI 0x18005000 /* PCI core registers */ ++#define BCM4710_REG_MIPS 0x18006000 /* MIPS core registers */ ++#define BCM4710_REG_EXTIF 0x18007000 /* External Interface core registers */ ++#define BCM4710_REG_EMAC1 0x18008000 /* Ethernet MAC 1 core registers */ + -+typedef enum { -+ PCI_NET_ETHER, -+ PCI_NET_TOKEN, -+ PCI_NET_FDDI, -+ PCI_NET_ATM, -+ PCI_NET_OTHER = 0x80 -+} pci_net_subclasses; ++#define BCM4710_EXTIF 0x1f000000 /* External Interface base address */ ++#define BCM4710_PCMCIA_MEM 0x1f000000 /* External Interface PCMCIA memory access */ ++#define BCM4710_PCMCIA_IO 0x1f100000 /* PCMCIA I/O access */ ++#define BCM4710_PCMCIA_CONF 0x1f200000 /* PCMCIA configuration */ ++#define BCM4710_PROG 0x1f800000 /* Programable interface */ ++#define BCM4710_FLASH 0x1fc00000 /* Flash */ + -+typedef enum { -+ PCI_DISPLAY_VGA, -+ PCI_DISPLAY_XGA, -+ PCI_DISPLAY_3D, -+ PCI_DISPLAY_OTHER = 0x80 -+} pci_display_subclasses; ++#define BCM4710_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */ + -+typedef enum { -+ PCI_MMEDIA_VIDEO, -+ PCI_MMEDIA_AUDIO, -+ PCI_MMEDIA_PHONE, -+ PCI_MEDIA_OTHER = 0x80 -+} pci_mmedia_subclasses; ++#define BCM4710_UART (BCM4710_REG_EXTIF + 0x00000300) + -+typedef enum { -+ PCI_MEMORY_RAM, -+ PCI_MEMORY_FLASH, -+ PCI_MEMORY_OTHER = 0x80 -+} pci_memory_subclasses; ++#define BCM4710_EUART (BCM4710_EXTIF + 0x00800000) ++#define BCM4710_LED (BCM4710_EXTIF + 0x00900000) + -+typedef enum { -+ PCI_BRIDGE_HOST, -+ PCI_BRIDGE_ISA, -+ PCI_BRIDGE_EISA, -+ PCI_BRIDGE_MC, -+ PCI_BRIDGE_PCI, -+ PCI_BRIDGE_PCMCIA, -+ PCI_BRIDGE_NUBUS, -+ PCI_BRIDGE_CARDBUS, -+ PCI_BRIDGE_RACEWAY, -+ PCI_BRIDGE_OTHER = 0x80 -+} pci_bridge_subclasses; ++#define BCM4712_DEVICE_ID 0x4712 /* 4712 chipcommon chipid */ ++#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ ++#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ ++#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ ++#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ + -+typedef enum { -+ PCI_COMM_UART, -+ PCI_COMM_PARALLEL, -+ PCI_COMM_MULTIUART, -+ PCI_COMM_MODEM, -+ PCI_COMM_OTHER = 0x80 -+} pci_comm_subclasses; ++#define SDIOH_FPGA_ID 0x4380 /* sdio host fpga */ + -+typedef enum { -+ PCI_BASE_PIC, -+ PCI_BASE_DMA, -+ PCI_BASE_TIMER, -+ PCI_BASE_RTC, -+ PCI_BASE_PCI_HOTPLUG, -+ PCI_BASE_OTHER = 0x80 -+} pci_base_subclasses; ++#define BCM5365_DEVICE_ID 0x5365 /* 5365 chipcommon chipid */ ++#define BCM5350_DEVICE_ID 0x5350 /* bcm5350 chipcommon chipid */ ++#define BCM5352_DEVICE_ID 0x5352 /* bcm5352 chipcommon chipid */ + -+typedef enum { -+ PCI_INPUT_KBD, -+ PCI_INPUT_PEN, -+ PCI_INPUT_MOUSE, -+ PCI_INPUT_SCANNER, -+ PCI_INPUT_GAMEPORT, -+ PCI_INPUT_OTHER = 0x80 -+} pci_input_subclasses; ++#define BCM4320_DEVICE_ID 0x4320 /* bcm4320 chipcommon chipid */ + -+typedef enum { -+ PCI_DOCK_GENERIC, -+ PCI_DOCK_OTHER = 0x80 -+} pci_dock_subclasses; ++/* PCMCIA vendor Id's */ + -+typedef enum { -+ PCI_CPU_386, -+ PCI_CPU_486, -+ PCI_CPU_PENTIUM, -+ PCI_CPU_ALPHA = 0x10, -+ PCI_CPU_POWERPC = 0x20, -+ PCI_CPU_MIPS = 0x30, -+ PCI_CPU_COPROC = 0x40, -+ PCI_CPU_OTHER = 0x80 -+} pci_cpu_subclasses; ++#define VENDOR_BROADCOM_PCMCIA 0x02d0 + -+typedef enum { -+ PCI_SERIAL_IEEE1394, -+ PCI_SERIAL_ACCESS, -+ PCI_SERIAL_SSA, -+ PCI_SERIAL_USB, -+ PCI_SERIAL_FIBER, -+ PCI_SERIAL_SMBUS, -+ PCI_SERIAL_OTHER = 0x80 -+} pci_serial_subclasses; ++/* SDIO vendor Id's */ ++#define VENDOR_BROADCOM_SDIO 0x00BF + -+typedef enum { -+ PCI_INTELLIGENT_I2O, -+} pci_intelligent_subclasses; + -+typedef enum { -+ PCI_SATELLITE_TV, -+ PCI_SATELLITE_AUDIO, -+ PCI_SATELLITE_VOICE, -+ PCI_SATELLITE_DATA, -+ PCI_SATELLITE_OTHER = 0x80 -+} pci_satellite_subclasses; ++/* boardflags */ ++#define BFL_BTCOEXIST 0x0001 /* This board implements Bluetooth coexistance */ ++#define BFL_PACTRL 0x0002 /* This board has gpio 9 controlling the PA */ ++#define BFL_AIRLINEMODE 0x0004 /* This board implements gpio13 radio disable indication */ ++#define BFL_ENETROBO 0x0010 /* This board has robo switch or core */ ++#define BFL_CCKHIPWR 0x0040 /* Can do high-power CCK transmission */ ++#define BFL_ENETADM 0x0080 /* This board has ADMtek switch */ ++#define BFL_ENETVLAN 0x0100 /* This board has vlan capability */ ++#define BFL_AFTERBURNER 0x0200 /* This board supports Afterburner mode */ ++#define BFL_NOPCI 0x0400 /* This board leaves PCI floating */ ++#define BFL_FEM 0x0800 /* This board supports the Front End Module */ ++#define BFL_EXTLNA 0x1000 /* This board has an external LNA */ ++#define BFL_HGPA 0x2000 /* This board has a high gain PA */ ++#define BFL_BTCMOD 0x4000 /* This board' BTCOEXIST is in the alternate gpios */ ++#define BFL_ALTIQ 0x8000 /* Alternate I/Q settings */ + -+typedef enum { -+ PCI_CRYPT_NETWORK, -+ PCI_CRYPT_ENTERTAINMENT, -+ PCI_CRYPT_OTHER = 0x80 -+} pci_crypt_subclasses; ++/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ ++#define BOARD_GPIO_HWRAD_B 0x010 /* bit 4 is HWRAD input on 4301 */ ++#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistance Input */ ++#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistance Out */ ++#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistance Input */ ++#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistance Out */ ++#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ ++#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ ++#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ ++#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ ++#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ + -+typedef enum { -+ PCI_DSP_DPIO, -+ PCI_DSP_OTHER = 0x80 -+} pci_dsp_subclasses; ++/* Bus types */ ++#define SB_BUS 0 /* Silicon Backplane */ ++#define PCI_BUS 1 /* PCI target */ ++#define PCMCIA_BUS 2 /* PCMCIA target */ ++#define SDIO_BUS 3 /* SDIO target */ ++#define JTAG_BUS 4 /* JTAG */ + -+/* Header types */ -+typedef enum { -+ PCI_HEADER_NORMAL, -+ PCI_HEADER_BRIDGE, -+ PCI_HEADER_CARDBUS -+} pci_header_types; ++/* Allows optimization for single-bus support */ ++#ifdef BCMBUSTYPE ++#define BUSTYPE(bus) (BCMBUSTYPE) ++#else ++#define BUSTYPE(bus) (bus) ++#endif + ++/* power control defines */ ++#define PLL_DELAY 150 /* us pll on delay */ ++#define FREF_DELAY 200 /* us fref change delay */ ++#define MIN_SLOW_CLK 32 /* us Slow clock period */ ++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ + -+/* Overlay for a PCI-to-PCI bridge */ ++/* Reference Board Types */ + -+#define PPB_RSVDA_MAX 2 -+#define PPB_RSVDD_MAX 8 ++#define BU4710_BOARD 0x0400 ++#define VSIM4710_BOARD 0x0401 ++#define QT4710_BOARD 0x0402 + -+typedef struct _ppb_config_regs { -+ unsigned short vendor; -+ unsigned short device; -+ unsigned short command; -+ unsigned short status; -+ unsigned char rev_id; -+ unsigned char prog_if; -+ unsigned char sub_class; -+ unsigned char base_class; -+ unsigned char cache_line_size; -+ unsigned char latency_timer; -+ unsigned char header_type; -+ unsigned char bist; -+ unsigned long rsvd_a[PPB_RSVDA_MAX]; -+ unsigned char prim_bus; -+ unsigned char sec_bus; -+ unsigned char sub_bus; -+ unsigned char sec_lat; -+ unsigned char io_base; -+ unsigned char io_lim; -+ unsigned short sec_status; -+ unsigned short mem_base; -+ unsigned short mem_lim; -+ unsigned short pf_mem_base; -+ unsigned short pf_mem_lim; -+ unsigned long pf_mem_base_hi; -+ unsigned long pf_mem_lim_hi; -+ unsigned short io_base_hi; -+ unsigned short io_lim_hi; -+ unsigned short subsys_vendor; -+ unsigned short subsys_id; -+ unsigned long rsvd_b; -+ unsigned char rsvd_c; -+ unsigned char int_pin; -+ unsigned short bridge_ctrl; -+ unsigned char chip_ctrl; -+ unsigned char diag_ctrl; -+ unsigned short arb_ctrl; -+ unsigned long rsvd_d[PPB_RSVDD_MAX]; -+ unsigned char dev_dep[192]; -+} ppb_config_regs; ++#define BU4610_BOARD 0x0403 ++#define VSIM4610_BOARD 0x0404 + ++#define BU4307_BOARD 0x0405 ++#define BCM94301CB_BOARD 0x0406 ++#define BCM94301PC_BOARD 0x0406 /* Pcmcia 5v card */ ++#define BCM94301MP_BOARD 0x0407 ++#define BCM94307MP_BOARD 0x0408 ++#define BCMAP4307_BOARD 0x0409 + -+/* PCI CAPABILITY DEFINES */ -+#define PCI_CAP_POWERMGMTCAP_ID 0x01 -+#define PCI_CAP_MSICAP_ID 0x05 -+#define PCI_CAP_PCIECAP_ID 0x10 ++#define BU4309_BOARD 0x040a ++#define BCM94309CB_BOARD 0x040b ++#define BCM94309MP_BOARD 0x040c ++#define BCM4309AP_BOARD 0x040d + -+/* Data structure to define the Message Signalled Interrupt facility -+ * Valid for PCI and PCIE configurations */ -+typedef struct _pciconfig_cap_msi { -+ unsigned char capID; -+ unsigned char nextptr; -+ unsigned short msgctrl; -+ unsigned int msgaddr; -+} pciconfig_cap_msi; ++#define BCM94302MP_BOARD 0x040e + -+/* Data structure to define the Power managment facility -+ * Valid for PCI and PCIE configurations */ -+typedef struct _pciconfig_cap_pwrmgmt { -+ unsigned char capID; -+ unsigned char nextptr; -+ unsigned short pme_cap; -+ unsigned short pme_sts_ctrl; -+ unsigned char pme_bridge_ext; -+ unsigned char data; -+} pciconfig_cap_pwrmgmt; ++#define VSIM4310_BOARD 0x040f ++#define BU4711_BOARD 0x0410 ++#define BCM94310U_BOARD 0x0411 ++#define BCM94310AP_BOARD 0x0412 ++#define BCM94310MP_BOARD 0x0414 + -+/* Data structure to define the PCIE capability */ -+typedef struct _pciconfig_cap_pcie { -+ unsigned char capID; -+ unsigned char nextptr; -+ unsigned short pcie_cap; -+ unsigned int dev_cap; -+ unsigned short dev_ctrl; -+ unsigned short dev_status; -+ unsigned int link_cap; -+ unsigned short link_ctrl; -+ unsigned short link_status; -+} pciconfig_cap_pcie; ++#define BU4306_BOARD 0x0416 ++#define BCM94306CB_BOARD 0x0417 ++#define BCM94306MP_BOARD 0x0418 + -+/* PCIE Enhanced CAPABILITY DEFINES */ -+#define PCIE_EXTCFG_OFFSET 0x100 -+#define PCIE_ADVERRREP_CAPID 0x0001 -+#define PCIE_VC_CAPID 0x0002 -+#define PCIE_DEVSNUM_CAPID 0x0003 -+#define PCIE_PWRBUDGET_CAPID 0x0004 ++#define BCM94710D_BOARD 0x041a ++#define BCM94710R1_BOARD 0x041b ++#define BCM94710R4_BOARD 0x041c ++#define BCM94710AP_BOARD 0x041d + -+/* Header to define the PCIE specific capabilities in the extended config space */ -+typedef struct _pcie_enhanced_caphdr { -+ unsigned short capID; -+ unsigned short cap_ver : 4; -+ unsigned short next_ptr : 12; -+} pcie_enhanced_caphdr; + ++#define BU2050_BOARD 0x041f + -+/* Everything below is BRCM HND proprietary */ + -+#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */ -+#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */ -+#define PCI_SPROM_CONTROL 0x88 /* sprom property control */ -+#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */ -+#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */ -+#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */ -+#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */ -+#define PCI_BACKPLANE_ADDR 0xA0 /* address an arbitrary location on the system backplane */ -+#define PCI_BACKPLANE_DATA 0xA4 /* data at the location specified by above address register */ -+#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */ -+#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */ -+#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */ ++#define BCM94309G_BOARD 0x0421 + -+#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */ -+#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */ ++#define BCM94301PC3_BOARD 0x0422 /* Pcmcia 3.3v card */ + -+/* PCI_INT_STATUS */ -+#define PCI_SBIM_STATUS_SERR 0x4 /* backplane SBErr interrupt status */ ++#define BU4704_BOARD 0x0423 ++#define BU4702_BOARD 0x0424 + -+/* PCI_INT_MASK */ -+#define PCI_SBIM_SHIFT 8 /* backplane core interrupt mask bits offset */ -+#define PCI_SBIM_MASK 0xff00 /* backplane core interrupt mask */ -+#define PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */ ++#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */ + -+/* PCI_SPROM_CONTROL */ -+#define SPROM_BLANK 0x04 /* indicating a blank sprom */ -+#define SPROM_WRITEEN 0x10 /* sprom write enable */ -+#define SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */ ++#define BU4317_BOARD 0x0426 + -+#define SPROM_SIZE 256 /* sprom size in 16-bit */ -+#define SPROM_CRC_RANGE 64 /* crc cover range in 16-bit */ + -+/* PCI_CFG_CMD_STAT */ -+#define PCI_CFG_CMD_STAT_TA 0x08000000 /* target abort status */ ++#define BCM94702MN_BOARD 0x0428 + -+#endif -diff -Naur linux.old/arch/mips/bcm947xx/include/sbchipc.h linux.dev/arch/mips/bcm947xx/include/sbchipc.h ---- linux.old/arch/mips/bcm947xx/include/sbchipc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbchipc.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,440 @@ -+/* -+ * SiliconBackplane Chipcommon core hardware definitions. -+ * -+ * The chipcommon core provides chip identification, SB control, -+ * jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer, -+ * gpio interface, extbus, and support for serial and parallel flashes. -+ * -+ * $Id$ -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ */ ++/* BCM4702 1U CompactPCI Board */ ++#define BCM94702CPCI_BOARD 0x0429 + -+#ifndef _SBCHIPC_H -+#define _SBCHIPC_H ++/* BCM4702 with BCM95380 VLAN Router */ ++#define BCM95380RR_BOARD 0x042a + ++/* cb4306 with SiGe PA */ ++#define BCM94306CBSG_BOARD 0x042b + -+#ifndef _LANGUAGE_ASSEMBLY ++/* mp4301 with 2050 radio */ ++#define BCM94301MPL_BOARD 0x042c + -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif /* PAD */ ++/* cb4306 with SiGe PA */ ++#define PCSG94306_BOARD 0x042d + -+typedef volatile struct { -+ uint32 chipid; /* 0x0 */ -+ uint32 capabilities; -+ uint32 corecontrol; /* corerev >= 1 */ -+ uint32 bist; ++/* bu4704 with sdram */ ++#define BU4704SD_BOARD 0x042e + -+ /* OTP */ -+ uint32 otpstatus; /* 0x10, corerev >= 10 */ -+ uint32 otpcontrol; -+ uint32 otpprog; -+ uint32 PAD; ++/* Dual 11a/11g Router */ ++#define BCM94704AGR_BOARD 0x042f + -+ /* Interrupt control */ -+ uint32 intstatus; /* 0x20 */ -+ uint32 intmask; -+ uint32 chipcontrol; /* 0x28, rev >= 11 */ -+ uint32 chipstatus; /* 0x2c, rev >= 11 */ ++/* 11a-only minipci */ ++#define BCM94308MP_BOARD 0x0430 + -+ /* Jtag Master */ -+ uint32 jtagcmd; /* 0x30, rev >= 10 */ -+ uint32 jtagir; -+ uint32 jtagdr; -+ uint32 jtagctrl; + -+ /* serial flash interface registers */ -+ uint32 flashcontrol; /* 0x40 */ -+ uint32 flashaddress; -+ uint32 flashdata; -+ uint32 PAD[1]; + -+ /* Silicon backplane configuration broadcast control */ -+ uint32 broadcastaddress; /* 0x50 */ -+ uint32 broadcastdata; -+ uint32 PAD[2]; ++/* BCM94317 boards */ ++#define BCM94317CB_BOARD 0x0440 ++#define BCM94317MP_BOARD 0x0441 ++#define BCM94317PCMCIA_BOARD 0x0442 ++#define BCM94317SDIO_BOARD 0x0443 + -+ /* gpio - cleared only by power-on-reset */ -+ uint32 gpioin; /* 0x60 */ -+ uint32 gpioout; -+ uint32 gpioouten; -+ uint32 gpiocontrol; -+ uint32 gpiointpolarity; -+ uint32 gpiointmask; -+ uint32 PAD[2]; ++#define BU4712_BOARD 0x0444 ++#define BU4712SD_BOARD 0x045d ++#define BU4712L_BOARD 0x045f + -+ /* Watchdog timer */ -+ uint32 watchdog; /* 0x80 */ -+ uint32 PAD[1]; ++/* BCM4712 boards */ ++#define BCM94712AP_BOARD 0x0445 ++#define BCM94712P_BOARD 0x0446 + -+ /*GPIO based LED powersave registers corerev >= 16*/ -+ uint32 gpiotimerval; /*0x88 */ -+ uint32 gpiotimeroutmask; ++/* BCM4318 boards */ ++#define BU4318_BOARD 0x0447 ++#define CB4318_BOARD 0x0448 ++#define MPG4318_BOARD 0x0449 ++#define MP4318_BOARD 0x044a ++#define SD4318_BOARD 0x044b + -+ /* clock control */ -+ uint32 clockcontrol_n; /* 0x90 */ -+ uint32 clockcontrol_sb; /* aka m0 */ -+ uint32 clockcontrol_pci; /* aka m1 */ -+ uint32 clockcontrol_m2; /* mii/uart/mipsref */ -+ uint32 clockcontrol_mips; /* aka m3 */ -+ uint32 clkdiv; /* corerev >= 3 */ -+ uint32 PAD[2]; ++/* BCM63XX boards */ ++#define BCM96338_BOARD 0x6338 ++#define BCM96345_BOARD 0x6345 ++#define BCM96348_BOARD 0x6348 + -+ /* pll delay registers (corerev >= 4) */ -+ uint32 pll_on_delay; /* 0xb0 */ -+ uint32 fref_sel_delay; -+ uint32 slow_clk_ctl; /* 5 < corerev < 10 */ -+ uint32 PAD[1]; ++/* Another mp4306 with SiGe */ ++#define BCM94306P_BOARD 0x044c + -+ /* Instaclock registers (corerev >= 10) */ -+ uint32 system_clk_ctl; /* 0xc0 */ -+ uint32 clkstatestretch; -+ uint32 PAD[14]; ++/* CF-like 4317 modules */ ++#define BCM94317CF_BOARD 0x044d + -+ /* ExtBus control registers (corerev >= 3) */ -+ uint32 pcmcia_config; /* 0x100 */ -+ uint32 pcmcia_memwait; -+ uint32 pcmcia_attrwait; -+ uint32 pcmcia_iowait; -+ uint32 ide_config; -+ uint32 ide_memwait; -+ uint32 ide_attrwait; -+ uint32 ide_iowait; -+ uint32 prog_config; -+ uint32 prog_waitcount; -+ uint32 flash_config; -+ uint32 flash_waitcount; -+ uint32 PAD[116]; ++/* mp4303 */ ++#define BCM94303MP_BOARD 0x044e + -+ /* uarts */ -+ uint8 uart0data; /* 0x300 */ -+ uint8 uart0imr; -+ uint8 uart0fcr; -+ uint8 uart0lcr; -+ uint8 uart0mcr; -+ uint8 uart0lsr; -+ uint8 uart0msr; -+ uint8 uart0scratch; -+ uint8 PAD[248]; /* corerev >= 1 */ ++/* mpsgh4306 */ ++#define BCM94306MPSGH_BOARD 0x044f + -+ uint8 uart1data; /* 0x400 */ -+ uint8 uart1imr; -+ uint8 uart1fcr; -+ uint8 uart1lcr; -+ uint8 uart1mcr; -+ uint8 uart1lsr; -+ uint8 uart1msr; -+ uint8 uart1scratch; -+} chipcregs_t; ++/* BRCM 4306 w/ Front End Modules */ ++#define BCM94306MPM 0x0450 ++#define BCM94306MPL 0x0453 + -+#endif /* _LANGUAGE_ASSEMBLY */ ++/* 4712agr */ ++#define BCM94712AGR_BOARD 0x0451 + -+#define CC_CHIPID 0 -+#define CC_CAPABILITIES 4 -+#define CC_JTAGCMD 0x30 -+#define CC_JTAGIR 0x34 -+#define CC_JTAGDR 0x38 -+#define CC_JTAGCTRL 0x3c -+#define CC_WATCHDOG 0x80 -+#define CC_CLKC_N 0x90 -+#define CC_CLKC_M0 0x94 -+#define CC_CLKC_M1 0x98 -+#define CC_CLKC_M2 0x9c -+#define CC_CLKC_M3 0xa0 -+#define CC_CLKDIV 0xa4 -+#define CC_SYS_CLK_CTL 0xc0 -+#define CC_OTP 0x800 ++/* The real CF 4317 board */ ++#define CFI4317_BOARD 0x0452 + -+/* chipid */ -+#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ -+#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ -+#define CID_REV_SHIFT 16 /* Chip Revision shift */ -+#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ -+#define CID_PKG_SHIFT 20 /* Package Option shift */ -+#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ -+#define CID_CC_SHIFT 24 ++/* pcmcia 4303 */ ++#define PC4303_BOARD 0x0454 + -+/* capabilities */ -+#define CAP_UARTS_MASK 0x00000003 /* Number of uarts */ -+#define CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ -+#define CAP_UCLKSEL 0x00000018 /* UARTs clock select */ -+#define CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ -+#define CAP_UARTGPIO 0x00000020 /* UARTs own Gpio's 15:12 */ -+#define CAP_EXTBUS 0x00000040 /* External bus present */ -+#define CAP_FLASH_MASK 0x00000700 /* Type of flash */ -+#define CAP_PLL_MASK 0x00038000 /* Type of PLL */ -+#define CAP_PWR_CTL 0x00040000 /* Power control */ -+#define CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ -+#define CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ -+#define CAP_OTPSIZE_BASE 5 /* OTP Size base */ -+#define CAP_JTAGP 0x00400000 /* JTAG Master Present */ -+#define CAP_ROM 0x00800000 /* Internal boot rom active */ ++/* 5350K */ ++#define BCM95350K_BOARD 0x0455 + -+/* PLL type */ -+#define PLL_NONE 0x00000000 -+#define PLL_TYPE1 0x00010000 /* 48Mhz base, 3 dividers */ -+#define PLL_TYPE2 0x00020000 /* 48Mhz, 4 dividers */ -+#define PLL_TYPE3 0x00030000 /* 25Mhz, 2 dividers */ -+#define PLL_TYPE4 0x00008000 /* 48Mhz, 4 dividers */ -+#define PLL_TYPE5 0x00018000 /* 25Mhz, 4 dividers */ -+#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */ -+#define PLL_TYPE7 0x00038000 /* 25Mhz, 4 dividers */ ++/* 5350R */ ++#define BCM95350R_BOARD 0x0456 + -+/* corecontrol */ -+#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */ -+#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ ++/* 4306mplna */ ++#define BCM94306MPLNA_BOARD 0x0457 + -+/* Fields in the otpstatus register */ -+#define OTPS_PROGFAIL 0x80000000 -+#define OTPS_PROTECT 0x00000007 -+#define OTPS_HW_PROTECT 0x00000001 -+#define OTPS_SW_PROTECT 0x00000002 -+#define OTPS_CID_PROTECT 0x00000004 ++/* 4320 boards */ ++#define BU4320_BOARD 0x0458 ++#define BU4320S_BOARD 0x0459 ++#define BCM94320PH_BOARD 0x045a + -+/* Fields in the otpcontrol register */ -+#define OTPC_RECWAIT 0xff000000 -+#define OTPC_PROGWAIT 0x00ffff00 -+#define OTPC_PRW_SHIFT 8 -+#define OTPC_MAXFAIL 0x00000038 -+#define OTPC_VSEL 0x00000006 -+#define OTPC_SELVL 0x00000001 ++/* 4306mph */ ++#define BCM94306MPH_BOARD 0x045b + -+/* Fields in otpprog */ -+#define OTPP_COL_MASK 0x000000ff -+#define OTPP_ROW_MASK 0x0000ff00 -+#define OTPP_ROW_SHIFT 8 -+#define OTPP_READERR 0x10000000 -+#define OTPP_VALUE 0x20000000 -+#define OTPP_VALUE_SHIFT 29 -+#define OTPP_READ 0x40000000 -+#define OTPP_START 0x80000000 -+#define OTPP_BUSY 0x80000000 ++/* 4306pciv */ ++#define BCM94306PCIV_BOARD 0x045c + -+/* jtagcmd */ -+#define JCMD_START 0x80000000 -+#define JCMD_BUSY 0x80000000 -+#define JCMD_PAUSE 0x40000000 -+#define JCMD0_ACC_MASK 0x0000f000 -+#define JCMD0_ACC_IRDR 0x00000000 -+#define JCMD0_ACC_DR 0x00001000 -+#define JCMD0_ACC_IR 0x00002000 -+#define JCMD0_ACC_RESET 0x00003000 -+#define JCMD0_ACC_IRPDR 0x00004000 -+#define JCMD0_ACC_PDR 0x00005000 -+#define JCMD0_IRW_MASK 0x00000f00 -+#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */ -+#define JCMD_ACC_IRDR 0x00000000 -+#define JCMD_ACC_DR 0x00010000 -+#define JCMD_ACC_IR 0x00020000 -+#define JCMD_ACC_RESET 0x00030000 -+#define JCMD_ACC_IRPDR 0x00040000 -+#define JCMD_ACC_PDR 0x00050000 -+#define JCMD_IRW_MASK 0x00001f00 -+#define JCMD_IRW_SHIFT 8 -+#define JCMD_DRW_MASK 0x0000003f ++#define BU4712SD_BOARD 0x045d + -+/* jtagctrl */ -+#define JCTRL_FORCE_CLK 4 /* Force clock */ -+#define JCTRL_EXT_EN 2 /* Enable external targets */ -+#define JCTRL_EN 1 /* Enable Jtag master */ ++#define BCM94320PFLSH_BOARD 0x045e + -+/* Fields in clkdiv */ -+#define CLKD_SFLASH 0x0f000000 -+#define CLKD_SFLASH_SHIFT 24 -+#define CLKD_OTP 0x000f0000 -+#define CLKD_OTP_SHIFT 16 -+#define CLKD_JTAG 0x00000f00 -+#define CLKD_JTAG_SHIFT 8 -+#define CLKD_UART 0x000000ff ++#define BU4712L_BOARD 0x045f ++#define BCM94712LGR_BOARD 0x0460 ++#define BCM94320R_BOARD 0x0461 + -+/* intstatus/intmask */ -+#define CI_GPIO 0x00000001 /* gpio intr */ -+#define CI_EI 0x00000002 /* ro: ext intr pin (corerev >= 3) */ -+#define CI_WDRESET 0x80000000 /* watchdog reset occurred */ ++#define BU5352_BOARD 0x0462 + -+/* slow_clk_ctl */ -+#define SCC_SS_MASK 0x00000007 /* slow clock source mask */ -+#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */ -+#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */ -+#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */ -+#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ -+#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */ -+#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */ -+#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors PLL clock disable requests from core */ -+#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't disable crystal when appropriate */ -+#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ -+#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ -+#define SCC_CD_SHIFT 16 ++#define BCM94318MPGH_BOARD 0x0463 + -+/* system_clk_ctl */ -+#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */ -+#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */ -+#define SYCC_FP 0x00000004 /* ForcePLLOn */ -+#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */ -+#define SYCC_HR 0x00000010 /* Force HT */ -+#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4+divisor)) */ -+#define SYCC_CD_SHIFT 16 + -+/* gpiotimerval*/ -+#define GPIO_ONTIME_SHIFT 16 ++#define BCM95352GR_BOARD 0x0467 + -+/* clockcontrol_n */ -+#define CN_N1_MASK 0x3f /* n1 control */ -+#define CN_N2_MASK 0x3f00 /* n2 control */ -+#define CN_N2_SHIFT 8 -+#define CN_PLLC_MASK 0xf0000 /* pll control */ -+#define CN_PLLC_SHIFT 16 ++/* bcm95351agr */ ++#define BCM95351AGR_BOARD 0x0470 + -+/* clockcontrol_sb/pci/uart */ -+#define CC_M1_MASK 0x3f /* m1 control */ -+#define CC_M2_MASK 0x3f00 /* m2 control */ -+#define CC_M2_SHIFT 8 -+#define CC_M3_MASK 0x3f0000 /* m3 control */ -+#define CC_M3_SHIFT 16 -+#define CC_MC_MASK 0x1f000000 /* mux control */ -+#define CC_MC_SHIFT 24 ++/* # of GPIO pins */ ++#define GPIO_NUMPINS 16 + -+/* N3M Clock control magic field values */ -+#define CC_F6_2 0x02 /* A factor of 2 in */ -+#define CC_F6_3 0x03 /* 6-bit fields like */ -+#define CC_F6_4 0x05 /* N1, M1 or M3 */ -+#define CC_F6_5 0x09 -+#define CC_F6_6 0x11 -+#define CC_F6_7 0x21 ++#endif /* _BCMDEVS_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/bcmendian.h linux.dev/arch/mips/bcm947xx/include/bcmendian.h +--- linux.old/arch/mips/bcm947xx/include/bcmendian.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/bcmendian.h 2006-04-27 20:08:35.000000000 +0200 +@@ -0,0 +1,198 @@ ++/* ++ * local version of endian.h - byte order defines ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: bcmendian.h,v 1.1.1.10 2006/02/27 03:43:16 honor Exp $ ++*/ + -+#define CC_F5_BIAS 5 /* 5-bit fields get this added */ ++#ifndef _BCMENDIAN_H_ ++#define _BCMENDIAN_H_ + -+#define CC_MC_BYPASS 0x08 -+#define CC_MC_M1 0x04 -+#define CC_MC_M1M2 0x02 -+#define CC_MC_M1M2M3 0x01 -+#define CC_MC_M1M3 0x11 ++#include + -+/* Type 2 Clock control magic field values */ -+#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */ -+#define CC_T2M2_BIAS 3 /* m2 bias */ ++/* Byte swap a 16 bit value */ ++#define BCMSWAP16(val) \ ++ ((uint16)(\ ++ (((uint16)(val) & (uint16)0x00ffU) << 8) | \ ++ (((uint16)(val) & (uint16)0xff00U) >> 8))) + -+#define CC_T2MC_M1BYP 1 -+#define CC_T2MC_M2BYP 2 -+#define CC_T2MC_M3BYP 4 ++/* Byte swap a 32 bit value */ ++#define BCMSWAP32(val) \ ++ ((uint32)(\ ++ (((uint32)(val) & (uint32)0x000000ffUL) << 24) | \ ++ (((uint32)(val) & (uint32)0x0000ff00UL) << 8) | \ ++ (((uint32)(val) & (uint32)0x00ff0000UL) >> 8) | \ ++ (((uint32)(val) & (uint32)0xff000000UL) >> 24))) + -+/* Type 6 Clock control magic field values */ -+#define CC_T6_MMASK 1 /* bits of interest in m */ -+#define CC_T6_M0 120000000 /* sb clock for m = 0 */ -+#define CC_T6_M1 100000000 /* sb clock for m = 1 */ -+#define SB2MIPS_T6(sb) (2 * (sb)) ++/* 2 Byte swap a 32 bit value */ ++#define BCMSWAP32BY16(val) \ ++ ((uint32)(\ ++ (((uint32)(val) & (uint32)0x0000ffffUL) << 16) | \ ++ (((uint32)(val) & (uint32)0xffff0000UL) >> 16))) + -+/* Common clock base */ -+#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */ -+#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLL's */ + -+/* Clock control values for 200Mhz in 5350 */ -+#define CLKC_5350_N 0x0311 -+#define CLKC_5350_M 0x04020009 ++static INLINE uint16 ++bcmswap16(uint16 val) ++{ ++ return BCMSWAP16(val); ++} + -+/* Flash types in the chipcommon capabilities register */ -+#define FLASH_NONE 0x000 /* No flash */ -+#define SFLASH_ST 0x100 /* ST serial flash */ -+#define SFLASH_AT 0x200 /* Atmel serial flash */ -+#define PFLASH 0x700 /* Parallel flash */ ++static INLINE uint32 ++bcmswap32(uint32 val) ++{ ++ return BCMSWAP32(val); ++} + -+/* Bits in the config registers */ -+#define CC_CFG_EN 0x0001 /* Enable */ -+#define CC_CFG_EM_MASK 0x000e /* Extif Mode */ -+#define CC_CFG_EM_ASYNC 0x0002 /* Async/Parallel flash */ -+#define CC_CFG_EM_SYNC 0x0004 /* Synchronous */ -+#define CC_CFG_EM_PCMCIA 0x0008 /* PCMCIA */ -+#define CC_CFG_EM_IDE 0x000a /* IDE */ -+#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ -+#define CC_CFG_CD_MASK 0x0060 /* Sync: Clock divisor */ -+#define CC_CFG_CE 0x0080 /* Sync: Clock enable */ -+#define CC_CFG_SB 0x0100 /* Sync: Size/Bytestrobe */ ++static INLINE uint32 ++bcmswap32by16(uint32 val) ++{ ++ return BCMSWAP32BY16(val); ++} + -+/* Start/busy bit in flashcontrol */ -+#define SFLASH_START 0x80000000 -+#define SFLASH_BUSY SFLASH_START ++/* buf - start of buffer of shorts to swap */ ++/* len - byte length of buffer */ ++static INLINE void ++bcmswap16_buf(uint16 *buf, uint len) ++{ ++ len = len/2; + -+/* flashcontrol opcodes for ST flashes */ -+#define SFLASH_ST_WREN 0x0006 /* Write Enable */ -+#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */ -+#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */ -+#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */ -+#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */ -+#define SFLASH_ST_PP 0x0302 /* Page Program */ -+#define SFLASH_ST_SE 0x02d8 /* Sector Erase */ -+#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */ -+#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */ -+#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */ ++ while (len--) { ++ *buf = bcmswap16(*buf); ++ buf++; ++ } ++} + -+/* Status register bits for ST flashes */ -+#define SFLASH_ST_WIP 0x01 /* Write In Progress */ -+#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */ -+#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */ -+#define SFLASH_ST_BP_SHIFT 2 -+#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */ ++#ifndef hton16 ++#ifndef IL_BIGENDIAN ++#define HTON16(i) BCMSWAP16(i) ++#define hton16(i) bcmswap16(i) ++#define hton32(i) bcmswap32(i) ++#define ntoh16(i) bcmswap16(i) ++#define ntoh32(i) bcmswap32(i) ++#define ltoh16(i) (i) ++#define ltoh32(i) (i) ++#define htol16(i) (i) ++#define htol32(i) (i) ++#else ++#define HTON16(i) (i) ++#define hton16(i) (i) ++#define hton32(i) (i) ++#define ntoh16(i) (i) ++#define ntoh32(i) (i) ++#define ltoh16(i) bcmswap16(i) ++#define ltoh32(i) bcmswap32(i) ++#define htol16(i) bcmswap16(i) ++#define htol32(i) bcmswap32(i) ++#endif /* IL_BIGENDIAN */ ++#endif /* hton16 */ + -+/* flashcontrol opcodes for Atmel flashes */ -+#define SFLASH_AT_READ 0x07e8 -+#define SFLASH_AT_PAGE_READ 0x07d2 -+#define SFLASH_AT_BUF1_READ -+#define SFLASH_AT_BUF2_READ -+#define SFLASH_AT_STATUS 0x01d7 -+#define SFLASH_AT_BUF1_WRITE 0x0384 -+#define SFLASH_AT_BUF2_WRITE 0x0387 -+#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283 -+#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286 -+#define SFLASH_AT_BUF1_PROGRAM 0x0288 -+#define SFLASH_AT_BUF2_PROGRAM 0x0289 -+#define SFLASH_AT_PAGE_ERASE 0x0281 -+#define SFLASH_AT_BLOCK_ERASE 0x0250 -+#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382 -+#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385 -+#define SFLASH_AT_BUF1_LOAD 0x0253 -+#define SFLASH_AT_BUF2_LOAD 0x0255 -+#define SFLASH_AT_BUF1_COMPARE 0x0260 -+#define SFLASH_AT_BUF2_COMPARE 0x0261 -+#define SFLASH_AT_BUF1_REPROGRAM 0x0258 -+#define SFLASH_AT_BUF2_REPROGRAM 0x0259 ++#ifndef IL_BIGENDIAN ++#define ltoh16_buf(buf, i) ++#define htol16_buf(buf, i) ++#else ++#define ltoh16_buf(buf, i) bcmswap16_buf((uint16*)buf, i) ++#define htol16_buf(buf, i) bcmswap16_buf((uint16*)buf, i) ++#endif /* IL_BIGENDIAN */ + -+/* Status register bits for Atmel flashes */ -+#define SFLASH_AT_READY 0x80 -+#define SFLASH_AT_MISMATCH 0x40 -+#define SFLASH_AT_ID_MASK 0x38 -+#define SFLASH_AT_ID_SHIFT 3 ++/* ++* store 16-bit value to unaligned little endian byte array. ++*/ ++static INLINE void ++htol16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[0] = val&0xff; ++ bytes[1] = val>>8; ++} + -+/* OTP regions */ -+#define OTP_HW_REGION OTPS_HW_PROTECT -+#define OTP_SW_REGION OTPS_SW_PROTECT -+#define OTP_CID_REGION OTPS_CID_PROTECT ++/* ++* store 32-bit value to unaligned little endian byte array. ++*/ ++static INLINE void ++htol32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[0] = val&0xff; ++ bytes[1] = (val>>8)&0xff; ++ bytes[2] = (val>>16)&0xff; ++ bytes[3] = val>>24; ++} + -+/* OTP regions (Byte offsets from otp size) */ -+#define OTP_SWLIM_OFF (-8) -+#define OTP_CIDBASE_OFF 0 -+#define OTP_CIDLIM_OFF 8 ++/* ++* store 16-bit value to unaligned network(big) endian byte array. ++*/ ++static INLINE void ++hton16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[1] = val&0xff; ++ bytes[0] = val>>8; ++} + -+/* Predefined OTP words (Word offset from otp size) */ -+#define OTP_BOUNDARY_OFF (-4) -+#define OTP_HWSIGN_OFF (-3) -+#define OTP_SWSIGN_OFF (-2) -+#define OTP_CIDSIGN_OFF (-1) ++/* ++* store 32-bit value to unaligned network(big) endian byte array. ++*/ ++static INLINE void ++hton32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[3] = val&0xff; ++ bytes[2] = (val>>8)&0xff; ++ bytes[1] = (val>>16)&0xff; ++ bytes[0] = val>>24; ++} + -+#define OTP_CID_OFF 0 -+#define OTP_PKG_OFF 1 -+#define OTP_FID_OFF 2 -+#define OTP_RSV_OFF 3 -+#define OTP_LIM_OFF 4 ++/* ++* load 16-bit value from unaligned little endian byte array. ++*/ ++static INLINE uint16 ++ltoh16_ua(void *bytes) ++{ ++ return (((uint8*)bytes)[1]<<8)+((uint8 *)bytes)[0]; ++} + -+#define OTP_SIGNATURE 0x578a -+#define OTP_MAGIC 0x4e56 ++/* ++* load 32-bit value from unaligned little endian byte array. ++*/ ++static INLINE uint32 ++ltoh32_ua(void *bytes) ++{ ++ return (((uint8*)bytes)[3]<<24)+(((uint8*)bytes)[2]<<16)+ ++ (((uint8*)bytes)[1]<<8)+((uint8*)bytes)[0]; ++} + -+#endif /* _SBCHIPC_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbconfig.h linux.dev/arch/mips/bcm947xx/include/sbconfig.h ---- linux.old/arch/mips/bcm947xx/include/sbconfig.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbconfig.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,342 @@ +/* -+ * Broadcom SiliconBackplane hardware register definitions. ++* load 16-bit value from unaligned big(network) endian byte array. ++*/ ++static INLINE uint16 ++ntoh16_ua(void *bytes) ++{ ++ return (((uint8*)bytes)[0]<<8)+((uint8*)bytes)[1]; ++} ++ ++/* ++* load 32-bit value from unaligned big(network) endian byte array. ++*/ ++static INLINE uint32 ++ntoh32_ua(void *bytes) ++{ ++ return (((uint8*)bytes)[0]<<24)+(((uint8*)bytes)[1]<<16)+ ++ (((uint8*)bytes)[2]<<8)+((uint8*)bytes)[3]; ++} ++ ++#define ltoh_ua(ptr) (\ ++ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] : \ ++ (((uint8 *)ptr)[3]<<24)+(((uint8 *)ptr)[2]<<16)+(((uint8 *)ptr)[1]<<8)+((uint8 *)ptr)[0] \ ++) ++ ++#define ntoh_ua(ptr) (\ ++ sizeof(*(ptr)) == sizeof(uint8) ? *(uint8 *)ptr : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? (((uint8 *)ptr)[0]<<8)+((uint8 *)ptr)[1] : \ ++ (((uint8 *)ptr)[0]<<24)+(((uint8 *)ptr)[1]<<16)+(((uint8 *)ptr)[2]<<8)+((uint8 *)ptr)[3] \ ++) ++ ++#endif /* _BCMENDIAN_H_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/bcmnvram.h linux.dev/arch/mips/bcm947xx/include/bcmnvram.h +--- linux.old/arch/mips/bcm947xx/include/bcmnvram.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/bcmnvram.h 2006-04-27 23:29:18.000000000 +0200 +@@ -0,0 +1,159 @@ ++/* ++ * NVRAM variable manipulation + * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: bcmnvram.h,v 1.17 2006/03/02 12:33:44 honor Exp $ + */ + -+#ifndef _SBCONFIG_H -+#define _SBCONFIG_H ++#ifndef _bcmnvram_h_ ++#define _bcmnvram_h_ + -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif ++#ifndef _LANGUAGE_ASSEMBLY ++ ++#include ++#include ++ ++struct nvram_header { ++ uint32 magic; ++ uint32 len; ++ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ ++ uint32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ ++ uint32 config_ncdl; /* ncdl values for memc */ ++}; ++ ++struct nvram_tuple { ++ char *name; ++ char *value; ++ struct nvram_tuple *next; ++}; + +/* -+ * SiliconBackplane Address Map. -+ * All regions may not exist on all chips. ++ * Initialize NVRAM access. May be unnecessary or undefined on certain ++ * platforms. + */ -+#define SB_SDRAM_BASE 0x00000000 /* Physical SDRAM */ -+#define SB_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */ -+#define SB_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */ -+#define SB_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ -+#define SB_ENUM_BASE 0x18000000 /* Enumeration space base */ -+#define SB_ENUM_LIM 0x18010000 /* Enumeration space limit */ ++extern int nvram_init(void *sbh); + -+#define SB_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ -+#define SB_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ ++/* ++ * Disable NVRAM access. May be unnecessary or undefined on certain ++ * platforms. ++ */ ++extern void nvram_exit(void *sbh); + -+#define SB_EXTIF_BASE 0x1f000000 /* External Interface region base address */ -+#define SB_FLASH1 0x1fc00000 /* Flash Region 1 */ -+#define SB_FLASH1_SZ 0x00400000 /* Size of Flash Region 1 */ ++/* ++ * Get the value of an NVRAM variable. The pointer returned may be ++ * invalid after a set. ++ * @param name name of variable to get ++ * @return value of variable or NULL if undefined ++ */ ++extern char * nvram_get(const char *name); + -+#define SB_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */ -+#define SB_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */ -+#define SB_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */ -+#define SB_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */ -+#define SB_EUART (SB_EXTIF_BASE + 0x00800000) -+#define SB_LED (SB_EXTIF_BASE + 0x00900000) ++/* ++ * Read the reset GPIO value from the nvram and set the GPIO ++ * as input ++ */ ++extern int BCMINITFN(nvram_resetgpio_init)(void *sbh); ++extern int BCMINITFN(nvram_gpio_init)(const char *name, void *sbh); ++extern int BCMINITFN(nvram_gpio_set)(const char *name, void *sbh, int type); + ++/* ++ * Get the value of an NVRAM variable. ++ * @param name name of variable to get ++ * @return value of variable or NUL if undefined ++ */ ++#define nvram_safe_get(name) (nvram_get(name) ? : "") + -+/* enumeration space related defs */ -+#define SB_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ -+#define SB_MAXCORES ((SB_ENUM_LIM - SB_ENUM_BASE)/SB_CORE_SIZE) -+#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */ -+#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */ ++#define nvram_safe_unset(name) ({ \ ++ if(nvram_get(name)) \ ++ nvram_unset(name); \ ++}) + -+/* mips address */ -+#define SB_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */ ++#define nvram_safe_set(name, value) ({ \ ++ if(!nvram_get(name) || strcmp(nvram_get(name), value)) \ ++ nvram_set(name, value); \ ++}) + +/* -+ * Sonics Configuration Space Registers. ++ * Match an NVRAM variable. ++ * @param name name of variable to match ++ * @param match value to compare against value of variable ++ * @return TRUE if variable is defined and its value is string equal ++ * to match or FALSE otherwise + */ -+#define SBIPSFLAG 0x08 -+#define SBTPSFLAG 0x18 -+#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */ -+#define SBTMERRLOG 0x50 /* sonics >= 2.3 */ -+#define SBADMATCH3 0x60 -+#define SBADMATCH2 0x68 -+#define SBADMATCH1 0x70 -+#define SBIMSTATE 0x90 -+#define SBINTVEC 0x94 -+#define SBTMSTATELOW 0x98 -+#define SBTMSTATEHIGH 0x9c -+#define SBBWA0 0xa0 -+#define SBIMCONFIGLOW 0xa8 -+#define SBIMCONFIGHIGH 0xac -+#define SBADMATCH0 0xb0 -+#define SBTMCONFIGLOW 0xb8 -+#define SBTMCONFIGHIGH 0xbc -+#define SBBCONFIG 0xc0 -+#define SBBSTATE 0xc8 -+#define SBACTCNFG 0xd8 -+#define SBFLAGST 0xe8 -+#define SBIDLOW 0xf8 -+#define SBIDHIGH 0xfc ++static INLINE int ++nvram_match(char *name, char *match) { ++ const char *value = nvram_get(name); ++ return (value && !strcmp(value, match)); ++} + -+#ifndef _LANGUAGE_ASSEMBLY ++/* ++ * Inversely match an NVRAM variable. ++ * @param name name of variable to match ++ * @param match value to compare against value of variable ++ * @return TRUE if variable is defined and its value is not string ++ * equal to invmatch or FALSE otherwise ++ */ ++static INLINE int ++nvram_invmatch(char *name, char *invmatch) { ++ const char *value = nvram_get(name); ++ return (value && strcmp(value, invmatch)); ++} + -+typedef volatile struct _sbconfig { -+ uint32 PAD[2]; -+ uint32 sbipsflag; /* initiator port ocp slave flag */ -+ uint32 PAD[3]; -+ uint32 sbtpsflag; /* target port ocp slave flag */ -+ uint32 PAD[11]; -+ uint32 sbtmerrloga; /* (sonics >= 2.3) */ -+ uint32 PAD; -+ uint32 sbtmerrlog; /* (sonics >= 2.3) */ -+ uint32 PAD[3]; -+ uint32 sbadmatch3; /* address match3 */ -+ uint32 PAD; -+ uint32 sbadmatch2; /* address match2 */ -+ uint32 PAD; -+ uint32 sbadmatch1; /* address match1 */ -+ uint32 PAD[7]; -+ uint32 sbimstate; /* initiator agent state */ -+ uint32 sbintvec; /* interrupt mask */ -+ uint32 sbtmstatelow; /* target state */ -+ uint32 sbtmstatehigh; /* target state */ -+ uint32 sbbwa0; /* bandwidth allocation table0 */ -+ uint32 PAD; -+ uint32 sbimconfiglow; /* initiator configuration */ -+ uint32 sbimconfighigh; /* initiator configuration */ -+ uint32 sbadmatch0; /* address match0 */ -+ uint32 PAD; -+ uint32 sbtmconfiglow; /* target configuration */ -+ uint32 sbtmconfighigh; /* target configuration */ -+ uint32 sbbconfig; /* broadcast configuration */ -+ uint32 PAD; -+ uint32 sbbstate; /* broadcast state */ -+ uint32 PAD[3]; -+ uint32 sbactcnfg; /* activate configuration */ -+ uint32 PAD[3]; -+ uint32 sbflagst; /* current sbflags */ -+ uint32 PAD[3]; -+ uint32 sbidlow; /* identification */ -+ uint32 sbidhigh; /* identification */ -+} sbconfig_t; ++/* ++ * Set the value of an NVRAM variable. The name and value strings are ++ * copied into private storage. Pointers to previously set values ++ * may become invalid. The new value may be immediately ++ * retrieved but will not be permanently stored until a commit. ++ * @param name name of variable to set ++ * @param value value of variable ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_set(const char *name, const char *value); + -+#endif /* _LANGUAGE_ASSEMBLY */ ++/* ++ * Unset an NVRAM variable. Pointers to previously set values ++ * remain valid until a set. ++ * @param name name of variable to unset ++ * @return 0 on success and errno on failure ++ * NOTE: use nvram_commit to commit this change to flash. ++ */ ++extern int nvram_unset(const char *name); + -+/* sbipsflag */ -+#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */ -+#define SBIPS_INT1_SHIFT 0 -+#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */ -+#define SBIPS_INT2_SHIFT 8 -+#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */ -+#define SBIPS_INT3_SHIFT 16 -+#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */ -+#define SBIPS_INT4_SHIFT 24 ++/* ++ * Commit NVRAM variables to permanent storage. All pointers to values ++ * may be invalid after a commit. ++ * NVRAM values are undefined after a commit. ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_commit(void); + -+/* sbtpsflag */ -+#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */ -+#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */ ++/* ++ * Get all NVRAM variables (format name=value\0 ... \0\0). ++ * @param buf buffer to store variables ++ * @param count size of buffer in bytes ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_getall(char *buf, int count); + -+/* sbtmerrlog */ -+#define SBTMEL_CM 0x00000007 /* command */ -+#define SBTMEL_CI 0x0000ff00 /* connection id */ -+#define SBTMEL_EC 0x0f000000 /* error code */ -+#define SBTMEL_ME 0x80000000 /* multiple error */ ++extern int file2nvram(char *filename, char *varname); ++extern int nvram2file(char *varname, char *filename); + -+/* sbimstate */ -+#define SBIM_PC 0xf /* pipecount */ -+#define SBIM_AP_MASK 0x30 /* arbitration policy */ -+#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */ -+#define SBIM_AP_TS 0x10 /* use timesliaces only */ -+#define SBIM_AP_TK 0x20 /* use token only */ -+#define SBIM_AP_RSV 0x30 /* reserved */ -+#define SBIM_IBE 0x20000 /* inbanderror */ -+#define SBIM_TO 0x40000 /* timeout */ -+#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ -+#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ ++#endif /* _LANGUAGE_ASSEMBLY */ + -+/* sbtmstatelow */ -+#define SBTML_RESET 0x1 /* reset */ -+#define SBTML_REJ_MASK 0x6 /* reject */ -+#define SBTML_REJ_SHIFT 1 -+#define SBTML_CLK 0x10000 /* clock enable */ -+#define SBTML_FGC 0x20000 /* force gated clocks on */ -+#define SBTML_FL_MASK 0x3ffc0000 /* core-specific flags */ -+#define SBTML_PE 0x40000000 /* pme enable */ -+#define SBTML_BE 0x80000000 /* bist enable */ ++#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ ++#define NVRAM_CLEAR_MAGIC 0x0 ++#define NVRAM_INVALID_MAGIC 0xFFFFFFFF ++#define NVRAM_VERSION 1 ++#define NVRAM_HEADER_SIZE 20 ++#define NVRAM_SPACE 0x8000 + -+/* sbtmstatehigh */ -+#define SBTMH_SERR 0x1 /* serror */ -+#define SBTMH_INT 0x2 /* interrupt */ -+#define SBTMH_BUSY 0x4 /* busy */ -+#define SBTMH_TO 0x00000020 /* timeout (sonics >= 2.3) */ -+#define SBTMH_FL_MASK 0x1fff0000 /* core-specific flags */ -+#define SBTMH_DMA64 0x10000000 /* supports DMA with 64-bit addresses */ -+#define SBTMH_GCR 0x20000000 /* gated clock request */ -+#define SBTMH_BISTF 0x40000000 /* bist failed */ -+#define SBTMH_BISTD 0x80000000 /* bist done */ ++#define NVRAM_MAX_VALUE_LEN 255 ++#define NVRAM_MAX_PARAM_LEN 64 + ++#endif /* _bcmnvram_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/bcmsrom.h linux.dev/arch/mips/bcm947xx/include/bcmsrom.h +--- linux.old/arch/mips/bcm947xx/include/bcmsrom.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/bcmsrom.h 2006-04-27 20:27:33.000000000 +0200 +@@ -0,0 +1,108 @@ ++/* ++ * Misc useful routines to access NIC local SROM/OTP . ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: bcmsrom.h,v 1.1.1.13 2006/04/15 01:29:08 michael Exp $ ++ */ + -+/* sbbwa0 */ -+#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */ -+#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */ -+#define SBBWA_TAB1_SHIFT 16 ++#ifndef _bcmsrom_h_ ++#define _bcmsrom_h_ + -+/* sbimconfiglow */ -+#define SBIMCL_STO_MASK 0x7 /* service timeout */ -+#define SBIMCL_RTO_MASK 0x70 /* request timeout */ -+#define SBIMCL_RTO_SHIFT 4 -+#define SBIMCL_CID_MASK 0xff0000 /* connection id */ -+#define SBIMCL_CID_SHIFT 16 ++/* Maximum srom: 4 Kilobits == 512 bytes */ ++#define SROM_MAX 512 + -+/* sbimconfighigh */ -+#define SBIMCH_IEM_MASK 0xc /* inband error mode */ -+#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */ -+#define SBIMCH_TEM_SHIFT 4 -+#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */ -+#define SBIMCH_BEM_SHIFT 6 ++/* SROM Rev 4: Reallocate the software part of the srom to accomodate ++ * MIMO features. It assumes up to two PCIE functions and 440 bytes ++ * of useable srom i.e. the useable storage in chips with OTP that ++ * implements hardware redundancy. ++ */ + -+/* sbadmatch0 */ -+#define SBAM_TYPE_MASK 0x3 /* address type */ -+#define SBAM_AD64 0x4 /* reserved */ -+#define SBAM_ADINT0_MASK 0xf8 /* type0 size */ -+#define SBAM_ADINT0_SHIFT 3 -+#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */ -+#define SBAM_ADINT1_SHIFT 3 -+#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */ -+#define SBAM_ADINT2_SHIFT 3 -+#define SBAM_ADEN 0x400 /* enable */ -+#define SBAM_ADNEG 0x800 /* negative decode */ -+#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */ -+#define SBAM_BASE0_SHIFT 8 -+#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */ -+#define SBAM_BASE1_SHIFT 12 -+#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */ -+#define SBAM_BASE2_SHIFT 16 ++#define SROM4_WORDS 220 ++ ++#define SROM4_SIGN 32 ++#define SROM4_SIGNATURE 0x5372 ++ ++#define SROM4_BREV 33 ++ ++#define SROM4_BFL0 34 ++#define SROM4_BFL1 35 ++#define SROM4_BFL2 36 ++#define SROM4_BFL3 37 ++ ++#define SROM4_MACHI 38 ++#define SROM4_MACMID 39 ++#define SROM4_MACLO 40 ++ ++#define SROM4_CCODE 41 ++#define SROM4_REGREV 42 ++ ++#define SROM4_LEDBH10 43 ++#define SROM4_LEDBH32 44 ++ ++#define SROM4_LEDDC 45 ++ ++#define SROM4_AA 46 ++#define SROM4_AA2G_MASK 0x00ff ++#define SROM4_AA2G_SHIFT 0 ++#define SROM4_AA5G_MASK 0xff00 ++#define SROM4_AA5G_SHIFT 8 ++ ++#define SROM4_AG10 47 ++#define SROM4_AG32 48 ++ ++#define SROM4_TXPID2G 49 ++#define SROM4_TXPID5G 51 ++#define SROM4_TXPID5GL 53 ++#define SROM4_TXPID5GH 55 ++ ++/* Per-path fields */ ++#define MAX_PATH 4 ++#define SROM4_PATH0 64 ++#define SROM4_PATH1 87 ++#define SROM4_PATH2 110 ++#define SROM4_PATH3 133 ++ ++#define SROM4_2G_ITT_MAXP 0 ++#define SROM4_2G_PA 1 ++#define SROM4_5G_ITT_MAXP 5 ++#define SROM4_5GLH_MAXP 6 ++#define SROM4_5G_PA 7 ++#define SROM4_5GL_PA 11 ++#define SROM4_5GH_PA 15 ++ ++/* Fields in the ITT_MAXP and 5GLH_MAXP words */ ++#define B2G_MAXP_MASK 0xff ++#define B2G_ITT_SHIFT 8 ++#define B5G_MAXP_MASK 0xff ++#define B5G_ITT_SHIFT 8 ++#define B5GH_MAXP_MASK 0xff ++#define B5GL_MAXP_SHIFT 8 ++ ++/* All the miriad power offsets */ ++#define SROM4_2G_CCKPO 156 ++#define SROM4_2G_OFDMPO 157 ++#define SROM4_5G_OFDMPO 159 ++#define SROM4_5GL_OFDMPO 161 ++#define SROM4_5GH_OFDMPO 163 ++#define SROM4_2G_MCSPO 165 ++#define SROM4_5G_MCSPO 173 ++#define SROM4_5GL_MCSPO 181 ++#define SROM4_5GH_MCSPO 189 ++#define SROM4_CCDPO 197 ++#define SROM4_STBCPO 198 ++#define SROM4_BW40PO 199 ++#define SROM4_BWDUPPO 200 ++ ++extern int srom_var_init(void *sbh, uint bus, void *curmap, osl_t *osh, char **vars, uint *count); + -+/* sbtmconfiglow */ -+#define SBTMCL_CD_MASK 0xff /* clock divide */ -+#define SBTMCL_CO_MASK 0xf800 /* clock offset */ -+#define SBTMCL_CO_SHIFT 11 -+#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */ -+#define SBTMCL_IF_SHIFT 18 -+#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */ -+#define SBTMCL_IM_SHIFT 24 ++extern int srom_read(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf); ++extern int srom_write(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf); + -+/* sbtmconfighigh */ -+#define SBTMCH_BM_MASK 0x3 /* busy mode */ -+#define SBTMCH_RM_MASK 0x3 /* retry mode */ -+#define SBTMCH_RM_SHIFT 2 -+#define SBTMCH_SM_MASK 0x30 /* stop mode */ -+#define SBTMCH_SM_SHIFT 4 -+#define SBTMCH_EM_MASK 0x300 /* sb error mode */ -+#define SBTMCH_EM_SHIFT 8 -+#define SBTMCH_IM_MASK 0xc00 /* int mode */ -+#define SBTMCH_IM_SHIFT 10 ++#endif /* _bcmsrom_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/bcmutils.h linux.dev/arch/mips/bcm947xx/include/bcmutils.h +--- linux.old/arch/mips/bcm947xx/include/bcmutils.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/bcmutils.h 2006-05-02 01:52:12.000000000 +0200 +@@ -0,0 +1,433 @@ ++/* ++ * Misc useful os-independent macros and functions. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * $Id: bcmutils.h,v 1.1.1.16 2006/04/08 06:13:39 honor Exp $ ++ */ + -+/* sbbconfig */ -+#define SBBC_LAT_MASK 0x3 /* sb latency */ -+#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */ -+#define SBBC_MAX0_SHIFT 16 -+#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */ -+#define SBBC_MAX1_SHIFT 20 ++#ifndef _bcmutils_h_ ++#define _bcmutils_h_ + -+/* sbbstate */ -+#define SBBS_SRD 0x1 /* st reg disable */ -+#define SBBS_HRD 0x2 /* hold reg disable */ ++/* ** driver-only section ** */ ++#ifdef BCMDRIVER + -+/* sbidlow */ -+#define SBIDL_CS_MASK 0x3 /* config space */ -+#define SBIDL_AR_MASK 0x38 /* # address ranges supported */ -+#define SBIDL_AR_SHIFT 3 -+#define SBIDL_SYNCH 0x40 /* sync */ -+#define SBIDL_INIT 0x80 /* initiator */ -+#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */ -+#define SBIDL_MINLAT_SHIFT 8 -+#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */ -+#define SBIDL_MAXLAT_SHIFT 12 -+#define SBIDL_FIRST 0x10000 /* this initiator is first */ -+#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */ -+#define SBIDL_CW_SHIFT 18 -+#define SBIDL_TP_MASK 0xf00000 /* target ports */ -+#define SBIDL_TP_SHIFT 20 -+#define SBIDL_IP_MASK 0xf000000 /* initiator ports */ -+#define SBIDL_IP_SHIFT 24 -+#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */ -+#define SBIDL_RV_SHIFT 28 -+#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */ -+#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */ ++#define _BCM_U 0x01 /* upper */ ++#define _BCM_L 0x02 /* lower */ ++#define _BCM_D 0x04 /* digit */ ++#define _BCM_C 0x08 /* cntrl */ ++#define _BCM_P 0x10 /* punct */ ++#define _BCM_S 0x20 /* white space (space/lf/tab) */ ++#define _BCM_X 0x40 /* hex digit */ ++#define _BCM_SP 0x80 /* hard space (0x20) */ + -+/* sbidhigh */ -+#define SBIDH_RC_MASK 0x000f /* revision code */ -+#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ -+#define SBIDH_RCE_SHIFT 8 -+#define SBCOREREV(sbidh) \ -+ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) -+#define SBIDH_CC_MASK 0x8ff0 /* core code */ -+#define SBIDH_CC_SHIFT 4 -+#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ -+#define SBIDH_VC_SHIFT 16 ++#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ + -+#define SB_COMMIT 0xfd8 /* update buffered registers value */ ++extern unsigned char bcm_ctype[]; ++#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) + -+/* vendor codes */ -+#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */ ++#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) ++#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) ++#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) ++#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) ++#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) ++#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) ++#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) ++#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) ++#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) + -+/* core codes */ -+#define SB_CC 0x800 /* chipcommon core */ -+#define SB_ILINE20 0x801 /* iline20 core */ -+#define SB_SDRAM 0x803 /* sdram core */ -+#define SB_PCI 0x804 /* pci core */ -+#define SB_MIPS 0x805 /* mips core */ -+#define SB_ENET 0x806 /* enet mac core */ -+#define SB_CODEC 0x807 /* v90 codec core */ -+#define SB_USB 0x808 /* usb 1.1 host/device core */ -+#define SB_ADSL 0x809 /* ADSL core */ -+#define SB_ILINE100 0x80a /* iline100 core */ -+#define SB_IPSEC 0x80b /* ipsec core */ -+#define SB_PCMCIA 0x80d /* pcmcia core */ -+#define SB_SOCRAM 0x80e /* internal memory core */ -+#define SB_MEMC 0x80f /* memc sdram core */ -+#define SB_EXTIF 0x811 /* external interface core */ -+#define SB_D11 0x812 /* 802.11 MAC core */ -+#define SB_MIPS33 0x816 /* mips3302 core */ -+#define SB_USB11H 0x817 /* usb 1.1 host core */ -+#define SB_USB11D 0x818 /* usb 1.1 device core */ -+#define SB_USB20H 0x819 /* usb 2.0 host core */ -+#define SB_USB20D 0x81a /* usb 2.0 device core */ -+#define SB_SDIOH 0x81b /* sdio host core */ -+#define SB_ROBO 0x81c /* roboswitch core */ -+#define SB_ATA100 0x81d /* parallel ATA core */ -+#define SB_SATAXOR 0x81e /* serial ATA & XOR DMA core */ -+#define SB_GIGETH 0x81f /* gigabit ethernet core */ -+#define SB_PCIE 0x820 /* pci express core */ -+#define SB_SRAMC 0x822 /* SRAM controller core */ -+#define SB_MINIMAC 0x823 /* MINI MAC/phy core */ ++/* ++ * Spin at most 'us' microseconds while 'exp' is true. ++ * Caller should explicitly test 'exp' when this completes ++ * and take appropriate error action if 'exp' is still true. ++ */ ++#define SPINWAIT(exp, us) { \ ++ uint countdown = (us) + 9; \ ++ while ((exp) && (countdown >= 10)) {\ ++ OSL_DELAY(10); \ ++ countdown -= 10; \ ++ } \ ++} + -+#define SB_CC_IDX 0 /* chipc, when present, is always core 0 */ ++struct ether_addr { ++ uint8 octet[6]; ++} __attribute__((packed)); + -+/* Not really related to Silicon Backplane, but a couple of software -+ * conventions for the use the flash space: ++/* string */ ++extern uchar bcm_toupper(uchar c); ++extern ulong bcm_strtoul(char *cp, char **endp, uint base); ++extern char *bcmstrstr(char *haystack, char *needle); ++extern char *bcmstrcat(char *dest, const char *src); ++extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); ++/* ethernet address */ ++extern char *bcm_ether_ntoa(struct ether_addr *ea, char *buf); ++/* variable access */ ++extern char *getvar(char *vars, char *name); ++extern int getintvar(char *vars, char *name); ++extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); ++#ifdef BCMPERFSTATS ++extern void bcm_perf_enable(void); ++extern void bcmstats(char *fmt); ++extern void bcmlog(char *fmt, uint a1, uint a2); ++extern void bcmdumplog(char *buf, int size); ++extern int bcmdumplogent(char *buf, uint idx); ++#else ++#define bcm_perf_enable() ++#define bcmstats(fmt) ++#define bcmlog(fmt, a1, a2) ++#define bcmdumplog(buf, size) *buf = '\0' ++#define bcmdumplogent(buf, idx) -1 ++#endif /* BCMPERFSTATS */ ++extern char *bcm_nvram_vars(uint *length); ++extern int bcm_nvram_cache(void *sbh); ++ ++/* Support for sharing code across in-driver iovar implementations. ++ * The intent is that a driver use this structure to map iovar names ++ * to its (private) iovar identifiers, and the lookup function to ++ * find the entry. Macros are provided to map ids and get/set actions ++ * into a single number space for a switch statement. + */ + -+/* Minumum amount of flash we support */ -+#define FLASH_MIN 0x00020000 /* Minimum flash size */ -+ -+/* A boot/binary may have an embedded block that describes its size */ -+#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */ -+#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */ -+#define BISZ_MAGIC_IDX 0 /* Word 0: magic */ -+#define BISZ_TXTST_IDX 1 /* 1: text start */ -+#define BISZ_TXTEND_IDX 2 /* 2: text start */ -+#define BISZ_DATAST_IDX 3 /* 3: text start */ -+#define BISZ_DATAEND_IDX 4 /* 4: text start */ -+#define BISZ_BSSST_IDX 5 /* 5: text start */ -+#define BISZ_BSSEND_IDX 6 /* 6: text start */ -+#define BISZ_SIZE 7 /* descriptor size in 32-bit intergers */ ++/* iovar structure */ ++typedef struct bcm_iovar { ++ const char *name; /* name for lookup and display */ ++ uint16 varid; /* id for switch */ ++ uint16 flags; /* driver-specific flag bits */ ++ uint16 type; /* base type of argument */ ++ uint16 minlen; /* min length for buffer vars */ ++} bcm_iovar_t; ++ ++/* varid definitions are per-driver, may use these get/set bits */ ++ ++/* IOVar action bits for id mapping */ ++#define IOV_GET 0 /* Get an iovar */ ++#define IOV_SET 1 /* Set an iovar */ ++ ++/* Varid to actionid mapping */ ++#define IOV_GVAL(id) ((id)*2) ++#define IOV_SVAL(id) (((id)*2)+IOV_SET) ++#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) ++ ++/* flags are per-driver based on driver attributes */ ++ ++/* Base type definitions */ ++#define IOVT_VOID 0 /* no value (implictly set only) */ ++#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */ ++#define IOVT_INT8 2 /* integer values are range-checked */ ++#define IOVT_UINT8 3 /* unsigned int 8 bits */ ++#define IOVT_INT16 4 /* int 16 bits */ ++#define IOVT_UINT16 5 /* unsigned int 16 bits */ ++#define IOVT_INT32 6 /* int 32 bits */ ++#define IOVT_UINT32 7 /* unsigned int 32 bits */ ++#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */ ++ ++extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); ++extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); + -+#endif /* _SBCONFIG_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbextif.h linux.dev/arch/mips/bcm947xx/include/sbextif.h ---- linux.old/arch/mips/bcm947xx/include/sbextif.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbextif.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,242 @@ -+/* -+ * Hardware-specific External Interface I/O core definitions -+ * for the BCM47xx family of SiliconBackplane-based chips. -+ * -+ * The External Interface core supports a total of three external chip selects -+ * supporting external interfaces. One of the external chip selects is -+ * used for Flash, one is used for PCMCIA, and the other may be -+ * programmed to support either a synchronous interface or an -+ * asynchronous interface. The asynchronous interface can be used to -+ * support external devices such as UARTs and the BCM2019 Bluetooth -+ * baseband processor. -+ * The external interface core also contains 2 on-chip 16550 UARTs, clock -+ * frequency control, a watchdog interrupt timer, and a GPIO interface. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ ++#endif /* #ifdef BCMDRIVER */ + -+#ifndef _SBEXTIF_H -+#define _SBEXTIF_H ++/* ** driver/apps-shared section ** */ + -+/* external interface address space */ -+#define EXTIF_PCMCIA_MEMBASE(x) (x) -+#define EXTIF_PCMCIA_IOBASE(x) ((x) + 0x100000) -+#define EXTIF_PCMCIA_CFGBASE(x) ((x) + 0x200000) -+#define EXTIF_CFGIF_BASE(x) ((x) + 0x800000) -+#define EXTIF_FLASH_BASE(x) ((x) + 0xc00000) ++#define BCME_STRLEN 64 /* Max string length for BCM errors */ ++#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) + -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif /* PAD */ + +/* -+ * The multiple instances of output and output enable registers -+ * are present to allow driver software for multiple cores to control -+ * gpio outputs without needing to share a single register pair. -+ */ -+struct gpiouser { -+ uint32 out; -+ uint32 outen; -+}; -+#define NGPIOUSER 5 ++ * error codes could be added but the defined ones shouldn't be changed/deleted ++ * these error codes are exposed to the user code ++ * when ever a new error code is added to this list ++ * please update errorstring table with the related error string and ++ * update osl files with os specific errorcode map ++*/ + -+typedef volatile struct { -+ uint32 corecontrol; -+ uint32 extstatus; -+ uint32 PAD[2]; ++#define BCME_OK 0 /* Success */ ++#define BCME_ERROR -1 /* Error generic */ ++#define BCME_BADARG -2 /* Bad Argument */ ++#define BCME_BADOPTION -3 /* Bad option */ ++#define BCME_NOTUP -4 /* Not up */ ++#define BCME_NOTDOWN -5 /* Not down */ ++#define BCME_NOTAP -6 /* Not AP */ ++#define BCME_NOTSTA -7 /* Not STA */ ++#define BCME_BADKEYIDX -8 /* BAD Key Index */ ++#define BCME_RADIOOFF -9 /* Radio Off */ ++#define BCME_NOTBANDLOCKED -10 /* Not band locked */ ++#define BCME_NOCLK -11 /* No Clock */ ++#define BCME_BADRATESET -12 /* BAD Rate valueset */ ++#define BCME_BADBAND -13 /* BAD Band */ ++#define BCME_BUFTOOSHORT -14 /* Buffer too short */ ++#define BCME_BUFTOOLONG -15 /* Buffer too long */ ++#define BCME_BUSY -16 /* Busy */ ++#define BCME_NOTASSOCIATED -17 /* Not Associated */ ++#define BCME_BADSSIDLEN -18 /* Bad SSID len */ ++#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ ++#define BCME_BADCHAN -20 /* Bad Channel */ ++#define BCME_BADADDR -21 /* Bad Address */ ++#define BCME_NORESOURCE -22 /* Not Enough Resources */ ++#define BCME_UNSUPPORTED -23 /* Unsupported */ ++#define BCME_BADLEN -24 /* Bad length */ ++#define BCME_NOTREADY -25 /* Not Ready */ ++#define BCME_EPERM -26 /* Not Permitted */ ++#define BCME_NOMEM -27 /* No Memory */ ++#define BCME_ASSOCIATED -28 /* Associated */ ++#define BCME_RANGE -29 /* Not In Range */ ++#define BCME_NOTFOUND -30 /* Not Found */ ++#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ ++#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ ++#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ ++#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ ++#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ ++#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ ++#define BCME_LAST BCME_DONGLE_DOWN ++ ++/* These are collection of BCME Error strings */ ++#define BCMERRSTRINGTABLE { \ ++ "OK", \ ++ "Undefined error", \ ++ "Bad Argument", \ ++ "Bad Option", \ ++ "Not up", \ ++ "Not down", \ ++ "Not AP", \ ++ "Not STA", \ ++ "Bad Key Index", \ ++ "Radio Off", \ ++ "Not band locked", \ ++ "No clock", \ ++ "Bad Rate valueset", \ ++ "Bad Band", \ ++ "Buffer too short", \ ++ "Buffer too long", \ ++ "Busy", \ ++ "Not Associated", \ ++ "Bad SSID len", \ ++ "Out of Range Channel", \ ++ "Bad Channel", \ ++ "Bad Address", \ ++ "Not Enough Resources", \ ++ "Unsupported", \ ++ "Bad length", \ ++ "Not Ready", \ ++ "Not Permitted", \ ++ "No Memory", \ ++ "Associated", \ ++ "Not In Range", \ ++ "Not Found", \ ++ "WME Not Enabled", \ ++ "TSPEC Not Found", \ ++ "ACM Not Supported", \ ++ "Not WME Association", \ ++ "SDIO Bus Error", \ ++ "Dongle Not Accessible" \ ++} + -+ /* pcmcia control registers */ -+ uint32 pcmcia_config; -+ uint32 pcmcia_memwait; -+ uint32 pcmcia_attrwait; -+ uint32 pcmcia_iowait; ++#ifndef ABS ++#define ABS(a) (((a) < 0)?-(a):(a)) ++#endif /* ABS */ + -+ /* programmable interface control registers */ -+ uint32 prog_config; -+ uint32 prog_waitcount; ++#ifndef MIN ++#define MIN(a, b) (((a) < (b))?(a):(b)) ++#endif /* MIN */ + -+ /* flash control registers */ -+ uint32 flash_config; -+ uint32 flash_waitcount; -+ uint32 PAD[4]; ++#ifndef MAX ++#define MAX(a, b) (((a) > (b))?(a):(b)) ++#endif /* MAX */ + -+ uint32 watchdog; ++#define CEIL(x, y) (((x) + ((y)-1)) / (y)) ++#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) ++#define ISALIGNED(a, x) (((a) & ((x)-1)) == 0) ++#define ISPOWEROF2(x) ((((x)-1)&(x)) == 0) ++#define VALID_MASK(mask) !((mask) & ((mask) + 1)) ++#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) ++#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) + -+ /* clock control */ -+ uint32 clockcontrol_n; -+ uint32 clockcontrol_sb; -+ uint32 clockcontrol_pci; -+ uint32 clockcontrol_mii; -+ uint32 PAD[3]; ++/* bit map related macros */ ++#ifndef setbit ++#ifndef NBBY /* the BSD family defines NBBY */ ++#define NBBY 8 /* 8 bits per byte */ ++#endif /* #ifndef NBBY */ ++#define setbit(a, i) (((uint8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY)) ++#define clrbit(a, i) (((uint8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) ++#define isset(a, i) (((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) ++#define isclr(a, i) ((((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) ++#endif /* setbit */ + -+ /* gpio */ -+ uint32 gpioin; -+ struct gpiouser gpio[NGPIOUSER]; -+ uint32 PAD; -+ uint32 ejtagouten; -+ uint32 gpiointpolarity; -+ uint32 gpiointmask; -+ uint32 PAD[153]; ++#define NBITS(type) (sizeof(type) * 8) ++#define NBITVAL(nbits) (1 << (nbits)) ++#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) ++#define NBITMASK(nbits) MAXBITVAL(nbits) ++#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) + -+ uint8 uartdata; -+ uint8 PAD[3]; -+ uint8 uartimer; -+ uint8 PAD[3]; -+ uint8 uartfcr; -+ uint8 PAD[3]; -+ uint8 uartlcr; -+ uint8 PAD[3]; -+ uint8 uartmcr; -+ uint8 PAD[3]; -+ uint8 uartlsr; -+ uint8 PAD[3]; -+ uint8 uartmsr; -+ uint8 PAD[3]; -+ uint8 uartscratch; -+ uint8 PAD[3]; -+} extifregs_t; ++/* basic mux operation - can be optimized on several architectures */ ++#define MUX(pred, true, false) ((pred) ? (true) : (false)) + -+/* corecontrol */ -+#define CC_UE (1 << 0) /* uart enable */ ++/* modulo inc/dec - assumes x E [0, bound - 1] */ ++#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) ++#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) + -+/* extstatus */ -+#define ES_EM (1 << 0) /* endian mode (ro) */ -+#define ES_EI (1 << 1) /* external interrupt pin (ro) */ -+#define ES_GI (1 << 2) /* gpio interrupt pin (ro) */ ++/* modulo inc/dec, bound = 2^k */ ++#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) ++#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) + -+/* gpio bit mask */ -+#define GPIO_BIT0 (1 << 0) -+#define GPIO_BIT1 (1 << 1) -+#define GPIO_BIT2 (1 << 2) -+#define GPIO_BIT3 (1 << 3) -+#define GPIO_BIT4 (1 << 4) -+#define GPIO_BIT5 (1 << 5) -+#define GPIO_BIT6 (1 << 6) -+#define GPIO_BIT7 (1 << 7) ++/* modulo add/sub - assumes x, y E [0, bound - 1] */ ++#define MODADD(x, y, bound) \ ++ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) ++#define MODSUB(x, y, bound) \ ++ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) + ++/* module add/sub, bound = 2^k */ ++#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) ++#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) + -+/* pcmcia/prog/flash_config */ -+#define CF_EN (1 << 0) /* enable */ -+#define CF_EM_MASK 0xe /* mode */ -+#define CF_EM_SHIFT 1 -+#define CF_EM_FLASH 0x0 /* flash/asynchronous mode */ -+#define CF_EM_SYNC 0x2 /* synchronous mode */ -+#define CF_EM_PCMCIA 0x4 /* pcmcia mode */ -+#define CF_DS (1 << 4) /* destsize: 0=8bit, 1=16bit */ -+#define CF_BS (1 << 5) /* byteswap */ -+#define CF_CD_MASK 0xc0 /* clock divider */ -+#define CF_CD_SHIFT 6 -+#define CF_CD_DIV2 0x0 /* backplane/2 */ -+#define CF_CD_DIV3 0x40 /* backplane/3 */ -+#define CF_CD_DIV4 0x80 /* backplane/4 */ -+#define CF_CE (1 << 8) /* clock enable */ -+#define CF_SB (1 << 9) /* size/bytestrobe (synch only) */ ++/* crc defines */ ++#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ ++#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ ++#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ ++#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ ++#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ ++#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ + -+/* pcmcia_memwait */ -+#define PM_W0_MASK 0x3f /* waitcount0 */ -+#define PM_W1_MASK 0x1f00 /* waitcount1 */ -+#define PM_W1_SHIFT 8 -+#define PM_W2_MASK 0x1f0000 /* waitcount2 */ -+#define PM_W2_SHIFT 16 -+#define PM_W3_MASK 0x1f000000 /* waitcount3 */ -+#define PM_W3_SHIFT 24 ++/* bcm_format_flags() bit description structure */ ++typedef struct bcm_bit_desc { ++ uint32 bit; ++ char* name; ++} bcm_bit_desc_t; + -+/* pcmcia_attrwait */ -+#define PA_W0_MASK 0x3f /* waitcount0 */ -+#define PA_W1_MASK 0x1f00 /* waitcount1 */ -+#define PA_W1_SHIFT 8 -+#define PA_W2_MASK 0x1f0000 /* waitcount2 */ -+#define PA_W2_SHIFT 16 -+#define PA_W3_MASK 0x1f000000 /* waitcount3 */ -+#define PA_W3_SHIFT 24 ++/* tag_ID/length/value_buffer tuple */ ++typedef struct bcm_tlv { ++ uint8 id; ++ uint8 len; ++ uint8 data[1]; ++} bcm_tlv_t; + -+/* pcmcia_iowait */ -+#define PI_W0_MASK 0x3f /* waitcount0 */ -+#define PI_W1_MASK 0x1f00 /* waitcount1 */ -+#define PI_W1_SHIFT 8 -+#define PI_W2_MASK 0x1f0000 /* waitcount2 */ -+#define PI_W2_SHIFT 16 -+#define PI_W3_MASK 0x1f000000 /* waitcount3 */ -+#define PI_W3_SHIFT 24 ++/* Check that bcm_tlv_t fits into the given buflen */ ++#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) + -+/* prog_waitcount */ -+#define PW_W0_MASK 0x0000001f /* waitcount0 */ -+#define PW_W1_MASK 0x00001f00 /* waitcount1 */ -+#define PW_W1_SHIFT 8 -+#define PW_W2_MASK 0x001f0000 /* waitcount2 */ -+#define PW_W2_SHIFT 16 -+#define PW_W3_MASK 0x1f000000 /* waitcount3 */ -+#define PW_W3_SHIFT 24 ++/* buffer length for ethernet address from bcm_ether_ntoa() */ ++#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ + -+#define PW_W0 0x0000000c -+#define PW_W1 0x00000a00 -+#define PW_W2 0x00020000 -+#define PW_W3 0x01000000 ++/* unaligned load and store macros */ ++#ifdef IL_BIGENDIAN ++static INLINE uint32 ++load32_ua(uint8 *a) ++{ ++ return ((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]); ++} + -+/* flash_waitcount */ -+#define FW_W0_MASK 0x1f /* waitcount0 */ -+#define FW_W1_MASK 0x1f00 /* waitcount1 */ -+#define FW_W1_SHIFT 8 -+#define FW_W2_MASK 0x1f0000 /* waitcount2 */ -+#define FW_W2_SHIFT 16 -+#define FW_W3_MASK 0x1f000000 /* waitcount3 */ -+#define FW_W3_SHIFT 24 ++static INLINE void ++store32_ua(uint8 *a, uint32 v) ++{ ++ a[0] = (v >> 24) & 0xff; ++ a[1] = (v >> 16) & 0xff; ++ a[2] = (v >> 8) & 0xff; ++ a[3] = v & 0xff; ++} + -+/* watchdog */ -+#define WATCHDOG_CLOCK 48000000 /* Hz */ ++static INLINE uint16 ++load16_ua(uint8 *a) ++{ ++ return ((a[0] << 8) | a[1]); ++} + -+/* clockcontrol_n */ -+#define CN_N1_MASK 0x3f /* n1 control */ -+#define CN_N2_MASK 0x3f00 /* n2 control */ -+#define CN_N2_SHIFT 8 ++static INLINE void ++store16_ua(uint8 *a, uint16 v) ++{ ++ a[0] = (v >> 8) & 0xff; ++ a[1] = v & 0xff; ++} + -+/* clockcontrol_sb/pci/mii */ -+#define CC_M1_MASK 0x3f /* m1 control */ -+#define CC_M2_MASK 0x3f00 /* m2 control */ -+#define CC_M2_SHIFT 8 -+#define CC_M3_MASK 0x3f0000 /* m3 control */ -+#define CC_M3_SHIFT 16 -+#define CC_MC_MASK 0x1f000000 /* mux control */ -+#define CC_MC_SHIFT 24 ++#else + -+/* Clock control default values */ -+#define CC_DEF_N 0x0009 /* Default values for bcm4710 */ -+#define CC_DEF_100 0x04020011 -+#define CC_DEF_33 0x11030011 -+#define CC_DEF_25 0x11050011 ++static INLINE uint32 ++load32_ua(uint8 *a) ++{ ++ return ((a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]); ++} + -+/* Clock control values for 125Mhz */ -+#define CC_125_N 0x0802 -+#define CC_125_M 0x04020009 -+#define CC_125_M25 0x11090009 -+#define CC_125_M33 0x11090005 ++static INLINE void ++store32_ua(uint8 *a, uint32 v) ++{ ++ a[3] = (v >> 24) & 0xff; ++ a[2] = (v >> 16) & 0xff; ++ a[1] = (v >> 8) & 0xff; ++ a[0] = v & 0xff; ++} + -+/* Clock control magic field values */ -+#define CC_F6_2 0x02 /* A factor of 2 in */ -+#define CC_F6_3 0x03 /* 6-bit fields like */ -+#define CC_F6_4 0x05 /* N1, M1 or M3 */ -+#define CC_F6_5 0x09 -+#define CC_F6_6 0x11 -+#define CC_F6_7 0x21 ++static INLINE uint16 ++load16_ua(uint8 *a) ++{ ++ return ((a[1] << 8) | a[0]); ++} + -+#define CC_F5_BIAS 5 /* 5-bit fields get this added */ ++static INLINE void ++store16_ua(uint8 *a, uint16 v) ++{ ++ a[1] = (v >> 8) & 0xff; ++ a[0] = v & 0xff; ++} + -+#define CC_MC_BYPASS 0x08 -+#define CC_MC_M1 0x04 -+#define CC_MC_M1M2 0x02 -+#define CC_MC_M1M2M3 0x01 -+#define CC_MC_M1M3 0x11 ++#endif /* IL_BIGENDIAN */ + -+#define CC_CLOCK_BASE 24000000 /* Half the clock freq. in the 4710 */ ++/* externs */ ++/* crc */ ++extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc); ++extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc); ++extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc); ++/* format/print */ ++extern void printfbig(char *buf); + -+#endif /* _SBEXTIF_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbmemc.h linux.dev/arch/mips/bcm947xx/include/sbmemc.h ---- linux.old/arch/mips/bcm947xx/include/sbmemc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbmemc.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,148 @@ ++/* IE parsing */ ++extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen); ++extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); ++extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key); ++ ++/* bcmerror */ ++extern const char *bcmerrorstr(int bcmerror); ++ ++/* multi-bool data type: set of bools, mbool is true if any is set */ ++typedef uint32 mbool; ++#define mboolset(mb, bit) (mb |= bit) /* set one bool */ ++#define mboolclr(mb, bit) (mb &= ~bit) /* clear one bool */ ++#define mboolisset(mb, bit) ((mb & bit) != 0) /* TRUE if one bool is set */ ++#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) ++ ++/* power conversion */ ++extern uint16 bcm_qdbm_to_mw(uint8 qdbm); ++extern uint8 bcm_mw_to_qdbm(uint16 mw); ++ ++/* generic datastruct to help dump routines */ ++struct fielddesc { ++ char *nameandfmt; ++ uint32 offset; ++ uint32 len; ++}; ++ ++/* Buffer structure for collecting string-formatted data ++* using bcm_bprintf() API. ++* Use bcm_binit() to initialize before use ++*/ ++struct bcmstrbuf ++{ ++ char *buf; /* pointer to current position in origbuf */ ++ uint size; /* current (residual) size in bytes */ ++ char *origbuf; /* unmodified pointer to orignal buffer */ ++ uint origsize; /* unmodified orignal buffer size in bytes */ ++}; ++ ++extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); ++extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); ++ ++typedef uint32 (*readreg_rtn)(void *arg0, void *arg1, uint32 offset); ++extern uint bcmdumpfields(readreg_rtn func_ptr, void *arg0, void *arg1, struct fielddesc *str, ++ char *buf, uint32 bufsize); ++ ++extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); ++extern uint bcm_bitcount(uint8 *bitmap, uint bytelength); ++ ++#endif /* _bcmutils_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/hndcpu.h linux.dev/arch/mips/bcm947xx/include/hndcpu.h +--- linux.old/arch/mips/bcm947xx/include/hndcpu.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/hndcpu.h 2006-04-27 22:14:38.000000000 +0200 +@@ -0,0 +1,28 @@ +/* -+ * BCM47XX Sonics SiliconBackplane DDR/SDRAM controller core hardware definitions. ++ * HND SiliconBackplane MIPS/ARM cores software interface. + * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * $Id$ ++ * $Id: hndcpu.h,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ + */ + -+#ifndef _SBMEMC_H -+#define _SBMEMC_H ++#ifndef _hndcpu_h_ ++#define _hndcpu_h_ + -+#ifdef _LANGUAGE_ASSEMBLY ++#if defined(mips) ++#include ++#elif defined(__ARM_ARCH_4T__) ++#include ++#endif + -+#define MEMC_CONTROL 0x00 -+#define MEMC_CONFIG 0x04 -+#define MEMC_REFRESH 0x08 -+#define MEMC_BISTSTAT 0x0c -+#define MEMC_MODEBUF 0x10 -+#define MEMC_BKCLS 0x14 -+#define MEMC_PRIORINV 0x18 -+#define MEMC_DRAMTIM 0x1c -+#define MEMC_INTSTAT 0x20 -+#define MEMC_INTMASK 0x24 -+#define MEMC_INTINFO 0x28 -+#define MEMC_NCDLCTL 0x30 -+#define MEMC_RDNCDLCOR 0x34 -+#define MEMC_WRNCDLCOR 0x38 -+#define MEMC_MISCDLYCTL 0x3c -+#define MEMC_DQSGATENCDL 0x40 -+#define MEMC_SPARE 0x44 -+#define MEMC_TPADDR 0x48 -+#define MEMC_TPDATA 0x4c -+#define MEMC_BARRIER 0x50 -+#define MEMC_CORE 0x54 ++extern uint sb_irq(sb_t *sbh); ++extern uint32 sb_cpu_clock(sb_t *sbh); ++extern void sb_cpu_wait(void); + ++#endif /* _hndcpu_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/hndmips.h linux.dev/arch/mips/bcm947xx/include/hndmips.h +--- linux.old/arch/mips/bcm947xx/include/hndmips.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/hndmips.h 2006-04-27 20:43:42.000000000 +0200 +@@ -0,0 +1,45 @@ ++/* ++ * HND SiliconBackplane MIPS core software interface. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: hndmips.h,v 1.1.1.8 2006/02/27 03:43:16 honor Exp $ ++ */ + -+#else -+ -+/* Sonics side: MEMC core registers */ -+typedef volatile struct sbmemcregs { -+ uint32 control; -+ uint32 config; -+ uint32 refresh; -+ uint32 biststat; -+ uint32 modebuf; -+ uint32 bkcls; -+ uint32 priorinv; -+ uint32 dramtim; -+ uint32 intstat; -+ uint32 intmask; -+ uint32 intinfo; -+ uint32 reserved1; -+ uint32 ncdlctl; -+ uint32 rdncdlcor; -+ uint32 wrncdlcor; -+ uint32 miscdlyctl; -+ uint32 dqsgatencdl; -+ uint32 spare; -+ uint32 tpaddr; -+ uint32 tpdata; -+ uint32 barrier; -+ uint32 core; -+} sbmemcregs_t; -+ -+#endif -+ -+/* MEMC Core Init values (OCP ID 0x80f) */ -+ -+/* For sdr: */ -+#define MEMC_SD_CONFIG_INIT 0x00048000 -+#define MEMC_SD_DRAMTIM2_INIT 0x000754d8 -+#define MEMC_SD_DRAMTIM3_INIT 0x000754da -+#define MEMC_SD_RDNCDLCOR_INIT 0x00000000 -+#define MEMC_SD_WRNCDLCOR_INIT 0x49351200 -+#define MEMC_SD1_WRNCDLCOR_INIT 0x14500200 /* For corerev 1 (4712) */ -+#define MEMC_SD_MISCDLYCTL_INIT 0x00061c1b -+#define MEMC_SD1_MISCDLYCTL_INIT 0x00021416 /* For corerev 1 (4712) */ -+#define MEMC_SD_CONTROL_INIT0 0x00000002 -+#define MEMC_SD_CONTROL_INIT1 0x00000008 -+#define MEMC_SD_CONTROL_INIT2 0x00000004 -+#define MEMC_SD_CONTROL_INIT3 0x00000010 -+#define MEMC_SD_CONTROL_INIT4 0x00000001 -+#define MEMC_SD_MODEBUF_INIT 0x00000000 -+#define MEMC_SD_REFRESH_INIT 0x0000840f -+ -+ -+/* This is for SDRM8X8X4 */ -+#define MEMC_SDR_INIT 0x0008 -+#define MEMC_SDR_MODE 0x32 -+#define MEMC_SDR_NCDL 0x00020032 -+#define MEMC_SDR1_NCDL 0x0002020f /* For corerev 1 (4712) */ -+ -+/* For ddr: */ -+#define MEMC_CONFIG_INIT 0x00048000 -+#define MEMC_DRAMTIM2_INIT 0x000754d8 -+#define MEMC_DRAMTIM25_INIT 0x000754d9 -+#define MEMC_RDNCDLCOR_INIT 0x00000000 -+#define MEMC_RDNCDLCOR_SIMINIT 0xf6f6f6f6 /* For hdl sim */ -+#define MEMC_WRNCDLCOR_INIT 0x49351200 -+#define MEMC_1_WRNCDLCOR_INIT 0x14500200 -+#define MEMC_DQSGATENCDL_INIT 0x00030000 -+#define MEMC_MISCDLYCTL_INIT 0x21061c1b -+#define MEMC_1_MISCDLYCTL_INIT 0x21021400 -+#define MEMC_NCDLCTL_INIT 0x00002001 -+#define MEMC_CONTROL_INIT0 0x00000002 -+#define MEMC_CONTROL_INIT1 0x00000008 -+#define MEMC_MODEBUF_INIT0 0x00004000 -+#define MEMC_CONTROL_INIT2 0x00000010 -+#define MEMC_MODEBUF_INIT1 0x00000100 -+#define MEMC_CONTROL_INIT3 0x00000010 -+#define MEMC_CONTROL_INIT4 0x00000008 -+#define MEMC_REFRESH_INIT 0x0000840f -+#define MEMC_CONTROL_INIT5 0x00000004 -+#define MEMC_MODEBUF_INIT2 0x00000000 -+#define MEMC_CONTROL_INIT6 0x00000010 -+#define MEMC_CONTROL_INIT7 0x00000001 -+ -+ -+/* This is for DDRM16X16X2 */ -+#define MEMC_DDR_INIT 0x0009 -+#define MEMC_DDR_MODE 0x62 -+#define MEMC_DDR_NCDL 0x0005050a -+#define MEMC_DDR1_NCDL 0x00000a0a /* For corerev 1 (4712) */ -+ -+/* mask for sdr/ddr calibration registers */ -+#define MEMC_RDNCDLCOR_RD_MASK 0x000000ff -+#define MEMC_WRNCDLCOR_WR_MASK 0x000000ff -+#define MEMC_DQSGATENCDL_G_MASK 0x000000ff -+ -+/* masks for miscdlyctl registers */ -+#define MEMC_MISC_SM_MASK 0x30000000 -+#define MEMC_MISC_SM_SHIFT 28 -+#define MEMC_MISC_SD_MASK 0x0f000000 -+#define MEMC_MISC_SD_SHIFT 24 -+ -+/* hw threshhold for calculating wr/rd for sdr memc */ -+#define MEMC_CD_THRESHOLD 128 ++#ifndef _hndmips_h_ ++#define _hndmips_h_ ++ ++extern void sb_mips_init(sb_t *sbh, uint shirq_map_base); ++extern bool sb_mips_setclock(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock); ++extern void enable_pfc(uint32 mode); ++extern uint32 sb_memc_get_ncdl(sb_t *sbh); ++ ++#if defined(BCMPERFSTATS) ++/* enable counting - exclusive version. Only one set of counters allowed at a time */ ++extern void hndmips_perf_instrcount_enable(void); ++extern void hndmips_perf_icachecount_enable(void); ++extern void hndmips_perf_dcachecount_enable(void); ++/* start and stop counting */ ++#define hndmips_perf_start01() \ ++ MTC0(C0_PERFORMANCE, 4, MFC0(C0_PERFORMANCE, 4) | 0x80008000) ++#define hndmips_perf_stop01() \ ++ MTC0(C0_PERFORMANCE, 4, MFC0(C0_PERFORMANCE, 4) & ~0x80008000) ++/* retrieve coutners - counters *decrement* */ ++#define hndmips_perf_read0() -(long)(MFC0(C0_PERFORMANCE, 0)) ++#define hndmips_perf_read1() -(long)(MFC0(C0_PERFORMANCE, 1)) ++#define hndmips_perf_read2() -(long)(MFC0(C0_PERFORMANCE, 2)) ++/* enable counting - modular version. Each counters can be enabled separately. */ ++extern void hndmips_perf_icache_hit_enable(void); ++extern void hndmips_perf_icache_miss_enable(void); ++extern uint32 hndmips_perf_read_instrcount(void); ++extern uint32 hndmips_perf_read_cache_miss(void); ++extern uint32 hndmips_perf_read_cache_hit(void); ++#endif /* defined(BCMINTERNAL) || defined (BCMPERFSTATS) */ ++ ++#endif /* _hndmips_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/hndpci.h linux.dev/arch/mips/bcm947xx/include/hndpci.h +--- linux.old/arch/mips/bcm947xx/include/hndpci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/hndpci.h 2006-04-27 20:36:48.000000000 +0200 +@@ -0,0 +1,30 @@ ++/* ++ * HND SiliconBackplane PCI core software interface. ++ * ++ * $Id: hndpci.h,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ */ + -+/* Low bit of init register says if memc is ddr or sdr */ -+#define MEMC_CONFIG_DDR 0x00000001 ++#ifndef _hndpci_h_ ++#define _hndpci_h_ ++ ++extern int sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, ++ int len); ++extern int extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, ++ int len); ++extern int sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, ++ int len); ++extern int extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, ++ int len); ++extern void sbpci_ban(uint16 core); ++extern int sbpci_init(sb_t *sbh); ++extern int sbpci_init_pci(sb_t *sbh); ++extern void sbpci_check(sb_t *sbh); + -+#endif /* _SBMEMC_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbmips.h linux.dev/arch/mips/bcm947xx/include/sbmips.h ---- linux.old/arch/mips/bcm947xx/include/sbmips.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbmips.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,62 @@ ++#endif /* _hndpci_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/linuxver.h linux.dev/arch/mips/bcm947xx/include/linuxver.h +--- linux.old/arch/mips/bcm947xx/include/linuxver.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/linuxver.h 2006-04-27 20:10:08.000000000 +0200 +@@ -0,0 +1,417 @@ +/* -+ * Broadcom SiliconBackplane MIPS definitions -+ * -+ * SB MIPS cores are custom MIPS32 processors with SiliconBackplane -+ * OCP interfaces. The CP0 processor ID is 0x00024000, where bits -+ * 23:16 mean Broadcom and bits 15:8 mean a MIPS core with an OCP -+ * interface. The core revision is stored in the SB ID register in SB -+ * configuration space. ++ * Linux-specific abstractions to gain some independence from linux kernel versions. ++ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. + * -+ * Copyright 2005, Broadcom Corporation ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -4783,1533 +4409,1651 @@ diff -Naur linux.old/arch/mips/bcm947xx/include/sbmips.h linux.dev/arch/mips/bcm + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * $Id$ ++ * $Id: linuxver.h,v 1.1.1.10 2006/02/27 03:43:16 honor Exp $ + */ + -+#ifndef _SBMIPS_H -+#define _SBMIPS_H ++#ifndef _linuxver_h_ ++#define _linuxver_h_ + -+#include ++#include ++#include + -+#ifndef _LANGUAGE_ASSEMBLY ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)) ++/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */ ++#ifdef __UNDEF_NO_VERSION__ ++#undef __NO_VERSION__ ++#else ++#define __NO_VERSION__ ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */ + -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif /* PAD */ ++#if defined(MODULE) && defined(MODVERSIONS) ++#include ++#endif + -+typedef volatile struct { -+ uint32 corecontrol; -+ uint32 PAD[2]; -+ uint32 biststatus; -+ uint32 PAD[4]; -+ uint32 intstatus; -+ uint32 intmask; -+ uint32 timer; -+} mipsregs_t; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) ++#include ++#endif + -+extern uint32 sb_flag(sb_t *sbh); -+extern uint sb_irq(sb_t *sbh); + -+extern void BCMINIT(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift)); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) ++#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") ++#define module_param_string(_name_, _string_, _size_, _perm_) \ ++ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_)) ++#endif + -+extern void *sb_jtagm_init(sb_t *sbh, uint clkd, bool exttap); -+extern void sb_jtagm_disable(void *h); -+extern uint32 jtag_rwreg(void *h, uint32 ir, uint32 dr); -+extern void BCMINIT(sb_mips_init)(sb_t *sbh); -+extern uint32 BCMINIT(sb_mips_clock)(sb_t *sbh); -+extern bool BCMINIT(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock); -+extern void BCMINIT(enable_pfc)(uint32 mode); -+extern uint32 BCMINIT(sb_memc_get_ncdl)(sb_t *sbh); ++/* linux/malloc.h is deprecated, use linux/slab.h instead. */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9)) ++#include ++#else ++#include ++#endif + ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+#endif /* _LANGUAGE_ASSEMBLY */ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41)) ++#include ++#else ++#include ++#ifndef work_struct ++#define work_struct tq_struct ++#endif ++#ifndef INIT_WORK ++#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data)) ++#endif ++#ifndef schedule_work ++#define schedule_work(_work) schedule_task((_work)) ++#endif ++#ifndef flush_scheduled_work ++#define flush_scheduled_work() flush_scheduled_tasks() ++#endif ++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */ + -+#endif /* _SBMIPS_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbpci.h linux.dev/arch/mips/bcm947xx/include/sbpci.h ---- linux.old/arch/mips/bcm947xx/include/sbpci.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbpci.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,122 @@ -+/* -+ * BCM47XX Sonics SiliconBackplane PCI core hardware definitions. -+ * -+ * $Id$ -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* Some distributions have their own 2.6.x compatibility layers */ ++#ifndef IRQ_NONE ++typedef void irqreturn_t; ++#define IRQ_NONE ++#define IRQ_HANDLED ++#define IRQ_RETVAL(x) ++#endif ++#else ++typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ ++ ++#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 69)) ++/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which ++ * does this, but it's not in 2.4 so we do our own for now. + */ ++static inline void ++cs_error(client_handle_t handle, int func, int ret) ++{ ++ error_info_t err = { func, ret }; ++ CardServices(ReportError, handle, &err); ++} ++#endif + -+#ifndef _SBPCI_H -+#define _SBPCI_H ++#endif /* CONFIG_PCMCIA */ + -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) ++#ifndef __exit ++#define __exit ++#endif ++#ifndef __devexit ++#define __devexit ++#endif ++#ifndef __devinit ++#define __devinit __init ++#endif ++#ifndef __devinitdata ++#define __devinitdata ++#endif ++#ifndef __devexit_p ++#define __devexit_p(x) x +#endif + -+/* Sonics side: PCI core and host control registers */ -+typedef struct sbpciregs { -+ uint32 control; /* PCI control */ -+ uint32 PAD[3]; -+ uint32 arbcontrol; /* PCI arbiter control */ -+ uint32 PAD[3]; -+ uint32 intstatus; /* Interrupt status */ -+ uint32 intmask; /* Interrupt mask */ -+ uint32 sbtopcimailbox; /* Sonics to PCI mailbox */ -+ uint32 PAD[9]; -+ uint32 bcastaddr; /* Sonics broadcast address */ -+ uint32 bcastdata; /* Sonics broadcast data */ -+ uint32 PAD[2]; -+ uint32 gpioin; /* ro: gpio input (>=rev2) */ -+ uint32 gpioout; /* rw: gpio output (>=rev2) */ -+ uint32 gpioouten; /* rw: gpio output enable (>= rev2) */ -+ uint32 gpiocontrol; /* rw: gpio control (>= rev2) */ -+ uint32 PAD[36]; -+ uint32 sbtopci0; /* Sonics to PCI translation 0 */ -+ uint32 sbtopci1; /* Sonics to PCI translation 1 */ -+ uint32 sbtopci2; /* Sonics to PCI translation 2 */ -+ uint32 PAD[445]; -+ uint16 sprom[36]; /* SPROM shadow Area */ -+ uint32 PAD[46]; -+} sbpciregs_t; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)) + -+/* PCI control */ -+#define PCI_RST_OE 0x01 /* When set, drives PCI_RESET out to pin */ -+#define PCI_RST 0x02 /* Value driven out to pin */ -+#define PCI_CLK_OE 0x04 /* When set, drives clock as gated by PCI_CLK out to pin */ -+#define PCI_CLK 0x08 /* Gate for clock driven out to pin */ ++#define pci_get_drvdata(dev) (dev)->sysdata ++#define pci_set_drvdata(dev, value) (dev)->sysdata = (value) + -+/* PCI arbiter control */ -+#define PCI_INT_ARB 0x01 /* When set, use an internal arbiter */ -+#define PCI_EXT_ARB 0x02 /* When set, use an external arbiter */ -+#define PCI_PARKID_MASK 0x06 /* Selects which agent is parked on an idle bus */ -+#define PCI_PARKID_SHIFT 1 -+#define PCI_PARKID_LAST 0 /* Last requestor */ -+#define PCI_PARKID_4710 1 /* 4710 */ -+#define PCI_PARKID_EXTREQ0 2 /* External requestor 0 */ -+#define PCI_PARKID_EXTREQ1 3 /* External requestor 1 */ ++/* ++ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration ++ */ + -+/* Interrupt status/mask */ -+#define PCI_INTA 0x01 /* PCI INTA# is asserted */ -+#define PCI_INTB 0x02 /* PCI INTB# is asserted */ -+#define PCI_SERR 0x04 /* PCI SERR# has been asserted (write one to clear) */ -+#define PCI_PERR 0x08 /* PCI PERR# has been asserted (write one to clear) */ -+#define PCI_PME 0x10 /* PCI PME# is asserted */ ++struct pci_device_id { ++ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ ++ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ ++ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ ++ unsigned long driver_data; /* Data private to the driver */ ++}; + -+/* (General) PCI/SB mailbox interrupts, two bits per pci function */ -+#define MAILBOX_F0_0 0x100 /* function 0, int 0 */ -+#define MAILBOX_F0_1 0x200 /* function 0, int 1 */ -+#define MAILBOX_F1_0 0x400 /* function 1, int 0 */ -+#define MAILBOX_F1_1 0x800 /* function 1, int 1 */ -+#define MAILBOX_F2_0 0x1000 /* function 2, int 0 */ -+#define MAILBOX_F2_1 0x2000 /* function 2, int 1 */ -+#define MAILBOX_F3_0 0x4000 /* function 3, int 0 */ -+#define MAILBOX_F3_1 0x8000 /* function 3, int 1 */ ++struct pci_driver { ++ struct list_head node; ++ char *name; ++ const struct pci_device_id *id_table; /* NULL if wants all devices */ ++ int (*probe)(struct pci_dev *dev, ++ const struct pci_device_id *id); /* New device inserted */ ++ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug ++ * capable driver) ++ */ ++ void (*suspend)(struct pci_dev *dev); /* Device suspended */ ++ void (*resume)(struct pci_dev *dev); /* Device woken up */ ++}; + -+/* Sonics broadcast address */ -+#define BCAST_ADDR_MASK 0xff /* Broadcast register address */ ++#define MODULE_DEVICE_TABLE(type, name) ++#define PCI_ANY_ID (~0) + -+/* Sonics to PCI translation types */ -+#define SBTOPCI0_MASK 0xfc000000 -+#define SBTOPCI1_MASK 0xfc000000 -+#define SBTOPCI2_MASK 0xc0000000 -+#define SBTOPCI_MEM 0 -+#define SBTOPCI_IO 1 -+#define SBTOPCI_CFG0 2 -+#define SBTOPCI_CFG1 3 -+#define SBTOPCI_PREF 0x4 /* prefetch enable */ -+#define SBTOPCI_BURST 0x8 /* burst enable */ -+#define SBTOPCI_RC_MASK 0x30 /* read command (>= rev11) */ -+#define SBTOPCI_RC_READ 0x00 /* memory read */ -+#define SBTOPCI_RC_READLINE 0x10 /* memory read line */ -+#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */ ++/* compatpci.c */ ++#define pci_module_init pci_register_driver ++extern int pci_register_driver(struct pci_driver *drv); ++extern void pci_unregister_driver(struct pci_driver *drv); + -+/* PCI core index in SROM shadow area */ -+#define SRSH_PI_OFFSET 0 /* first word */ -+#define SRSH_PI_MASK 0xf000 /* bit 15:12 */ -+#define SRSH_PI_SHIFT 12 /* bit 15:12 */ ++#endif /* PCI registration */ + -+/* PCI side: Reserved PCI configuration registers (see pcicfg.h) */ -+#define cap_list rsvd_a[0] -+#define bar0_window dev_dep[0x80 - 0x40] -+#define bar1_window dev_dep[0x84 - 0x40] -+#define sprom_control dev_dep[0x88 - 0x40] ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) ++#ifdef MODULE ++#define module_init(x) int init_module(void) { return x(); } ++#define module_exit(x) void cleanup_module(void) { x(); } ++#else ++#define module_init(x) __initcall(x); ++#define module_exit(x) __exitcall(x); ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */ + -+#ifndef _LANGUAGE_ASSEMBLY ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48)) ++#define list_for_each(pos, head) \ ++ for (pos = (head)->next; pos != (head); pos = pos->next) ++#endif + -+extern int sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len); -+extern int sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len); -+extern void sbpci_ban(uint16 core); -+extern int sbpci_init(sb_t *sbh); -+extern void sbpci_check(sb_t *sbh); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13)) ++#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)]) ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44)) ++#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) ++#endif + -+#endif /* !_LANGUAGE_ASSEMBLY */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23)) ++#define pci_enable_device(dev) do { } while (0) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14)) ++#define net_device device ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42)) + -+#endif /* _SBPCI_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbpcie.h linux.dev/arch/mips/bcm947xx/include/sbpcie.h ---- linux.old/arch/mips/bcm947xx/include/sbpcie.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbpcie.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,199 @@ +/* -+ * BCM43XX SiliconBackplane PCIE core hardware definitions. ++ * DMA mapping + * -+ * $Id: -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * See linux/Documentation/DMA-mapping.txt + */ + -+#ifndef _SBPCIE_H -+#define _SBPCIE_H -+ -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) ++#ifndef PCI_DMA_TODEVICE ++#define PCI_DMA_TODEVICE 1 ++#define PCI_DMA_FROMDEVICE 2 +#endif + -+/* PCIE Enumeration space offsets*/ -+#define PCIE_CORE_CONFIG_OFFSET 0x0 -+#define PCIE_FUNC0_CONFIG_OFFSET 0x400 -+#define PCIE_FUNC1_CONFIG_OFFSET 0x500 -+#define PCIE_FUNC2_CONFIG_OFFSET 0x600 -+#define PCIE_FUNC3_CONFIG_OFFSET 0x700 -+#define PCIE_SPROM_SHADOW_OFFSET 0x800 -+#define PCIE_SBCONFIG_OFFSET 0xE00 ++typedef u32 dma_addr_t; + -+/* PCIE Bar0 Address Mapping. Each function maps 16KB config space */ -+#define PCIE_BAR0_WINMAPCORE_OFFSET 0x0 -+#define PCIE_BAR0_EXTSPROM_OFFSET 0x1000 -+#define PCIE_BAR0_PCIECORE_OFFSET 0x2000 -+#define PCIE_BAR0_CCCOREREG_OFFSET 0x3000 ++/* Pure 2^n version of get_order */ ++static inline int get_order(unsigned long size) ++{ ++ int order; + -+/* SB side: PCIE core and host control registers */ -+typedef struct sbpcieregs { ++ size = (size-1) >> (PAGE_SHIFT-1); ++ order = -1; ++ do { ++ size >>= 1; ++ order++; ++ } while (size); ++ return order; ++} + -+ uint32 PAD[3]; -+ uint32 biststatus; /* bist Status: 0x00C*/ -+ uint32 PAD[6]; -+ uint32 sbtopcimailbox; /* sb to pcie mailbox: 0x028*/ -+ uint32 PAD[54]; -+ uint32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ -+ uint32 sbtopcie1; /* sb to pcie translation 1: 0x104 */ -+ uint32 sbtopcie2; /* sb to pcie translation 2: 0x108 */ -+ uint32 PAD[4]; ++static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, ++ dma_addr_t *dma_handle) ++{ ++ void *ret; ++ int gfp = GFP_ATOMIC | GFP_DMA; + -+ /* pcie core supports in direct access to config space */ -+ uint32 configaddr; /* pcie config space access: Address field: 0x120*/ -+ uint32 configdata; /* pcie config space access: Data field: 0x124*/ ++ ret = (void *)__get_free_pages(gfp, get_order(size)); + -+ /* mdio access to serdes */ -+ uint32 mdiocontrol; /* controls the mdio access: 0x128 */ -+ uint32 mdiodata; /* Data to the mdio access: 0x12c */ ++ if (ret != NULL) { ++ memset(ret, 0, size); ++ *dma_handle = virt_to_bus(ret); ++ } ++ return ret; ++} ++static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, ++ void *vaddr, dma_addr_t dma_handle) ++{ ++ free_pages((unsigned long)vaddr, get_order(size)); ++} ++#ifdef ILSIM ++extern uint pci_map_single(void *dev, void *va, uint size, int direction); ++extern void pci_unmap_single(void *dev, uint pa, uint size, int direction); ++#else ++#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) ++#define pci_unmap_single(cookie, address, size, dir) ++#endif + -+ /* pcie protocol phy/dllp/tlp register access mechanism*/ -+ uint32 pcieaddr; /* address of the internal registeru: 0x130 */ -+ uint32 pciedata; /* Data to/from the internal regsiter: 0x134 */ ++#endif /* DMA mapping */ + -+ uint32 PAD[434]; -+ uint16 sprom[36]; /* SPROM shadow Area */ -+} sbpcieregs_t; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43)) + -+/* SB to PCIE translation masks */ -+#define SBTOPCIE0_MASK 0xfc000000 -+#define SBTOPCIE1_MASK 0xfc000000 -+#define SBTOPCIE2_MASK 0xc0000000 ++#define dev_kfree_skb_any(a) dev_kfree_skb(a) ++#define netif_down(dev) do { (dev)->start = 0; } while (0) + -+/* Access type bits (0:1)*/ -+#define SBTOPCIE_MEM 0 -+#define SBTOPCIE_IO 1 -+#define SBTOPCIE_CFG0 2 -+#define SBTOPCIE_CFG1 3 ++/* pcmcia-cs provides its own netdevice compatibility layer */ ++#ifndef _COMPAT_NETDEVICE_H + -+/*Prefetch enable bit 2*/ -+#define SBTOPCIE_PF 4 ++/* ++ * SoftNet ++ * ++ * For pre-softnet kernels we need to tell the upper layer not to ++ * re-enter start_xmit() while we are in there. However softnet ++ * guarantees not to enter while we are in there so there is no need ++ * to do the netif_stop_queue() dance unless the transmit queue really ++ * gets stuck. This should also improve performance according to tests ++ * done by Aman Singla. ++ */ + -+/*Write Burst enable for memory write bit 3*/ -+#define SBTOPCIE_WR_BURST 8 ++#define dev_kfree_skb_irq(a) dev_kfree_skb(a) ++#define netif_wake_queue(dev) \ ++ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0) ++#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy) + -+/* config access */ -+#define CONFIGADDR_FUNC_MASK 0x7000 -+#define CONFIGADDR_FUNC_SHF 12 -+#define CONFIGADDR_REG_MASK 0x0FFF -+#define CONFIGADDR_REG_SHF 0 ++static inline void netif_start_queue(struct net_device *dev) ++{ ++ dev->tbusy = 0; ++ dev->interrupt = 0; ++ dev->start = 1; ++} + -+/* PCIE protocol regs Indirect Address */ -+#define PCIEADDR_PROT_MASK 0x300 -+#define PCIEADDR_PROT_SHF 8 -+#define PCIEADDR_PL_TLP 0 -+#define PCIEADDR_PL_DLLP 1 -+#define PCIEADDR_PL_PLP 2 ++#define netif_queue_stopped(dev) (dev)->tbusy ++#define netif_running(dev) (dev)->start + -+/* PCIE protocol PHY diagnostic registers */ -+#define PCIE_PLP_MODEREG 0x200 /* Mode*/ -+#define PCIE_PLP_STATUSREG 0x204 /* Status*/ -+#define PCIE_PLP_LTSSMCTRLREG 0x208 /* LTSSM control */ -+#define PCIE_PLP_LTLINKNUMREG 0x20c /* Link Training Link number*/ -+#define PCIE_PLP_LTLANENUMREG 0x210 /* Link Training Lane number*/ -+#define PCIE_PLP_LTNFTSREG 0x214 /* Link Training N_FTS */ -+#define PCIE_PLP_ATTNREG 0x218 /* Attention */ -+#define PCIE_PLP_ATTNMASKREG 0x21C /* Attention Mask */ -+#define PCIE_PLP_RXERRCTR 0x220 /* Rx Error */ -+#define PCIE_PLP_RXFRMERRCTR 0x224 /* Rx Framing Error*/ -+#define PCIE_PLP_RXERRTHRESHREG 0x228 /* Rx Error threshold */ -+#define PCIE_PLP_TESTCTRLREG 0x22C /* Test Control reg*/ -+#define PCIE_PLP_SERDESCTRLOVRDREG 0x230 /* SERDES Control Override */ -+#define PCIE_PLP_TIMINGOVRDREG 0x234 /* Timing param override */ -+#define PCIE_PLP_RXTXSMDIAGREG 0x238 /* RXTX State Machine Diag*/ -+#define PCIE_PLP_LTSSMDIAGREG 0x23C /* LTSSM State Machine Diag*/ ++#endif /* _COMPAT_NETDEVICE_H */ + -+/* PCIE protocol DLLP diagnostic registers */ -+#define PCIE_DLLP_LCREG 0x100 /* Link Control*/ -+#define PCIE_DLLP_LSREG 0x104 /* Link Status */ -+#define PCIE_DLLP_LAREG 0x108 /* Link Attention*/ -+#define PCIE_DLLP_LAMASKREG 0x10C /* Link Attention Mask */ -+#define PCIE_DLLP_NEXTTXSEQNUMREG 0x110 /* Next Tx Seq Num*/ -+#define PCIE_DLLP_ACKEDTXSEQNUMREG 0x114 /* Acked Tx Seq Num*/ -+#define PCIE_DLLP_PURGEDTXSEQNUMREG 0x118 /* Purged Tx Seq Num*/ -+#define PCIE_DLLP_RXSEQNUMREG 0x11C /* Rx Sequence Number */ -+#define PCIE_DLLP_LRREG 0x120 /* Link Replay*/ -+#define PCIE_DLLP_LACKTOREG 0x124 /* Link Ack Timeout*/ -+#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold*/ -+#define PCIE_DLLP_RTRYWPREG 0x12C /* Retry buffer write ptr*/ -+#define PCIE_DLLP_RTRYRPREG 0x130 /* Retry buffer Read ptr*/ -+#define PCIE_DLLP_RTRYPPREG 0x134 /* Retry buffer Purged ptr*/ -+#define PCIE_DLLP_RTRRWREG 0x138 /* Retry buffer Read/Write*/ -+#define PCIE_DLLP_ECTHRESHREG 0x13C /* Error Count Threshold */ -+#define PCIE_DLLP_TLPERRCTRREG 0x140 /* TLP Error Counter */ -+#define PCIE_DLLP_ERRCTRREG 0x144 /* Error Counter*/ -+#define PCIE_DLLP_NAKRXCTRREG 0x148 /* NAK Received Counter*/ -+#define PCIE_DLLP_TESTREG 0x14C /* Test */ -+#define PCIE_DLLP_PKTBIST 0x150 /* Packet BIST*/ ++#define netif_device_attach(dev) netif_start_queue(dev) ++#define netif_device_detach(dev) netif_stop_queue(dev) + -+/* PCIE protocol TLP diagnostic registers */ -+#define PCIE_TLP_CONFIGREG 0x000 /* Configuration */ -+#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */ -+#define PCIE_TLP_WRDMAUPPER 0x010 /* Write DMA Upper Address*/ -+#define PCIE_TLP_WRDMALOWER 0x014 /* Write DMA Lower Address*/ -+#define PCIE_TLP_WRDMAREQ_LBEREG 0x018 /* Write DMA Len/ByteEn Req*/ -+#define PCIE_TLP_RDDMAUPPER 0x01C /* Read DMA Upper Address*/ -+#define PCIE_TLP_RDDMALOWER 0x020 /* Read DMA Lower Address*/ -+#define PCIE_TLP_RDDMALENREG 0x024 /* Read DMA Len Req*/ -+#define PCIE_TLP_MSIDMAUPPER 0x028 /* MSI DMA Upper Address*/ -+#define PCIE_TLP_MSIDMALOWER 0x02C /* MSI DMA Lower Address*/ -+#define PCIE_TLP_MSIDMALENREG 0x030 /* MSI DMA Len Req*/ -+#define PCIE_TLP_SLVREQLENREG 0x034 /* Slave Request Len*/ -+#define PCIE_TLP_FCINPUTSREQ 0x038 /* Flow Control Inputs*/ -+#define PCIE_TLP_TXSMGRSREQ 0x03C /* Tx StateMachine and Gated Req*/ -+#define PCIE_TLP_ADRACKCNTARBLEN 0x040 /* Address Ack XferCnt and ARB Len*/ -+#define PCIE_TLP_DMACPLHDR0 0x044 /* DMA Completion Hdr 0*/ -+#define PCIE_TLP_DMACPLHDR1 0x048 /* DMA Completion Hdr 1*/ -+#define PCIE_TLP_DMACPLHDR2 0x04C /* DMA Completion Hdr 2*/ -+#define PCIE_TLP_DMACPLMISC0 0x050 /* DMA Completion Misc0 */ -+#define PCIE_TLP_DMACPLMISC1 0x054 /* DMA Completion Misc1 */ -+#define PCIE_TLP_DMACPLMISC2 0x058 /* DMA Completion Misc2 */ -+#define PCIE_TLP_SPTCTRLLEN 0x05C /* Split Controller Req len*/ -+#define PCIE_TLP_SPTCTRLMSIC0 0x060 /* Split Controller Misc 0*/ -+#define PCIE_TLP_SPTCTRLMSIC1 0x064 /* Split Controller Misc 1*/ -+#define PCIE_TLP_BUSDEVFUNC 0x068 /* Bus/Device/Func*/ -+#define PCIE_TLP_RESETCTR 0x06C /* Reset Counter*/ -+#define PCIE_TLP_RTRYBUF 0x070 /* Retry Buffer value*/ -+#define PCIE_TLP_TGTDEBUG1 0x074 /* Target Debug Reg1*/ -+#define PCIE_TLP_TGTDEBUG2 0x078 /* Target Debug Reg2*/ -+#define PCIE_TLP_TGTDEBUG3 0x07C /* Target Debug Reg3*/ -+#define PCIE_TLP_TGTDEBUG4 0x080 /* Target Debug Reg4*/ -+ -+/* MDIO control */ -+#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ -+#define MDIOCTL_DIVISOR_VAL 0x2 -+#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ -+#define MDIOCTL_ACCESS_DONE 0x100 /* Tranaction complete */ ++/* 2.4.x renamed bottom halves to tasklets */ ++#define tasklet_struct tq_struct ++static inline void tasklet_schedule(struct tasklet_struct *tasklet) ++{ ++ queue_task(tasklet, &tq_immediate); ++ mark_bh(IMMEDIATE_BH); ++} + -+/* MDIO Data */ -+#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */ -+#define MDIODATA_TA 0x00020000 /* Turnaround */ -+#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ -+#define MDIODATA_REGADDR_MASK 0x003c0000 /* Regaddr Mask */ -+#define MDIODATA_DEVADDR_SHF 22 /* Physmedia devaddr shift */ -+#define MDIODATA_DEVADDR_MASK 0x0fc00000 /* Physmedia devaddr Mask */ -+#define MDIODATA_WRITE 0x10000000 /* write Transaction */ -+#define MDIODATA_READ 0x20000000 /* Read Transaction */ -+#define MDIODATA_START 0x40000000 /* start of Transaction */ ++static inline void tasklet_init(struct tasklet_struct *tasklet, ++ void (*func)(unsigned long), ++ unsigned long data) ++{ ++ tasklet->next = NULL; ++ tasklet->sync = 0; ++ tasklet->routine = (void (*)(void *))func; ++ tasklet->data = (void *)data; ++} ++#define tasklet_kill(tasklet) { do{} while (0); } + -+/* MDIO devices (SERDES modules) */ -+#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ -+#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ -+#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ ++/* 2.4.x introduced del_timer_sync() */ ++#define del_timer_sync(timer) del_timer(timer) + -+/* SERDES registers */ -+#define SERDES_RX_TIMER1 2 /* Rx Timer1 */ -+#define SERDES_RX_CDR 6 /* CDR */ -+#define SERDES_RX_CDRBW 7 /* CDR BW */ ++#else + -+#endif /* _SBPCIE_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbpcmcia.h linux.dev/arch/mips/bcm947xx/include/sbpcmcia.h ---- linux.old/arch/mips/bcm947xx/include/sbpcmcia.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbpcmcia.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,146 @@ -+/* -+ * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions. -+ * -+ * $Id$ -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ */ ++#define netif_down(dev) + -+#ifndef _SBPCMCIA_H -+#define _SBPCMCIA_H ++#endif /* SoftNet */ + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3)) + -+/* All the addresses that are offsets in attribute space are divided -+ * by two to account for the fact that odd bytes are invalid in -+ * attribute space and our read/write routines make the space appear -+ * as if they didn't exist. Still we want to show the original numbers -+ * as documented in the hnd_pcmcia core manual. ++/* ++ * Emit code to initialise a tq_struct's routine and data pointers + */ ++#define PREPARE_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ (_tq)->routine = _routine; \ ++ (_tq)->data = _data; \ ++ } while (0) + -+/* PCMCIA Function Configuration Registers */ -+#define PCMCIA_FCR (0x700 / 2) -+ -+#define FCR0_OFF 0 -+#define FCR1_OFF (0x40 / 2) -+#define FCR2_OFF (0x80 / 2) -+#define FCR3_OFF (0xc0 / 2) -+ -+#define PCMCIA_FCR0 (0x700 / 2) -+#define PCMCIA_FCR1 (0x740 / 2) -+#define PCMCIA_FCR2 (0x780 / 2) -+#define PCMCIA_FCR3 (0x7c0 / 2) -+ -+/* Standard PCMCIA FCR registers */ -+ -+#define PCMCIA_COR 0 ++/* ++ * Emit code to initialise all of a tq_struct ++ */ ++#define INIT_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ INIT_LIST_HEAD(&(_tq)->list); \ ++ (_tq)->sync = 0; \ ++ PREPARE_TQUEUE((_tq), (_routine), (_data)); \ ++ } while (0) + -+#define COR_RST 0x80 -+#define COR_LEV 0x40 -+#define COR_IRQEN 0x04 -+#define COR_BLREN 0x01 -+#define COR_FUNEN 0x01 ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */ + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)) + -+#define PCICIA_FCSR (2 / 2) -+#define PCICIA_PRR (4 / 2) -+#define PCICIA_SCR (6 / 2) -+#define PCICIA_ESR (8 / 2) ++/* Power management related routines */ + ++static inline int ++pci_save_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_read_config_dword(dev, i * 4, &buffer[i]); ++ } ++ return 0; ++} + -+#define PCM_MEMOFF 0x0000 -+#define F0_MEMOFF 0x1000 -+#define F1_MEMOFF 0x2000 -+#define F2_MEMOFF 0x3000 -+#define F3_MEMOFF 0x4000 ++static inline int ++pci_restore_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; + -+/* Memory base in the function fcr's */ -+#define MEM_ADDR0 (0x728 / 2) -+#define MEM_ADDR1 (0x72a / 2) -+#define MEM_ADDR2 (0x72c / 2) ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_write_config_dword(dev, i * 4, buffer[i]); ++ } ++ /* ++ * otherwise, write the context information we know from bootup. ++ * This works around a problem where warm-booting from Windows ++ * combined with a D3(hot)->D0 transition causes PCI config ++ * header data to be forgotten. ++ */ ++ else { ++ for (i = 0; i < 6; i ++) ++ pci_write_config_dword(dev, ++ PCI_BASE_ADDRESS_0 + (i * 4), ++ pci_resource_start(dev, i)); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); ++ } ++ return 0; ++} + -+/* PCMCIA base plus Srom access in fcr0: */ -+#define PCMCIA_ADDR0 (0x072e / 2) -+#define PCMCIA_ADDR1 (0x0730 / 2) -+#define PCMCIA_ADDR2 (0x0732 / 2) ++#endif /* PCI power management */ + -+#define MEM_SEG (0x0734 / 2) -+#define SROM_CS (0x0736 / 2) -+#define SROM_DATAL (0x0738 / 2) -+#define SROM_DATAH (0x073a / 2) -+#define SROM_ADDRL (0x073c / 2) -+#define SROM_ADDRH (0x073e / 2) ++/* Old cp0 access macros deprecated in 2.4.19 */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19)) ++#define read_c0_count() read_32bit_cp0_register(CP0_COUNT) ++#endif + -+/* Values for srom_cs: */ -+#define SROM_IDLE 0 -+#define SROM_WRITE 1 -+#define SROM_READ 2 -+#define SROM_WEN 4 -+#define SROM_WDS 7 -+#define SROM_DONE 8 ++/* Module refcount handled internally in 2.6.x */ ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do {} while (0) ++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#else ++#define OLD_MOD_INC_USE_COUNT do {} while (0) ++#define OLD_MOD_DEC_USE_COUNT do {} while (0) ++#endif + -+/* CIS stuff */ ++#ifndef SET_NETDEV_DEV ++#define SET_NETDEV_DEV(net, pdev) do {} while (0) ++#endif + -+/* The CIS stops where the FCRs start */ -+#define CIS_SIZE PCMCIA_FCR ++#ifndef HAVE_FREE_NETDEV ++#define free_netdev(dev) kfree(dev) ++#endif + -+/* Standard tuples we know about */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* struct packet_type redefined in 2.6.x */ ++#define af_packet_priv data ++#endif + -+#define CISTPL_MANFID 0x20 /* Manufacturer and device id */ -+#define CISTPL_FUNCE 0x22 /* Function extensions */ -+#define CISTPL_CFTABLE 0x1b /* Config table entry */ ++#endif /* _linuxver_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/mipsinc.h linux.dev/arch/mips/bcm947xx/include/mipsinc.h +--- linux.old/arch/mips/bcm947xx/include/mipsinc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/mipsinc.h 2006-04-27 22:12:20.000000000 +0200 +@@ -0,0 +1,541 @@ ++/* ++ * HND Run Time Environment for standalone MIPS programs. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: mipsinc.h,v 1.1.1.5 2006/02/27 03:43:16 honor Exp $ ++ */ + -+/* Function extensions for LANs */ ++#ifndef _MISPINC_H ++#define _MISPINC_H + -+#define LAN_TECH 1 /* Technology type */ -+#define LAN_SPEED 2 /* Raw bit rate */ -+#define LAN_MEDIA 3 /* Transmission media */ -+#define LAN_NID 4 /* Node identification (aka MAC addr) */ -+#define LAN_CONN 5 /* Connector standard */ + ++/* MIPS defines */ + -+/* CFTable */ -+#define CFTABLE_REGWIN_2K 0x08 /* 2k reg windows size */ -+#define CFTABLE_REGWIN_4K 0x10 /* 4k reg windows size */ -+#define CFTABLE_REGWIN_8K 0x20 /* 8k reg windows size */ ++#ifdef _LANGUAGE_ASSEMBLY + -+/* Vendor unique tuples are 0x80-0x8f. Within Broadcom we'll -+ * take one for HNBU, and use "extensions" (a la FUNCE) within it. ++/* ++ * Symbolic register names for 32 bit ABI + */ ++#define zero $0 /* wired zero */ ++#define AT $1 /* assembler temp - uppercase because of ".set at" */ ++#define v0 $2 /* return value */ ++#define v1 $3 ++#define a0 $4 /* argument registers */ ++#define a1 $5 ++#define a2 $6 ++#define a3 $7 ++#define t0 $8 /* caller saved */ ++#define t1 $9 ++#define t2 $10 ++#define t3 $11 ++#define t4 $12 ++#define t5 $13 ++#define t6 $14 ++#define t7 $15 ++#define s0 $16 /* callee saved */ ++#define s1 $17 ++#define s2 $18 ++#define s3 $19 ++#define s4 $20 ++#define s5 $21 ++#define s6 $22 ++#define s7 $23 ++#define t8 $24 /* caller saved */ ++#define t9 $25 ++#define jp $25 /* PIC jump register */ ++#define k0 $26 /* kernel scratch */ ++#define k1 $27 ++#define gp $28 /* global pointer */ ++#define sp $29 /* stack pointer */ ++#define fp $30 /* frame pointer */ ++#define s8 $30 /* same like fp! */ ++#define ra $31 /* return address */ + -+#define CISTPL_BRCM_HNBU 0x80 + -+/* Subtypes of BRCM_HNBU: */ ++/* CP0 Registers */ + -+#define HNBU_SROMREV 0x00 /* A byte with sromrev, 1 if not present */ -+#define HNBU_CHIPID 0x01 /* Six bytes with PCI vendor & -+ * device id and chiprev -+ */ -+#define HNBU_BOARDREV 0x02 /* Two bytes board revision */ -+#define HNBU_PAPARMS 0x03 /* PA parameters: 1 (old), 8 (sreomrev == 1) -+ * or 9 (sromrev > 1) bytes */ -+#define HNBU_OEM 0x04 /* Eight bytes OEM data (sromrev == 1) */ -+#define HNBU_CC 0x05 /* Default country code (sromrev == 1) */ -+#define HNBU_AA 0x06 /* Antennas available */ -+#define HNBU_AG 0x07 /* Antenna gain */ -+#define HNBU_BOARDFLAGS 0x08 /* board flags (2 or 4 bytes) */ -+#define HNBU_LEDS 0x09 /* LED set */ -+#define HNBU_CCODE 0x0a /* Country code (2 bytes ascii + 1 byte cctl) -+ * in rev 2 -+ */ -+#define HNBU_CCKPO 0x0b /* 2 byte cck power offsets in rev 3 */ -+#define HNBU_OFDMPO 0x0c /* 4 byte 11g ofdm power offsets in rev 3 */ -+ -+ -+/* sbtmstatelow */ -+#define SBTML_INT_ACK 0x40000 /* ack the sb interrupt */ -+#define SBTML_INT_EN 0x20000 /* enable sb interrupt */ -+ -+/* sbtmstatehigh */ -+#define SBTMH_INT_STATUS 0x40000 /* sb interrupt status */ ++#define C0_INX $0 ++#define C0_RAND $1 ++#define C0_TLBLO0 $2 ++#define C0_TLBLO C0_TLBLO0 ++#define C0_TLBLO1 $3 ++#define C0_CTEXT $4 ++#define C0_PGMASK $5 ++#define C0_WIRED $6 ++#define C0_BADVADDR $8 ++#define C0_COUNT $9 ++#define C0_TLBHI $10 ++#define C0_COMPARE $11 ++#define C0_SR $12 ++#define C0_STATUS C0_SR ++#define C0_CAUSE $13 ++#define C0_EPC $14 ++#define C0_PRID $15 ++#define C0_CONFIG $16 ++#define C0_LLADDR $17 ++#define C0_WATCHLO $18 ++#define C0_WATCHHI $19 ++#define C0_XCTEXT $20 ++#define C0_DIAGNOSTIC $22 ++#define C0_BROADCOM C0_DIAGNOSTIC ++#define C0_PERFORMANCE $25 ++#define C0_ECC $26 ++#define C0_CACHEERR $27 ++#define C0_TAGLO $28 ++#define C0_TAGHI $29 ++#define C0_ERREPC $30 ++#define C0_DESAVE $31 + -+#endif /* _SBPCMCIA_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbsdram.h linux.dev/arch/mips/bcm947xx/include/sbsdram.h ---- linux.old/arch/mips/bcm947xx/include/sbsdram.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbsdram.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,75 @@ +/* -+ * BCM47XX Sonics SiliconBackplane SDRAM controller core hardware definitions. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ ++ * LEAF - declare leaf routine + */ ++#define LEAF(symbol) \ ++ .globl symbol; \ ++ .align 2; \ ++ .type symbol, @function; \ ++ .ent symbol, 0; \ ++symbol: .frame sp, 0, ra + -+#ifndef _SBSDRAM_H -+#define _SBSDRAM_H -+ -+#ifndef _LANGUAGE_ASSEMBLY -+ -+/* Sonics side: SDRAM core registers */ -+typedef volatile struct sbsdramregs { -+ uint32 initcontrol; /* Generates external SDRAM initialization sequence */ -+ uint32 config; /* Initializes external SDRAM mode register */ -+ uint32 refresh; /* Controls external SDRAM refresh rate */ -+ uint32 pad1; -+ uint32 pad2; -+} sbsdramregs_t; -+ -+#endif ++/* ++ * END - mark end of function ++ */ ++#define END(function) \ ++ .end function; \ ++ .size function, . - function + -+/* SDRAM initialization control (initcontrol) register bits */ -+#define SDRAM_CBR 0x0001 /* Writing 1 generates refresh cycle and toggles bit */ -+#define SDRAM_PRE 0x0002 /* Writing 1 generates precharge cycle and toggles bit */ -+#define SDRAM_MRS 0x0004 /* Writing 1 generates mode register select cycle and toggles bit */ -+#define SDRAM_EN 0x0008 /* When set, enables access to SDRAM */ -+#define SDRAM_16Mb 0x0000 /* Use 16 Megabit SDRAM */ -+#define SDRAM_64Mb 0x0010 /* Use 64 Megabit SDRAM */ -+#define SDRAM_128Mb 0x0020 /* Use 128 Megabit SDRAM */ -+#define SDRAM_RSVMb 0x0030 /* Use special SDRAM */ -+#define SDRAM_RST 0x0080 /* Writing 1 causes soft reset of controller */ -+#define SDRAM_SELFREF 0x0100 /* Writing 1 enables self refresh mode */ -+#define SDRAM_PWRDOWN 0x0200 /* Writing 1 causes controller to power down */ -+#define SDRAM_32BIT 0x0400 /* When set, indicates 32 bit SDRAM interface */ -+#define SDRAM_9BITCOL 0x0800 /* When set, indicates 9 bit column */ ++#define _ULCAST_ + -+/* SDRAM configuration (config) register bits */ -+#define SDRAM_BURSTFULL 0x0000 /* Use full page bursts */ -+#define SDRAM_BURST8 0x0001 /* Use burst of 8 */ -+#define SDRAM_BURST4 0x0002 /* Use burst of 4 */ -+#define SDRAM_BURST2 0x0003 /* Use burst of 2 */ -+#define SDRAM_CAS3 0x0000 /* Use CAS latency of 3 */ -+#define SDRAM_CAS2 0x0004 /* Use CAS latency of 2 */ ++#define MFC0_SEL(dst, src, sel) \ ++ .word\t(0x40000000 | ((dst) << 16) | ((src) << 11) | (sel)) + -+/* SDRAM refresh control (refresh) register bits */ -+#define SDRAM_REF(p) (((p)&0xff) | SDRAM_REF_EN) /* Refresh period */ -+#define SDRAM_REF_EN 0x8000 /* Writing 1 enables periodic refresh */ + -+/* SDRAM Core default Init values (OCP ID 0x803) */ -+#define SDRAM_INIT MEM4MX16X2 -+#define SDRAM_CONFIG SDRAM_BURSTFULL -+#define SDRAM_REFRESH SDRAM_REF(0x40) ++#define MTC0_SEL(dst, src, sel) \ ++ .word\t(0x40800000 | ((dst) << 16) | ((src) << 11) | (sel)) + -+#define MEM1MX16 0x009 /* 2 MB */ -+#define MEM1MX16X2 0x409 /* 4 MB */ -+#define MEM2MX8X2 0x809 /* 4 MB */ -+#define MEM2MX8X4 0xc09 /* 8 MB */ -+#define MEM2MX32 0x439 /* 8 MB */ -+#define MEM4MX16 0x019 /* 8 MB */ -+#define MEM4MX16X2 0x419 /* 16 MB */ -+#define MEM8MX8X2 0x819 /* 16 MB */ -+#define MEM8MX16 0x829 /* 16 MB */ -+#define MEM4MX32 0x429 /* 16 MB */ -+#define MEM8MX8X4 0xc19 /* 32 MB */ -+#define MEM8MX16X2 0xc29 /* 32 MB */ ++#else + -+#endif /* _SBSDRAM_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbsocram.h linux.dev/arch/mips/bcm947xx/include/sbsocram.h ---- linux.old/arch/mips/bcm947xx/include/sbsocram.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbsocram.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,37 @@ +/* -+ * BCM47XX Sonics SiliconBackplane embedded ram core -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ ++ * The following macros are especially useful for __asm__ ++ * inline assembler. + */ ++#ifndef __STR ++#define __STR(x) #x ++#endif ++#ifndef STR ++#define STR(x) __STR(x) ++#endif + -+#ifndef _SBSOCRAM_H -+#define _SBSOCRAM_H -+ -+#define SOCRAM_MEMSIZE 0x00 -+#define SOCRAM_BISTSTAT 0x0c ++#define _ULCAST_ (unsigned long) + + -+#ifndef _LANGUAGE_ASSEMBLY ++/* CP0 Registers */ + -+/* Memcsocram core registers */ -+typedef volatile struct sbsocramregs { -+ uint32 memsize; -+ uint32 biststat; -+} sbsocramregs_t; ++#define C0_INX 0 /* CP0: TLB Index */ ++#define C0_RAND 1 /* CP0: TLB Random */ ++#define C0_TLBLO0 2 /* CP0: TLB EntryLo0 */ ++#define C0_TLBLO C0_TLBLO0 /* CP0: TLB EntryLo0 */ ++#define C0_TLBLO1 3 /* CP0: TLB EntryLo1 */ ++#define C0_CTEXT 4 /* CP0: Context */ ++#define C0_PGMASK 5 /* CP0: TLB PageMask */ ++#define C0_WIRED 6 /* CP0: TLB Wired */ ++#define C0_BADVADDR 8 /* CP0: Bad Virtual Address */ ++#define C0_COUNT 9 /* CP0: Count */ ++#define C0_TLBHI 10 /* CP0: TLB EntryHi */ ++#define C0_COMPARE 11 /* CP0: Compare */ ++#define C0_SR 12 /* CP0: Processor Status */ ++#define C0_STATUS C0_SR /* CP0: Processor Status */ ++#define C0_CAUSE 13 /* CP0: Exception Cause */ ++#define C0_EPC 14 /* CP0: Exception PC */ ++#define C0_PRID 15 /* CP0: Processor Revision Indentifier */ ++#define C0_CONFIG 16 /* CP0: Config */ ++#define C0_LLADDR 17 /* CP0: LLAddr */ ++#define C0_WATCHLO 18 /* CP0: WatchpointLo */ ++#define C0_WATCHHI 19 /* CP0: WatchpointHi */ ++#define C0_XCTEXT 20 /* CP0: XContext */ ++#define C0_DIAGNOSTIC 22 /* CP0: Diagnostic */ ++#define C0_BROADCOM C0_DIAGNOSTIC /* CP0: Broadcom Register */ ++#define C0_PERFORMANCE 25 /* CP0: Performance Counter/Control Registers */ ++#define C0_ECC 26 /* CP0: ECC */ ++#define C0_CACHEERR 27 /* CP0: CacheErr */ ++#define C0_TAGLO 28 /* CP0: TagLo */ ++#define C0_TAGHI 29 /* CP0: TagHi */ ++#define C0_ERREPC 30 /* CP0: ErrorEPC */ ++#define C0_DESAVE 31 /* CP0: DebugSave */ + -+#endif ++#endif /* _LANGUAGE_ASSEMBLY */ + -+/* Them memory size is 2 to the power of the following -+ * base added to the contents of the memsize register. ++/* ++ * Memory segments (32bit kernel mode addresses) + */ -+#define SOCRAM_MEMSIZE_BASESHIFT 16 ++#undef KUSEG ++#undef KSEG0 ++#undef KSEG1 ++#undef KSEG2 ++#undef KSEG3 ++#define KUSEG 0x00000000 ++#define KSEG0 0x80000000 ++#define KSEG1 0xa0000000 ++#define KSEG2 0xc0000000 ++#define KSEG3 0xe0000000 ++#define PHYSADDR_MASK 0x1fffffff + -+#endif /* _SBSOCRAM_H */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sbutils.h linux.dev/arch/mips/bcm947xx/include/sbutils.h ---- linux.old/arch/mips/bcm947xx/include/sbutils.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sbutils.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,140 @@ +/* -+ * Misc utility routines for accessing chip-specific features -+ * of Broadcom HNBU SiliconBackplane-based chips. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ ++ * Map an address to a certain kernel segment + */ ++#undef PHYSADDR ++#undef KSEG0ADDR ++#undef KSEG1ADDR ++#undef KSEG2ADDR ++#undef KSEG3ADDR + -+#ifndef _sbutils_h_ -+#define _sbutils_h_ -+ -+/* -+ * Datastructure to export all chip specific common variables -+ * public (read-only) portion of sbutils handle returned by -+ * sb_attach()/sb_kattach() -+*/ -+ -+struct sb_pub { -+ -+ uint bustype; /* SB_BUS, PCI_BUS */ -+ uint buscoretype; /* SB_PCI, SB_PCMCIA, SB_PCIE*/ -+ uint buscorerev; /* buscore rev */ -+ uint buscoreidx; /* buscore index */ -+ int ccrev; /* chip common core rev */ -+ uint boardtype; /* board type */ -+ uint boardvendor; /* board vendor */ -+ uint chip; /* chip number */ -+ uint chiprev; /* chip revision */ -+ uint chippkg; /* chip package option */ -+ uint sonicsrev; /* sonics backplane rev */ -+}; ++#define PHYSADDR(a) (_ULCAST_(a) & PHYSADDR_MASK) ++#define KSEG0ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG0) ++#define KSEG1ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG1) ++#define KSEG2ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG2) ++#define KSEG3ADDR(a) ((_ULCAST_(a) & PHYSADDR_MASK) | KSEG3) + -+typedef const struct sb_pub sb_t; + ++#ifndef Index_Invalidate_I +/* -+ * Many of the routines below take an 'sbh' handle as their first arg. -+ * Allocate this by calling sb_attach(). Free it by calling sb_detach(). -+ * At any one time, the sbh is logically focused on one particular sb core -+ * (the "current core"). -+ * Use sb_setcore() or sb_setcoreidx() to change the association to another core. ++ * Cache Operations + */ -+ -+/* exported externs */ -+extern sb_t * BCMINIT(sb_attach)(uint pcidev, osl_t *osh, void *regs, uint bustype, void *sdh, char **vars, int *varsz); -+extern sb_t * BCMINIT(sb_kattach)(void); -+extern void sb_detach(sb_t *sbh); -+extern uint BCMINIT(sb_chip)(sb_t *sbh); -+extern uint BCMINIT(sb_chiprev)(sb_t *sbh); -+extern uint BCMINIT(sb_chipcrev)(sb_t *sbh); -+extern uint BCMINIT(sb_chippkg)(sb_t *sbh); -+extern uint BCMINIT(sb_pcirev)(sb_t *sbh); -+extern bool BCMINIT(sb_war16165)(sb_t *sbh); -+extern uint BCMINIT(sb_pcmciarev)(sb_t *sbh); -+extern uint BCMINIT(sb_boardvendor)(sb_t *sbh); -+extern uint BCMINIT(sb_boardtype)(sb_t *sbh); -+extern uint sb_bus(sb_t *sbh); -+extern uint sb_buscoretype(sb_t *sbh); -+extern uint sb_buscorerev(sb_t *sbh); -+extern uint sb_corelist(sb_t *sbh, uint coreid[]); -+extern uint sb_coreid(sb_t *sbh); -+extern uint sb_coreidx(sb_t *sbh); -+extern uint sb_coreunit(sb_t *sbh); -+extern uint sb_corevendor(sb_t *sbh); -+extern uint sb_corerev(sb_t *sbh); -+extern void *sb_osh(sb_t *sbh); -+extern void *sb_coreregs(sb_t *sbh); -+extern uint32 sb_coreflags(sb_t *sbh, uint32 mask, uint32 val); -+extern uint32 sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val); -+extern bool sb_iscoreup(sb_t *sbh); -+extern void *sb_setcoreidx(sb_t *sbh, uint coreidx); -+extern void *sb_setcore(sb_t *sbh, uint coreid, uint coreunit); -+extern int sb_corebist(sb_t *sbh, uint coreid, uint coreunit); -+extern void sb_commit(sb_t *sbh); -+extern uint32 sb_base(uint32 admatch); -+extern uint32 sb_size(uint32 admatch); -+extern void sb_core_reset(sb_t *sbh, uint32 bits); -+extern void sb_core_tofixup(sb_t *sbh); -+extern void sb_core_disable(sb_t *sbh, uint32 bits); -+extern uint32 sb_clock_rate(uint32 pll_type, uint32 n, uint32 m); -+extern uint32 sb_clock(sb_t *sbh); -+extern void sb_pci_setup(sb_t *sbh, uint coremask); -+extern void sb_pcmcia_init(sb_t *sbh); -+extern void sb_watchdog(sb_t *sbh, uint ticks); -+extern void *sb_gpiosetcore(sb_t *sbh); -+extern uint32 sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); -+extern uint32 sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); -+extern uint32 sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); -+extern uint32 sb_gpioin(sb_t *sbh); -+extern uint32 sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); -+extern uint32 sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); -+extern uint32 sb_gpioled(sb_t *sbh, uint32 mask, uint32 val); -+extern uint32 sb_gpioreserve(sb_t *sbh, uint32 gpio_num, uint8 priority); -+extern uint32 sb_gpiorelease(sb_t *sbh, uint32 gpio_num, uint8 priority); -+ -+extern void sb_clkctl_init(sb_t *sbh); -+extern uint16 sb_clkctl_fast_pwrup_delay(sb_t *sbh); -+extern bool sb_clkctl_clk(sb_t *sbh, uint mode); -+extern int sb_clkctl_xtal(sb_t *sbh, uint what, bool on); -+extern void sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, -+ void *intrsrestore_fn, void *intrsenabled_fn, void *intr_arg); -+extern uint32 sb_set_initiator_to(sb_t *sbh, uint32 to); -+extern void sb_corepciid(sb_t *sbh, uint16 *pcivendor, uint16 *pcidevice, -+ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif); -+extern uint sb_pcie_readreg(void *sbh, void* arg1, uint offset); -+extern uint sb_pcie_writereg(sb_t *sbh, void *arg1, uint offset, uint val); -+extern uint32 sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 val); -+ ++#define Index_Invalidate_I 0x00 ++#define Index_Writeback_Inv_D 0x01 ++#define Index_Invalidate_SI 0x02 ++#define Index_Writeback_Inv_SD 0x03 ++#define Index_Load_Tag_I 0x04 ++#define Index_Load_Tag_D 0x05 ++#define Index_Load_Tag_SI 0x06 ++#define Index_Load_Tag_SD 0x07 ++#define Index_Store_Tag_I 0x08 ++#define Index_Store_Tag_D 0x09 ++#define Index_Store_Tag_SI 0x0A ++#define Index_Store_Tag_SD 0x0B ++#define Create_Dirty_Excl_D 0x0d ++#define Create_Dirty_Excl_SD 0x0f ++#define Hit_Invalidate_I 0x10 ++#define Hit_Invalidate_D 0x11 ++#define Hit_Invalidate_SI 0x12 ++#define Hit_Invalidate_SD 0x13 ++#define Fill_I 0x14 ++#define Hit_Writeback_Inv_D 0x15 ++ /* 0x16 is unused */ ++#define Hit_Writeback_Inv_SD 0x17 ++#define R5K_Page_Invalidate_S 0x17 ++#define Hit_Writeback_I 0x18 ++#define Hit_Writeback_D 0x19 ++ /* 0x1a is unused */ ++#define Hit_Writeback_SD 0x1b ++ /* 0x1c is unused */ ++ /* 0x1e is unused */ ++#define Hit_Set_Virtual_SI 0x1e ++#define Hit_Set_Virtual_SD 0x1f ++#endif /* !Index_Invalidate_I */ + + +/* -+* Build device path. Path size must be >= SB_DEVPATH_BUFSZ. -+* The returned path is NULL terminated and has trailing '/'. -+* Return 0 on success, nonzero otherwise. -+*/ -+extern int sb_devpath(sb_t *sbh, char *path, int size); ++ * R4x00 interrupt enable / cause bits ++ */ ++#define IE_SW0 (_ULCAST_(1) << 8) ++#define IE_SW1 (_ULCAST_(1) << 9) ++#define IE_IRQ0 (_ULCAST_(1) << 10) ++#define IE_IRQ1 (_ULCAST_(1) << 11) ++#define IE_IRQ2 (_ULCAST_(1) << 12) ++#define IE_IRQ3 (_ULCAST_(1) << 13) ++#define IE_IRQ4 (_ULCAST_(1) << 14) ++#define IE_IRQ5 (_ULCAST_(1) << 15) + -+/* clkctl xtal what flags */ -+#define XTAL 0x1 /* primary crystal oscillator (2050) */ -+#define PLL 0x2 /* main chip pll */ ++#ifndef ST0_UM ++/* ++ * Bitfields in the mips32 cp0 status register ++ */ ++#define ST0_IE 0x00000001 ++#define ST0_EXL 0x00000002 ++#define ST0_ERL 0x00000004 ++#define ST0_UM 0x00000010 ++#define ST0_SWINT0 0x00000100 ++#define ST0_SWINT1 0x00000200 ++#define ST0_HWINT0 0x00000400 ++#define ST0_HWINT1 0x00000800 ++#define ST0_HWINT2 0x00001000 ++#define ST0_HWINT3 0x00002000 ++#define ST0_HWINT4 0x00004000 ++#define ST0_HWINT5 0x00008000 ++#define ST0_IM 0x0000ff00 ++#define ST0_NMI 0x00080000 ++#define ST0_SR 0x00100000 ++#define ST0_TS 0x00200000 ++#define ST0_BEV 0x00400000 ++#define ST0_RE 0x02000000 ++#define ST0_RP 0x08000000 ++#define ST0_CU 0xf0000000 ++#define ST0_CU0 0x10000000 ++#define ST0_CU1 0x20000000 ++#define ST0_CU2 0x40000000 ++#define ST0_CU3 0x80000000 ++#endif /* !ST0_UM */ + -+/* clkctl clk mode */ -+#define CLK_FAST 0 /* force fast (pll) clock */ -+#define CLK_DYNAMIC 2 /* enable dynamic clock control */ + ++/* ++ * Bitfields in the mips32 cp0 cause register ++ */ ++#define C_EXC 0x0000007c ++#define C_EXC_SHIFT 2 ++#define C_INT 0x0000ff00 ++#define C_INT_SHIFT 8 ++#define C_SW0 (_ULCAST_(1) << 8) ++#define C_SW1 (_ULCAST_(1) << 9) ++#define C_IRQ0 (_ULCAST_(1) << 10) ++#define C_IRQ1 (_ULCAST_(1) << 11) ++#define C_IRQ2 (_ULCAST_(1) << 12) ++#define C_IRQ3 (_ULCAST_(1) << 13) ++#define C_IRQ4 (_ULCAST_(1) << 14) ++#define C_IRQ5 (_ULCAST_(1) << 15) ++#define C_WP 0x00400000 ++#define C_IV 0x00800000 ++#define C_CE 0x30000000 ++#define C_CE_SHIFT 28 ++#define C_BD 0x80000000 + -+/* GPIO usage priorities */ -+#define GPIO_DRV_PRIORITY 0 -+#define GPIO_APP_PRIORITY 1 ++/* Values in C_EXC */ ++#define EXC_INT 0 ++#define EXC_TLBM 1 ++#define EXC_TLBL 2 ++#define EXC_TLBS 3 ++#define EXC_AEL 4 ++#define EXC_AES 5 ++#define EXC_IBE 6 ++#define EXC_DBE 7 ++#define EXC_SYS 8 ++#define EXC_BPT 9 ++#define EXC_RI 10 ++#define EXC_CU 11 ++#define EXC_OV 12 ++#define EXC_TR 13 ++#define EXC_WATCH 23 ++#define EXC_MCHK 24 + -+/* device path */ -+#define SB_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ + -+#endif /* _sbutils_h_ */ -diff -Naur linux.old/arch/mips/bcm947xx/include/sflash.h linux.dev/arch/mips/bcm947xx/include/sflash.h ---- linux.old/arch/mips/bcm947xx/include/sflash.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/sflash.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,36 @@ +/* -+ * Broadcom SiliconBackplane chipcommon serial flash interface -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ ++ * Bits in the cp0 config register. + */ ++#define CONF_CM_CACHABLE_NO_WA 0 ++#define CONF_CM_CACHABLE_WA 1 ++#define CONF_CM_UNCACHED 2 ++#define CONF_CM_CACHABLE_NONCOHERENT 3 ++#define CONF_CM_CACHABLE_CE 4 ++#define CONF_CM_CACHABLE_COW 5 ++#define CONF_CM_CACHABLE_CUW 6 ++#define CONF_CM_CACHABLE_ACCELERATED 7 ++#define CONF_CM_CMASK 7 ++#define CONF_CU (_ULCAST_(1) << 3) ++#define CONF_DB (_ULCAST_(1) << 4) ++#define CONF_IB (_ULCAST_(1) << 5) ++#define CONF_SE (_ULCAST_(1) << 12) ++#ifndef CONF_BE /* duplicate in mipsregs.h */ ++#define CONF_BE (_ULCAST_(1) << 15) ++#endif ++#define CONF_SC (_ULCAST_(1) << 17) ++#define CONF_AC (_ULCAST_(1) << 23) ++#define CONF_HALT (_ULCAST_(1) << 25) ++#ifndef CONF_M /* duplicate in mipsregs.h */ ++#define CONF_M (_ULCAST_(1) << 31) ++#endif + -+#ifndef _sflash_h_ -+#define _sflash_h_ + -+#include -+#include ++/* ++ * Bits in the cp0 config register select 1. ++ */ ++#define CONF1_FP 0x00000001 /* FPU present */ ++#define CONF1_EP 0x00000002 /* EJTAG present */ ++#define CONF1_CA 0x00000004 /* mips16 implemented */ ++#define CONF1_WR 0x00000008 /* Watch registers present */ ++#define CONF1_PC 0x00000010 /* Performance counters present */ ++#define CONF1_DA_SHIFT 7 /* D$ associativity */ ++#define CONF1_DA_MASK 0x00000380 ++#define CONF1_DA_BASE 1 ++#define CONF1_DL_SHIFT 10 /* D$ line size */ ++#define CONF1_DL_MASK 0x00001c00 ++#define CONF1_DL_BASE 2 ++#define CONF1_DS_SHIFT 13 /* D$ sets/way */ ++#define CONF1_DS_MASK 0x0000e000 ++#define CONF1_DS_BASE 64 ++#define CONF1_IA_SHIFT 16 /* I$ associativity */ ++#define CONF1_IA_MASK 0x00070000 ++#define CONF1_IA_BASE 1 ++#define CONF1_IL_SHIFT 19 /* I$ line size */ ++#define CONF1_IL_MASK 0x00380000 ++#define CONF1_IL_BASE 2 ++#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */ ++#define CONF1_IS_MASK 0x01c00000 ++#define CONF1_IS_BASE 64 ++#define CONF1_MS_MASK 0x7e000000 /* Number of tlb entries */ ++#define CONF1_MS_SHIFT 25 + -+struct sflash { -+ uint blocksize; /* Block size */ -+ uint numblocks; /* Number of blocks */ -+ uint32 type; /* Type */ -+ uint size; /* Total size in bytes */ -+}; ++/* PRID register */ ++#define PRID_COPT_MASK 0xff000000 ++#define PRID_COMP_MASK 0x00ff0000 ++#define PRID_IMP_MASK 0x0000ff00 ++#define PRID_REV_MASK 0x000000ff + -+/* Utility functions */ -+extern int sflash_poll(chipcregs_t *cc, uint offset); -+extern int sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf); -+extern int sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf); -+extern int sflash_erase(chipcregs_t *cc, uint offset); -+extern int sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf); -+extern struct sflash * sflash_init(chipcregs_t *cc); ++#define PRID_COMP_LEGACY 0x000000 ++#define PRID_COMP_MIPS 0x010000 ++#define PRID_COMP_BROADCOM 0x020000 ++#define PRID_COMP_ALCHEMY 0x030000 ++#define PRID_COMP_SIBYTE 0x040000 ++#define PRID_IMP_BCM4710 0x4000 ++#define PRID_IMP_BCM3302 0x9000 ++#define PRID_IMP_BCM3303 0x9100 + -+#endif /* _sflash_h_ */ -diff -Naur linux.old/arch/mips/bcm947xx/include/trxhdr.h linux.dev/arch/mips/bcm947xx/include/trxhdr.h ---- linux.old/arch/mips/bcm947xx/include/trxhdr.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/trxhdr.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,33 @@ -+/* -+ * TRX image file header format. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ -+ */ ++#define PRID_IMP_UNKNOWN 0xff00 + -+#include ++#define BCM330X(id) \ ++ (((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == \ ++ (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) || \ ++ ((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == \ ++ (PRID_COMP_BROADCOM | PRID_IMP_BCM3303))) + -+#define TRX_MAGIC 0x30524448 /* "HDR0" */ -+#define TRX_VERSION 1 -+#define TRX_MAX_LEN 0x3A0000 -+#define TRX_NO_HEADER 1 /* Do not write TRX header */ -+#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ -+#define TRX_MAX_OFFSET 3 -+ -+struct trx_header { -+ uint32 magic; /* "HDR0" */ -+ uint32 len; /* Length of file including header */ -+ uint32 crc32; /* 32-bit CRC from flag_version to end of file */ -+ uint32 flag_version; /* 0:15 flags, 16:31 version */ -+ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ -+}; -+ -+/* Compatibility */ -+typedef struct trx_header TRXHDR, *PTRXHDR; -diff -Naur linux.old/arch/mips/bcm947xx/include/typedefs.h linux.dev/arch/mips/bcm947xx/include/typedefs.h ---- linux.old/arch/mips/bcm947xx/include/typedefs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/include/typedefs.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,326 @@ -+/* -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ -+ -+#ifndef _TYPEDEFS_H_ -+#define _TYPEDEFS_H_ -+ -+ -+/* Define 'SITE_TYPEDEFS' in the compile to include a site specific -+ * typedef file "site_typedefs.h". -+ * -+ * If 'SITE_TYPEDEFS' is not defined, then the "Inferred Typedefs" -+ * section of this file makes inferences about the compile environment -+ * based on defined symbols and possibly compiler pragmas. -+ * -+ * Following these two sections is the "Default Typedefs" -+ * section. This section is only prcessed if 'USE_TYPEDEF_DEFAULTS' is -+ * defined. This section has a default set of typedefs and a few -+ * proprocessor symbols (TRUE, FALSE, NULL, ...). -+ */ ++/* Bits in C0_BROADCOM */ ++#define BRCM_PFC_AVAIL 0x20000000 /* PFC is available */ ++#define BRCM_DC_ENABLE 0x40000000 /* Enable Data $ */ ++#define BRCM_IC_ENABLE 0x80000000 /* Enable Instruction $ */ ++#define BRCM_PFC_ENABLE 0x00400000 /* Obsolete? Enable PFC (at least on 4310) */ ++#define BRCM_CLF_ENABLE 0x00100000 /* Enable cache line first feature */ + -+#ifdef SITE_TYPEDEFS ++/* PreFetch Cache aka Read Ahead Cache */ + -+/******************************************************************************* -+ * Site Specific Typedefs -+ *******************************************************************************/ ++#define PFC_CR0 0xff400000 /* control reg 0 */ ++#define PFC_CR1 0xff400004 /* control reg 1 */ + -+#include "site_typedefs.h" ++/* PFC operations */ ++#define PFC_I 0x00000001 /* Enable PFC use for instructions */ ++#define PFC_D 0x00000002 /* Enable PFC use for data */ ++#define PFC_PFI 0x00000004 /* Enable seq. prefetch for instructions */ ++#define PFC_PFD 0x00000008 /* Enable seq. prefetch for data */ ++#define PFC_CINV 0x00000010 /* Enable selective (i/d) cacheop flushing */ ++#define PFC_NCH 0x00000020 /* Disable flushing based on cacheops */ ++#define PFC_DPF 0x00000040 /* Enable directional prefetching */ ++#define PFC_FLUSH 0x00000100 /* Flush the PFC */ ++#define PFC_BRR 0x40000000 /* Bus error indication */ ++#define PFC_PWR 0x80000000 /* Disable power saving (clock gating) */ + -+#else ++/* Handy defaults */ ++#define PFC_DISABLED 0 ++#define PFC_AUTO 0xffffffff /* auto select the default mode */ ++#define PFC_INST (PFC_I | PFC_PFI | PFC_CINV) ++#define PFC_INST_NOPF (PFC_I | PFC_CINV) ++#define PFC_DATA (PFC_D | PFC_PFD | PFC_CINV) ++#define PFC_DATA_NOPF (PFC_D | PFC_CINV) ++#define PFC_I_AND_D (PFC_INST | PFC_DATA) ++#define PFC_I_AND_D_NOPF (PFC_INST_NOPF | PFC_DATA_NOPF) + -+/******************************************************************************* -+ * Inferred Typedefs -+ *******************************************************************************/ ++#ifndef _LANGUAGE_ASSEMBLY + -+/* Infer the compile environment based on preprocessor symbols and pramas. -+ * Override type definitions as needed, and include configuration dependent -+ * header files to define types. ++/* ++ * Macros to access the system control coprocessor + */ + -+#ifdef __cplusplus ++#define MFC0(source, sel) \ ++({ \ ++ int __res; \ ++ __asm__ __volatile__(" \ ++ .set\tnoreorder; \ ++ .set\tnoat; \ ++ .word\t"STR(0x40010000 | ((source) << 11) | (sel))"; \ ++ move\t%0, $1; \ ++ .set\tat; \ ++ .set\treorder" \ ++ :"=r" (__res) \ ++ : \ ++ :"$1"); \ ++ __res; \ ++}) + -+#define TYPEDEF_BOOL -+#ifndef FALSE -+#define FALSE false -+#endif -+#ifndef TRUE -+#define TRUE true -+#endif ++#define MTC0(source, sel, value) \ ++do { \ ++ __asm__ __volatile__(" \ ++ .set\tnoreorder; \ ++ .set\tnoat; \ ++ move\t$1, %z0; \ ++ .word\t"STR(0x40810000 | ((source) << 11) | (sel))"; \ ++ .set\tat; \ ++ .set\treorder" \ ++ : \ ++ :"jr" (value) \ ++ :"$1"); \ ++} while (0) + -+#else /* ! __cplusplus */ ++#define get_c0_count() \ ++({ \ ++ int __res; \ ++ __asm__ __volatile__(" \ ++ .set\tnoreorder; \ ++ .set\tnoat; \ ++ mfc0\t%0, $9; \ ++ .set\tat; \ ++ .set\treorder" \ ++ :"=r" (__res)); \ ++ __res; \ ++}) + -+#if defined(_WIN32) ++static INLINE void icache_probe(uint32 config1, uint *size, uint *lsize) ++{ ++ uint lsz, sets, ways; + -+#define TYPEDEF_BOOL -+typedef unsigned char bool; /* consistent w/BOOL */ ++ /* Instruction Cache Size = Associativity * Line Size * Sets Per Way */ ++ if ((lsz = ((config1 & CONF1_IL_MASK) >> CONF1_IL_SHIFT))) ++ lsz = CONF1_IL_BASE << lsz; ++ sets = CONF1_IS_BASE << ((config1 & CONF1_IS_MASK) >> CONF1_IS_SHIFT); ++ ways = CONF1_IA_BASE + ((config1 & CONF1_IA_MASK) >> CONF1_IA_SHIFT); ++ *size = lsz * sets * ways; ++ *lsize = lsz; ++} + -+#endif /* _WIN32 */ ++static INLINE void dcache_probe(uint32 config1, uint *size, uint *lsize) ++{ ++ uint lsz, sets, ways; + -+#endif /* ! __cplusplus */ ++ /* Data Cache Size = Associativity * Line Size * Sets Per Way */ ++ if ((lsz = ((config1 & CONF1_DL_MASK) >> CONF1_DL_SHIFT))) ++ lsz = CONF1_DL_BASE << lsz; ++ sets = CONF1_DS_BASE << ((config1 & CONF1_DS_MASK) >> CONF1_DS_SHIFT); ++ ways = CONF1_DA_BASE + ((config1 & CONF1_DA_MASK) >> CONF1_DA_SHIFT); ++ *size = lsz * sets * ways; ++ *lsize = lsz; ++} + -+/* use the Windows ULONG_PTR type when compiling for 64 bit */ -+#if defined(_WIN64) -+#include -+#define TYPEDEF_UINTPTR -+typedef ULONG_PTR uintptr; -+#endif ++#define cache_op(base, op) \ ++ __asm__ __volatile__(" \ ++ .set noreorder; \ ++ .set mips3; \ ++ cache %1, (%0); \ ++ .set mips0; \ ++ .set reorder" \ ++ : \ ++ : "r" (base), \ ++ "i" (op)); + -+#ifdef _HNDRTE_ -+typedef long unsigned int size_t; -+#endif ++#define cache_unroll4(base, delta, op) \ ++ __asm__ __volatile__(" \ ++ .set noreorder; \ ++ .set mips3; \ ++ cache %1, 0(%0); \ ++ cache %1, delta(%0); \ ++ cache %1, (2 * delta)(%0); \ ++ cache %1, (3 * delta)(%0); \ ++ .set mips0; \ ++ .set reorder" \ ++ : \ ++ : "r" (base), \ ++ "i" (op)); + -+#ifdef _MSC_VER /* Microsoft C */ -+#define TYPEDEF_INT64 -+#define TYPEDEF_UINT64 -+typedef signed __int64 int64; -+typedef unsigned __int64 uint64; -+#endif ++#endif /* !_LANGUAGE_ASSEMBLY */ + -+#if defined(MACOSX) && defined(KERNEL) -+#define TYPEDEF_BOOL -+#endif ++#endif /* _MISPINC_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/osl.h linux.dev/arch/mips/bcm947xx/include/osl.h +--- linux.old/arch/mips/bcm947xx/include/osl.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/osl.h 2006-05-02 17:40:43.000000000 +0200 +@@ -0,0 +1,179 @@ ++#ifndef __osl_h ++#define __osl_h + ++#include ++#include ++#include ++#include ++#include + -+#if defined(linux) -+#define TYPEDEF_UINT -+#define TYPEDEF_USHORT -+#define TYPEDEF_ULONG -+#endif ++#define ASSERT(n) + -+#if !defined(linux) && !defined(_WIN32) && !defined(PMON) && !defined(_CFE_) && !defined(_HNDRTE_) && !defined(_MINOSL_) -+#define TYPEDEF_UINT -+#define TYPEDEF_USHORT -+#endif ++/* Pkttag flag should be part of public information */ ++struct osl_pubinfo { ++ bool pkttag; ++ uint pktalloced; /* Number of allocated packet buffers */ ++}; + ++struct osl_info { ++ struct osl_pubinfo pub; ++ uint magic; ++ void *pdev; ++ uint malloced; ++ uint failed; ++ void *dbgmem_list; ++}; + -+/* Do not support the (u)int64 types with strict ansi for GNU C */ -+#if defined(__GNUC__) && defined(__STRICT_ANSI__) -+#define TYPEDEF_INT64 -+#define TYPEDEF_UINT64 -+#endif ++typedef struct osl_info osl_t; + -+/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode -+ * for singned or unsigned */ -+#if defined(__ICL) ++#define PCI_CFG_RETRY 10 + -+#define TYPEDEF_INT64 ++/* map/unmap direction */ ++#define DMA_TX 1 /* TX direction for DMA */ ++#define DMA_RX 2 /* RX direction for DMA */ + -+#if defined(__STDC__) -+#define TYPEDEF_UINT64 -+#endif ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val))) + -+#endif /* __ICL */ ++/* bcopy, bcmp, and bzero */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) + ++/* uncached virtual address */ ++#ifdef mips ++#define OSL_UNCACHED(va) KSEG1ADDR((va)) ++#include ++#else ++#define OSL_UNCACHED(va) (va) ++#endif /* mips */ + -+#if !defined(_WIN32) && !defined(PMON) && !defined(_CFE_) && !defined(_HNDRTE_) && !defined(_MINOSL_) + -+/* pick up ushort & uint from standard types.h */ -+#if defined(linux) && defined(__KERNEL__) ++#ifndef IL_BIGENDIAN ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? readb((volatile uint8*)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? readw((volatile uint16*)(r)) : \ ++ readl((volatile uint32*)(r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \ ++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \ ++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ ++ } \ ++} while (0) ++#else /* IL_BIGENDIAN */ ++#define R_REG(osh, r) ({ \ ++ __typeof(*(r)) __osl_v; \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = readb((volatile uint8*)((uint32)r^3)); break; \ ++ case sizeof(uint16): __osl_v = readw((volatile uint16*)((uint32)r^2)); break; \ ++ case sizeof(uint32): __osl_v = readl((volatile uint32*)(r)); break; \ ++ } \ ++ __osl_v; \ ++}) ++#define W_REG(osh, r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)((uint32)r^3)); break; \ ++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)((uint32)r^2)); break; \ ++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ ++ } \ ++} while (0) ++#endif /* IL_BIGENDIAN */ + -+#include /* sys/types.h and linux/types.h are oil and water */ ++/* dereference an address that may cause a bus exception */ ++#define BUSPROBE(val, addr) get_dbe((val), (addr)) ++#include + -+#else ++/* map/unmap physical to virtual I/O */ ++#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) ++#define REG_UNMAP(va) iounmap((void *)(va)) + -+#include ++/* shared (dma-able) memory access macros */ ++#define R_SM(r) *(r) ++#define W_SM(r, v) (*(r) = (v)) ++#define BZERO_SM(r, len) memset((r), '\0', (len)) + -+#endif ++#define MALLOC(osh, size) kmalloc((size), GFP_ATOMIC) ++#define MFREE(osh, addr, size) kfree((addr)) ++#define MALLOCED(osh) (0) + -+#endif /* !_WIN32 && !PMON && !_CFE_ && !_HNDRTE_ && !_MINOSL_ */ ++#define osl_delay OSL_DELAY ++static inline void OSL_DELAY(uint usec) ++{ ++ uint d; + -+#if defined(MACOSX) && defined(KERNEL) -+#include -+#endif ++ while (usec > 0) { ++ d = MIN(usec, 1000); ++ udelay(d); ++ usec -= d; ++ } ++} + ++static inline void ++bcm_mdelay(uint ms) ++{ ++ uint i; + -+/* use the default typedefs in the next section of this file */ -+#define USE_TYPEDEF_DEFAULTS ++ for (i = 0; i < ms; i++) { ++ OSL_DELAY(1000); ++ } ++} + -+#endif /* SITE_TYPEDEFS */ + ++#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) ++#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) + -+/******************************************************************************* -+ * Default Typedefs -+ *******************************************************************************/ ++#define OSL_PCI_READ_CONFIG(osh, offset, size) \ ++ osl_pci_read_config((osh), (offset), (size)) + -+#ifdef USE_TYPEDEF_DEFAULTS -+#undef USE_TYPEDEF_DEFAULTS ++static inline uint32 ++osl_pci_read_config(osl_t *osh, uint offset, uint size) ++{ ++ uint val; ++ uint retry = PCI_CFG_RETRY; + -+#ifndef TYPEDEF_BOOL -+typedef /*@abstract@*/ unsigned char bool; -+#endif ++ do { ++ pci_read_config_dword(osh->pdev, offset, &val); ++ if (val != 0xffffffff) ++ break; ++ } while (retry--); + -+/*----------------------- define uchar, ushort, uint, ulong ------------------*/ ++ return (val); ++} + -+#ifndef TYPEDEF_UCHAR -+typedef unsigned char uchar; -+#endif ++#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ ++ osl_pci_write_config((osh), (offset), (size), (val)) ++static inline void ++osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) ++{ ++ uint retry = PCI_CFG_RETRY; + -+#ifndef TYPEDEF_USHORT -+typedef unsigned short ushort; -+#endif ++ do { ++ pci_write_config_dword(osh->pdev, offset, val); ++ if (offset != PCI_BAR0_WIN) ++ break; ++ if (osl_pci_read_config(osh, offset, size) == val) ++ break; ++ } while (retry--); ++} + -+#ifndef TYPEDEF_UINT -+typedef unsigned int uint; -+#endif + -+#ifndef TYPEDEF_ULONG -+typedef unsigned long ulong; -+#endif ++/* return bus # for the pci device pointed by osh->pdev */ ++#define OSL_PCI_BUS(osh) osl_pci_bus(osh) ++static inline uint ++osl_pci_bus(osl_t *osh) ++{ ++ return ((struct pci_dev *)osh->pdev)->bus->number; ++} + -+/*----------------------- define [u]int8/16/32/64, uintptr --------------------*/ ++/* return slot # for the pci device pointed by osh->pdev */ ++#define OSL_PCI_SLOT(osh) osl_pci_slot(osh) ++static inline uint ++osl_pci_slot(osl_t *osh) ++{ ++ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); ++} + -+#ifndef TYPEDEF_UINT8 -+typedef unsigned char uint8; +#endif +diff -urN linux.old/arch/mips/bcm947xx/include/pcicfg.h linux.dev/arch/mips/bcm947xx/include/pcicfg.h +--- linux.old/arch/mips/bcm947xx/include/pcicfg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/pcicfg.h 2006-04-27 20:31:41.000000000 +0200 +@@ -0,0 +1,495 @@ ++/* ++ * pcicfg.h: PCI configuration constants and structures. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: pcicfg.h,v 1.1.1.11 2006/04/08 06:13:40 honor Exp $ ++ */ + -+#ifndef TYPEDEF_UINT16 -+typedef unsigned short uint16; -+#endif ++#ifndef _h_pcicfg_ ++#define _h_pcicfg_ + -+#ifndef TYPEDEF_UINT32 -+typedef unsigned int uint32; ++/* The following inside ifndef's so we don't collide with NTDDK.H */ ++#ifndef PCI_MAX_BUS ++#define PCI_MAX_BUS 0x100 +#endif -+ -+#ifndef TYPEDEF_UINT64 -+typedef unsigned long long uint64; ++#ifndef PCI_MAX_DEVICES ++#define PCI_MAX_DEVICES 0x20 +#endif -+ -+#ifndef TYPEDEF_UINTPTR -+typedef unsigned int uintptr; ++#ifndef PCI_MAX_FUNCTION ++#define PCI_MAX_FUNCTION 0x8 +#endif + -+#ifndef TYPEDEF_INT8 -+typedef signed char int8; ++#ifndef PCI_INVALID_VENDORID ++#define PCI_INVALID_VENDORID 0xffff +#endif -+ -+#ifndef TYPEDEF_INT16 -+typedef signed short int16; ++#ifndef PCI_INVALID_DEVICEID ++#define PCI_INVALID_DEVICEID 0xffff +#endif + -+#ifndef TYPEDEF_INT32 -+typedef signed int int32; -+#endif + -+#ifndef TYPEDEF_INT64 -+typedef signed long long int64; -+#endif ++/* Convert between bus-slot-function-register and config addresses */ + -+/*----------------------- define float32/64, float_t -----------------------*/ ++#define PCICFG_BUS_SHIFT 16 /* Bus shift */ ++#define PCICFG_SLOT_SHIFT 11 /* Slot shift */ ++#define PCICFG_FUN_SHIFT 8 /* Function shift */ ++#define PCICFG_OFF_SHIFT 0 /* Register shift */ + -+#ifndef TYPEDEF_FLOAT32 -+typedef float float32; -+#endif ++#define PCICFG_BUS_MASK 0xff /* Bus mask */ ++#define PCICFG_SLOT_MASK 0x1f /* Slot mask */ ++#define PCICFG_FUN_MASK 7 /* Function mask */ ++#define PCICFG_OFF_MASK 0xff /* Bus mask */ + -+#ifndef TYPEDEF_FLOAT64 -+typedef double float64; -+#endif ++#define PCI_CONFIG_ADDR(b, s, f, o) \ ++ ((((b) & PCICFG_BUS_MASK) << PCICFG_BUS_SHIFT) \ ++ | (((s) & PCICFG_SLOT_MASK) << PCICFG_SLOT_SHIFT) \ ++ | (((f) & PCICFG_FUN_MASK) << PCICFG_FUN_SHIFT) \ ++ | (((o) & PCICFG_OFF_MASK) << PCICFG_OFF_SHIFT)) + -+/* -+ * abstracted floating point type allows for compile time selection of -+ * single or double precision arithmetic. Compiling with -DFLOAT32 -+ * selects single precision; the default is double precision. -+ */ ++#define PCI_CONFIG_BUS(a) (((a) >> PCICFG_BUS_SHIFT) & PCICFG_BUS_MASK) ++#define PCI_CONFIG_SLOT(a) (((a) >> PCICFG_SLOT_SHIFT) & PCICFG_SLOT_MASK) ++#define PCI_CONFIG_FUN(a) (((a) >> PCICFG_FUN_SHIFT) & PCICFG_FUN_MASK) ++#define PCI_CONFIG_OFF(a) (((a) >> PCICFG_OFF_SHIFT) & PCICFG_OFF_MASK) + -+#ifndef TYPEDEF_FLOAT_T ++/* PCIE Config space accessing MACROS */ + -+#if defined(FLOAT32) -+typedef float32 float_t; -+#else /* default to double precision floating point */ -+typedef float64 float_t; -+#endif ++#define PCIECFG_BUS_SHIFT 24 /* Bus shift */ ++#define PCIECFG_SLOT_SHIFT 19 /* Slot/Device shift */ ++#define PCIECFG_FUN_SHIFT 16 /* Function shift */ ++#define PCIECFG_OFF_SHIFT 0 /* Register shift */ + -+#endif /* TYPEDEF_FLOAT_T */ ++#define PCIECFG_BUS_MASK 0xff /* Bus mask */ ++#define PCIECFG_SLOT_MASK 0x1f /* Slot/Device mask */ ++#define PCIECFG_FUN_MASK 7 /* Function mask */ ++#define PCIECFG_OFF_MASK 0x3ff /* Register mask */ + -+/*----------------------- define macro values -----------------------------*/ ++#define PCIE_CONFIG_ADDR(b, s, f, o) \ ++ ((((b) & PCIECFG_BUS_MASK) << PCIECFG_BUS_SHIFT) \ ++ | (((s) & PCIECFG_SLOT_MASK) << PCIECFG_SLOT_SHIFT) \ ++ | (((f) & PCIECFG_FUN_MASK) << PCIECFG_FUN_SHIFT) \ ++ | (((o) & PCIECFG_OFF_MASK) << PCIECFG_OFF_SHIFT)) + -+#ifndef FALSE -+#define FALSE 0 -+#endif ++#define PCIE_CONFIG_BUS(a) (((a) >> PCIECFG_BUS_SHIFT) & PCIECFG_BUS_MASK) ++#define PCIE_CONFIG_SLOT(a) (((a) >> PCIECFG_SLOT_SHIFT) & PCIECFG_SLOT_MASK) ++#define PCIE_CONFIG_FUN(a) (((a) >> PCIECFG_FUN_SHIFT) & PCIECFG_FUN_MASK) ++#define PCIE_CONFIG_OFF(a) (((a) >> PCIECFG_OFF_SHIFT) & PCIECFG_OFF_MASK) + -+#ifndef TRUE -+#define TRUE 1 -+#endif ++/* The actual config space */ + -+#ifndef NULL -+#define NULL 0 -+#endif ++#define PCI_BAR_MAX 6 + -+#ifndef OFF -+#define OFF 0 -+#endif ++#define PCI_ROM_BAR 8 + -+#ifndef ON -+#define ON 1 -+#endif ++#define PCR_RSVDA_MAX 2 + -+#define AUTO (-1) ++/* Bits in PCI bars' flags */ + -+/* Reclaiming text and data : -+ The following macros specify special linker sections that can be reclaimed -+ after a system is considered 'up'. -+ */ -+#if defined(__GNUC__) && defined(BCMRECLAIM) -+extern bool bcmreclaimed; -+#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini." #_data))) _data##_ini -+#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini." #_fn))) _fn##_ini -+#define BCMINIT(_id) _id##_ini -+#else -+#define BCMINITDATA(_data) _data -+#define BCMINITFN(_fn) _fn -+#define BCMINIT(_id) _id -+#define bcmreclaimed 0 -+#endif ++#define PCIBAR_FLAGS 0xf ++#define PCIBAR_IO 0x1 ++#define PCIBAR_MEM1M 0x2 ++#define PCIBAR_MEM64 0x4 ++#define PCIBAR_PREFETCH 0x8 ++#define PCIBAR_MEM32_MASK 0xFFFFFF80 + -+/*----------------------- define PTRSZ, INLINE ----------------------------*/ ++/* pci config status reg has a bit to indicate that capability ptr is present */ + -+#ifndef PTRSZ -+#define PTRSZ sizeof (char*) -+#endif ++#define PCI_CAPPTR_PRESENT 0x0010 + -+#ifndef INLINE ++typedef struct _pci_config_regs { ++ unsigned short vendor; ++ unsigned short device; ++ unsigned short command; ++ unsigned short status; ++ unsigned char rev_id; ++ unsigned char prog_if; ++ unsigned char sub_class; ++ unsigned char base_class; ++ unsigned char cache_line_size; ++ unsigned char latency_timer; ++ unsigned char header_type; ++ unsigned char bist; ++ unsigned long base[PCI_BAR_MAX]; ++ unsigned long cardbus_cis; ++ unsigned short subsys_vendor; ++ unsigned short subsys_id; ++ unsigned long baserom; ++ unsigned long rsvd_a[PCR_RSVDA_MAX]; ++ unsigned char int_line; ++ unsigned char int_pin; ++ unsigned char min_gnt; ++ unsigned char max_lat; ++ unsigned char dev_dep[192]; ++} pci_config_regs; + -+#ifdef _MSC_VER ++#define SZPCR (sizeof (pci_config_regs)) ++#define MINSZPCR 64 /* offsetof (dev_dep[0] */ + -+#define INLINE __inline ++/* A structure for the config registers is nice, but in most ++ * systems the config space is not memory mapped, so we need ++ * filed offsetts. :-( ++ */ ++#define PCI_CFG_VID 0 ++#define PCI_CFG_DID 2 ++#define PCI_CFG_CMD 4 ++#define PCI_CFG_STAT 6 ++#define PCI_CFG_REV 8 ++#define PCI_CFG_PROGIF 9 ++#define PCI_CFG_SUBCL 0xa ++#define PCI_CFG_BASECL 0xb ++#define PCI_CFG_CLSZ 0xc ++#define PCI_CFG_LATTIM 0xd ++#define PCI_CFG_HDR 0xe ++#define PCI_CFG_BIST 0xf ++#define PCI_CFG_BAR0 0x10 ++#define PCI_CFG_BAR1 0x14 ++#define PCI_CFG_BAR2 0x18 ++#define PCI_CFG_BAR3 0x1c ++#define PCI_CFG_BAR4 0x20 ++#define PCI_CFG_BAR5 0x24 ++#define PCI_CFG_CIS 0x28 ++#define PCI_CFG_SVID 0x2c ++#define PCI_CFG_SSID 0x2e ++#define PCI_CFG_ROMBAR 0x30 ++#define PCI_CFG_CAPPTR 0x34 ++#define PCI_CFG_INT 0x3c ++#define PCI_CFG_PIN 0x3d ++#define PCI_CFG_MINGNT 0x3e ++#define PCI_CFG_MAXLAT 0x3f + -+#elif __GNUC__ ++#ifdef __NetBSD__ ++#undef PCI_CLASS_DISPLAY ++#undef PCI_CLASS_MEMORY ++#undef PCI_CLASS_BRIDGE ++#undef PCI_CLASS_INPUT ++#undef PCI_CLASS_DOCK ++#endif /* __NetBSD__ */ + -+#define INLINE __inline__ ++/* Classes and subclasses */ + -+#else ++typedef enum { ++ PCI_CLASS_OLD = 0, ++ PCI_CLASS_DASDI, ++ PCI_CLASS_NET, ++ PCI_CLASS_DISPLAY, ++ PCI_CLASS_MMEDIA, ++ PCI_CLASS_MEMORY, ++ PCI_CLASS_BRIDGE, ++ PCI_CLASS_COMM, ++ PCI_CLASS_BASE, ++ PCI_CLASS_INPUT, ++ PCI_CLASS_DOCK, ++ PCI_CLASS_CPU, ++ PCI_CLASS_SERIAL, ++ PCI_CLASS_INTELLIGENT = 0xe, ++ PCI_CLASS_SATELLITE, ++ PCI_CLASS_CRYPT, ++ PCI_CLASS_DSP, ++ PCI_CLASS_XOR = 0xfe ++} pci_classes; + -+#define INLINE ++typedef enum { ++ PCI_DASDI_SCSI, ++ PCI_DASDI_IDE, ++ PCI_DASDI_FLOPPY, ++ PCI_DASDI_IPI, ++ PCI_DASDI_RAID, ++ PCI_DASDI_OTHER = 0x80 ++} pci_dasdi_subclasses; + -+#endif /* _MSC_VER */ ++typedef enum { ++ PCI_NET_ETHER, ++ PCI_NET_TOKEN, ++ PCI_NET_FDDI, ++ PCI_NET_ATM, ++ PCI_NET_OTHER = 0x80 ++} pci_net_subclasses; + -+#endif /* INLINE */ ++typedef enum { ++ PCI_DISPLAY_VGA, ++ PCI_DISPLAY_XGA, ++ PCI_DISPLAY_3D, ++ PCI_DISPLAY_OTHER = 0x80 ++} pci_display_subclasses; + -+#undef TYPEDEF_BOOL -+#undef TYPEDEF_UCHAR -+#undef TYPEDEF_USHORT -+#undef TYPEDEF_UINT -+#undef TYPEDEF_ULONG -+#undef TYPEDEF_UINT8 -+#undef TYPEDEF_UINT16 -+#undef TYPEDEF_UINT32 -+#undef TYPEDEF_UINT64 -+#undef TYPEDEF_UINTPTR -+#undef TYPEDEF_INT8 -+#undef TYPEDEF_INT16 -+#undef TYPEDEF_INT32 -+#undef TYPEDEF_INT64 -+#undef TYPEDEF_FLOAT32 -+#undef TYPEDEF_FLOAT64 -+#undef TYPEDEF_FLOAT_T ++typedef enum { ++ PCI_MMEDIA_VIDEO, ++ PCI_MMEDIA_AUDIO, ++ PCI_MMEDIA_PHONE, ++ PCI_MEDIA_OTHER = 0x80 ++} pci_mmedia_subclasses; + -+#endif /* USE_TYPEDEF_DEFAULTS */ ++typedef enum { ++ PCI_MEMORY_RAM, ++ PCI_MEMORY_FLASH, ++ PCI_MEMORY_OTHER = 0x80 ++} pci_memory_subclasses; + -+#endif /* _TYPEDEFS_H_ */ -diff -Naur linux.old/arch/mips/bcm947xx/nvram.c linux.dev/arch/mips/bcm947xx/nvram.c ---- linux.old/arch/mips/bcm947xx/nvram.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/nvram.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,320 @@ -+/* -+ * NVRAM variable manipulation (common) -+ * -+ * Copyright 2004, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ */ ++typedef enum { ++ PCI_BRIDGE_HOST, ++ PCI_BRIDGE_ISA, ++ PCI_BRIDGE_EISA, ++ PCI_BRIDGE_MC, ++ PCI_BRIDGE_PCI, ++ PCI_BRIDGE_PCMCIA, ++ PCI_BRIDGE_NUBUS, ++ PCI_BRIDGE_CARDBUS, ++ PCI_BRIDGE_RACEWAY, ++ PCI_BRIDGE_OTHER = 0x80 ++} pci_bridge_subclasses; + -+#include -+#include -+#include -+#include -+#include -+#include ++typedef enum { ++ PCI_COMM_UART, ++ PCI_COMM_PARALLEL, ++ PCI_COMM_MULTIUART, ++ PCI_COMM_MODEM, ++ PCI_COMM_OTHER = 0x80 ++} pci_comm_subclasses; + -+extern struct nvram_tuple * BCMINIT(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value); -+extern void BCMINIT(_nvram_free)(struct nvram_tuple *t); -+extern int BCMINIT(_nvram_read)(void *buf); ++typedef enum { ++ PCI_BASE_PIC, ++ PCI_BASE_DMA, ++ PCI_BASE_TIMER, ++ PCI_BASE_RTC, ++ PCI_BASE_PCI_HOTPLUG, ++ PCI_BASE_OTHER = 0x80 ++} pci_base_subclasses; + -+char * BCMINIT(_nvram_get)(const char *name); -+int BCMINIT(_nvram_set)(const char *name, const char *value); -+int BCMINIT(_nvram_unset)(const char *name); -+int BCMINIT(_nvram_getall)(char *buf, int count); -+int BCMINIT(_nvram_commit)(struct nvram_header *header); -+int BCMINIT(_nvram_init)(void); -+void BCMINIT(_nvram_exit)(void); ++typedef enum { ++ PCI_INPUT_KBD, ++ PCI_INPUT_PEN, ++ PCI_INPUT_MOUSE, ++ PCI_INPUT_SCANNER, ++ PCI_INPUT_GAMEPORT, ++ PCI_INPUT_OTHER = 0x80 ++} pci_input_subclasses; + -+static struct nvram_tuple * BCMINITDATA(nvram_hash)[257]; -+static struct nvram_tuple * nvram_dead; ++typedef enum { ++ PCI_DOCK_GENERIC, ++ PCI_DOCK_OTHER = 0x80 ++} pci_dock_subclasses; + -+/* Free all tuples. Should be locked. */ -+static void -+BCMINITFN(nvram_free)(void) -+{ -+ uint i; -+ struct nvram_tuple *t, *next; ++typedef enum { ++ PCI_CPU_386, ++ PCI_CPU_486, ++ PCI_CPU_PENTIUM, ++ PCI_CPU_ALPHA = 0x10, ++ PCI_CPU_POWERPC = 0x20, ++ PCI_CPU_MIPS = 0x30, ++ PCI_CPU_COPROC = 0x40, ++ PCI_CPU_OTHER = 0x80 ++} pci_cpu_subclasses; + -+ /* Free hash table */ -+ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { -+ for (t = BCMINIT(nvram_hash)[i]; t; t = next) { -+ next = t->next; -+ BCMINIT(_nvram_free)(t); -+ } -+ BCMINIT(nvram_hash)[i] = NULL; -+ } ++typedef enum { ++ PCI_SERIAL_IEEE1394, ++ PCI_SERIAL_ACCESS, ++ PCI_SERIAL_SSA, ++ PCI_SERIAL_USB, ++ PCI_SERIAL_FIBER, ++ PCI_SERIAL_SMBUS, ++ PCI_SERIAL_OTHER = 0x80 ++} pci_serial_subclasses; + -+ /* Free dead table */ -+ for (t = nvram_dead; t; t = next) { -+ next = t->next; -+ BCMINIT(_nvram_free)(t); -+ } -+ nvram_dead = NULL; ++typedef enum { ++ PCI_INTELLIGENT_I2O ++} pci_intelligent_subclasses; + -+ /* Indicate to per-port code that all tuples have been freed */ -+ BCMINIT(_nvram_free)(NULL); -+} ++typedef enum { ++ PCI_SATELLITE_TV, ++ PCI_SATELLITE_AUDIO, ++ PCI_SATELLITE_VOICE, ++ PCI_SATELLITE_DATA, ++ PCI_SATELLITE_OTHER = 0x80 ++} pci_satellite_subclasses; + -+/* String hash */ -+static INLINE uint -+hash(const char *s) -+{ -+ uint hash = 0; ++typedef enum { ++ PCI_CRYPT_NETWORK, ++ PCI_CRYPT_ENTERTAINMENT, ++ PCI_CRYPT_OTHER = 0x80 ++} pci_crypt_subclasses; + -+ while (*s) -+ hash = 31 * hash + *s++; ++typedef enum { ++ PCI_DSP_DPIO, ++ PCI_DSP_OTHER = 0x80 ++} pci_dsp_subclasses; + -+ return hash; -+} ++typedef enum { ++ PCI_XOR_QDMA, ++ PCI_XOR_OTHER = 0x80 ++} pci_xor_subclasses; + -+/* (Re)initialize the hash table. Should be locked. */ -+static int -+BCMINITFN(nvram_rehash)(struct nvram_header *header) -+{ -+ char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq; ++/* Header types */ ++typedef enum { ++ PCI_HEADER_NORMAL, ++ PCI_HEADER_BRIDGE, ++ PCI_HEADER_CARDBUS ++} pci_header_types; + -+ /* (Re)initialize hash table */ -+ BCMINIT(nvram_free)(); + -+ /* Parse and set "name=value\0 ... \0\0" */ -+ name = (char *) &header[1]; -+ end = (char *) header + NVRAM_SPACE - 2; -+ end[0] = end[1] = '\0'; -+ for (; *name; name = value + strlen(value) + 1) { -+ if (!(eq = strchr(name, '='))) -+ break; -+ *eq = '\0'; -+ value = eq + 1; -+ BCMINIT(_nvram_set)(name, value); -+ *eq = '='; -+ } ++/* Overlay for a PCI-to-PCI bridge */ + -+ /* Set special SDRAM parameters */ -+ if (!BCMINIT(_nvram_get)("sdram_init")) { -+ sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16)); -+ BCMINIT(_nvram_set)("sdram_init", buf); -+ } -+ if (!BCMINIT(_nvram_get)("sdram_config")) { -+ sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff)); -+ BCMINIT(_nvram_set)("sdram_config", buf); -+ } -+ if (!BCMINIT(_nvram_get)("sdram_refresh")) { -+ sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff)); -+ BCMINIT(_nvram_set)("sdram_refresh", buf); -+ } -+ if (!BCMINIT(_nvram_get)("sdram_ncdl")) { -+ sprintf(buf, "0x%08X", header->config_ncdl); -+ BCMINIT(_nvram_set)("sdram_ncdl", buf); -+ } ++#define PPB_RSVDA_MAX 2 ++#define PPB_RSVDD_MAX 8 + -+ return 0; -+} ++typedef struct _ppb_config_regs { ++ unsigned short vendor; ++ unsigned short device; ++ unsigned short command; ++ unsigned short status; ++ unsigned char rev_id; ++ unsigned char prog_if; ++ unsigned char sub_class; ++ unsigned char base_class; ++ unsigned char cache_line_size; ++ unsigned char latency_timer; ++ unsigned char header_type; ++ unsigned char bist; ++ unsigned long rsvd_a[PPB_RSVDA_MAX]; ++ unsigned char prim_bus; ++ unsigned char sec_bus; ++ unsigned char sub_bus; ++ unsigned char sec_lat; ++ unsigned char io_base; ++ unsigned char io_lim; ++ unsigned short sec_status; ++ unsigned short mem_base; ++ unsigned short mem_lim; ++ unsigned short pf_mem_base; ++ unsigned short pf_mem_lim; ++ unsigned long pf_mem_base_hi; ++ unsigned long pf_mem_lim_hi; ++ unsigned short io_base_hi; ++ unsigned short io_lim_hi; ++ unsigned short subsys_vendor; ++ unsigned short subsys_id; ++ unsigned long rsvd_b; ++ unsigned char rsvd_c; ++ unsigned char int_pin; ++ unsigned short bridge_ctrl; ++ unsigned char chip_ctrl; ++ unsigned char diag_ctrl; ++ unsigned short arb_ctrl; ++ unsigned long rsvd_d[PPB_RSVDD_MAX]; ++ unsigned char dev_dep[192]; ++} ppb_config_regs; + -+/* Get the value of an NVRAM variable. Should be locked. */ -+char * -+BCMINITFN(_nvram_get)(const char *name) -+{ -+ uint i; -+ struct nvram_tuple *t; -+ char *value; + -+ if (!name) -+ return NULL; ++/* PCI CAPABILITY DEFINES */ ++#define PCI_CAP_POWERMGMTCAP_ID 0x01 ++#define PCI_CAP_MSICAP_ID 0x05 ++#define PCI_CAP_PCIECAP_ID 0x10 + -+ /* Hash the name */ -+ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); ++/* Data structure to define the Message Signalled Interrupt facility ++ * Valid for PCI and PCIE configurations ++ */ ++typedef struct _pciconfig_cap_msi { ++ unsigned char capID; ++ unsigned char nextptr; ++ unsigned short msgctrl; ++ unsigned int msgaddr; ++} pciconfig_cap_msi; + -+ /* Find the associated tuple in the hash table */ -+ for (t = BCMINIT(nvram_hash)[i]; t && strcmp(t->name, name); t = t->next); ++/* Data structure to define the Power managment facility ++ * Valid for PCI and PCIE configurations ++ */ ++typedef struct _pciconfig_cap_pwrmgmt { ++ unsigned char capID; ++ unsigned char nextptr; ++ unsigned short pme_cap; ++ unsigned short pme_sts_ctrl; ++ unsigned char pme_bridge_ext; ++ unsigned char data; ++} pciconfig_cap_pwrmgmt; + -+ value = t ? t->value : NULL; ++/* Data structure to define the PCIE capability */ ++typedef struct _pciconfig_cap_pcie { ++ unsigned char capID; ++ unsigned char nextptr; ++ unsigned short pcie_cap; ++ unsigned int dev_cap; ++ unsigned short dev_ctrl; ++ unsigned short dev_status; ++ unsigned int link_cap; ++ unsigned short link_ctrl; ++ unsigned short link_status; ++} pciconfig_cap_pcie; + -+ return value; -+} ++/* PCIE Enhanced CAPABILITY DEFINES */ ++#define PCIE_EXTCFG_OFFSET 0x100 ++#define PCIE_ADVERRREP_CAPID 0x0001 ++#define PCIE_VC_CAPID 0x0002 ++#define PCIE_DEVSNUM_CAPID 0x0003 ++#define PCIE_PWRBUDGET_CAPID 0x0004 + -+/* Get the value of an NVRAM variable. Should be locked. */ -+int -+BCMINITFN(_nvram_set)(const char *name, const char *value) -+{ -+ uint i; -+ struct nvram_tuple *t, *u, **prev; ++/* Header to define the PCIE specific capabilities in the extended config space */ ++typedef struct _pcie_enhanced_caphdr { ++ unsigned short capID; ++ unsigned short cap_ver : 4; ++ unsigned short next_ptr : 12; ++} pcie_enhanced_caphdr; + -+ /* Hash the name */ -+ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); + -+ /* Find the associated tuple in the hash table */ -+ for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev); ++/* Everything below is BRCM HND proprietary */ + -+ /* (Re)allocate tuple */ -+ if (!(u = BCMINIT(_nvram_realloc)(t, name, value))) -+ return -12; /* -ENOMEM */ + -+ /* Value reallocated */ -+ if (t && t == u) -+ return 0; ++/* Brcm PCI configuration registers */ ++#define cap_list rsvd_a[0] ++#define bar0_window dev_dep[0x80 - 0x40] ++#define bar1_window dev_dep[0x84 - 0x40] ++#define sprom_control dev_dep[0x88 - 0x40] + -+ /* Move old tuple to the dead table */ -+ if (t) { -+ *prev = t->next; -+ t->next = nvram_dead; -+ nvram_dead = t; -+ } ++#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */ ++#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */ ++#define PCI_SPROM_CONTROL 0x88 /* sprom property control */ ++#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */ ++#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */ ++#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */ ++#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */ ++#define PCI_BACKPLANE_ADDR 0xA0 /* address an arbitrary location on the system backplane */ ++#define PCI_BACKPLANE_DATA 0xA4 /* data at the location specified by above address */ ++#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */ ++#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */ ++#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */ + -+ /* Add new tuple to the hash table */ -+ u->next = BCMINIT(nvram_hash)[i]; -+ BCMINIT(nvram_hash)[i] = u; ++#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */ ++#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */ ++#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */ ++#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) /* pci core SB registers are at the end of the ++ * 8KB window, so their address is the "regular" ++ * address plus 4K ++ */ ++#define PCI_BAR0_WINSZ 8192 /* bar0 window size */ + -+ return 0; -+} ++/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ ++#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */ ++#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) /* bar0 + 12K accesses chipc core registers */ ++#define PCI_16KBB0_WINSZ (16 * 1024) /* bar0 window size */ + -+/* Unset the value of an NVRAM variable. Should be locked. */ -+int -+BCMINITFN(_nvram_unset)(const char *name) -+{ -+ uint i; -+ struct nvram_tuple *t, **prev; -+ -+ if (!name) -+ return 0; -+ -+ /* Hash the name */ -+ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); -+ -+ /* Find the associated tuple in the hash table */ -+ for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev); -+ -+ /* Move it to the dead table */ -+ if (t) { -+ *prev = t->next; -+ t->next = nvram_dead; -+ nvram_dead = t; -+ } -+ -+ return 0; -+} -+ -+/* Get all NVRAM variables. Should be locked. */ -+int -+BCMINITFN(_nvram_getall)(char *buf, int count) -+{ -+ uint i; -+ struct nvram_tuple *t; -+ int len = 0; -+ -+ bzero(buf, count); -+ -+ /* Write name=value\0 ... \0\0 */ -+ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { -+ for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) { -+ if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1)) -+ len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1; -+ else -+ break; -+ } -+ } -+ -+ return 0; -+} -+ -+/* Regenerate NVRAM. Should be locked. */ -+int -+BCMINITFN(_nvram_commit)(struct nvram_header *header) -+{ -+ char *init, *config, *refresh, *ncdl; -+ char *ptr, *end; -+ int i; -+ struct nvram_tuple *t; -+ struct nvram_header tmp; -+ uint8 crc; -+ -+ /* Regenerate header */ -+ header->magic = NVRAM_MAGIC; -+ header->crc_ver_init = (NVRAM_VERSION << 8); -+ if (!(init = BCMINIT(_nvram_get)("sdram_init")) || -+ !(config = BCMINIT(_nvram_get)("sdram_config")) || -+ !(refresh = BCMINIT(_nvram_get)("sdram_refresh")) || -+ !(ncdl = BCMINIT(_nvram_get)("sdram_ncdl"))) { -+ header->crc_ver_init |= SDRAM_INIT << 16; -+ header->config_refresh = SDRAM_CONFIG; -+ header->config_refresh |= SDRAM_REFRESH << 16; -+ header->config_ncdl = 0; -+ } else { -+ header->crc_ver_init |= (bcm_strtoul(init, NULL, 0) & 0xffff) << 16; -+ header->config_refresh = bcm_strtoul(config, NULL, 0) & 0xffff; -+ header->config_refresh |= (bcm_strtoul(refresh, NULL, 0) & 0xffff) << 16; -+ header->config_ncdl = bcm_strtoul(ncdl, NULL, 0); -+ } -+ -+ /* Clear data area */ -+ ptr = (char *) header + sizeof(struct nvram_header); -+ bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header)); -+ -+ /* Leave space for a double NUL at the end */ -+ end = (char *) header + NVRAM_SPACE - 2; -+ -+ /* Write out all tuples */ -+ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { -+ for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) { -+ if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end) -+ break; -+ ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1; -+ } -+ } -+ -+ /* End with a double NUL */ -+ ptr += 2; -+ -+ /* Set new length */ -+ header->len = ROUNDUP(ptr - (char *) header, 4); -+ -+ /* Little-endian CRC8 over the last 11 bytes of the header */ -+ tmp.crc_ver_init = htol32(header->crc_ver_init); -+ tmp.config_refresh = htol32(header->config_refresh); -+ tmp.config_ncdl = htol32(header->config_ncdl); -+ crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, CRC8_INIT_VALUE); -+ -+ /* Continue CRC8 over data bytes */ -+ crc = hndcrc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc); -+ -+ /* Set new CRC8 */ -+ header->crc_ver_init |= crc; -+ -+ /* Reinitialize hash table */ -+ return BCMINIT(nvram_rehash)(header); -+} -+ -+/* Initialize hash table. Should be locked. */ -+int -+BCMINITFN(_nvram_init)(void) -+{ -+ struct nvram_header *header; -+ int ret; -+ void *osh; ++/* PCI_INT_STATUS */ ++#define PCI_SBIM_STATUS_SERR 0x4 /* backplane SBErr interrupt status */ + -+ /* get kernel osl handler */ -+ osh = osl_attach(NULL); ++/* PCI_INT_MASK */ ++#define PCI_SBIM_SHIFT 8 /* backplane core interrupt mask bits offset */ ++#define PCI_SBIM_MASK 0xff00 /* backplane core interrupt mask */ ++#define PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */ + -+ if (!(header = (struct nvram_header *) MALLOC(osh, NVRAM_SPACE))) { -+ printf("nvram_init: out of memory, malloced %d bytes\n", MALLOCED(osh)); -+ return -12; /* -ENOMEM */ -+ } ++/* PCI_SPROM_CONTROL */ ++#define SPROM_SZ_MSK 0x02 /* SPROM Size Mask */ ++#define SPROM_LOCKED 0x08 /* SPROM Locked */ ++#define SPROM_BLANK 0x04 /* indicating a blank SPROM */ ++#define SPROM_WRITEEN 0x10 /* SPROM write enable */ ++#define SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */ ++#define SPROM_OTPIN_USE 0x80 /* device OTP In use */ + -+ if ((ret = BCMINIT(_nvram_read)(header)) == 0 && -+ header->magic == NVRAM_MAGIC) -+ BCMINIT(nvram_rehash)(header); ++#define SPROM_SIZE 256 /* sprom size in 16-bit */ ++#define SPROM_CRC_RANGE 64 /* crc cover range in 16-bit */ + -+ MFREE(osh, header, NVRAM_SPACE); -+ return ret; -+} ++/* PCI_CFG_CMD_STAT */ ++#define PCI_CFG_CMD_STAT_TA 0x08000000 /* target abort status */ + -+/* Free hash table. Should be locked. */ -+void -+BCMINITFN(_nvram_exit)(void) -+{ -+ BCMINIT(nvram_free)(); -+} -diff -Naur linux.old/arch/mips/bcm947xx/nvram_linux.c linux.dev/arch/mips/bcm947xx/nvram_linux.c ---- linux.old/arch/mips/bcm947xx/nvram_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/nvram_linux.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,653 @@ ++#endif /* _h_pcicfg_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbchipc.h linux.dev/arch/mips/bcm947xx/include/sbchipc.h +--- linux.old/arch/mips/bcm947xx/include/sbchipc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbchipc.h 2006-04-27 22:11:01.000000000 +0200 +@@ -0,0 +1,516 @@ +/* -+ * NVRAM variable manipulation (Linux kernel half) ++ * SiliconBackplane Chipcommon core hardware definitions. + * -+ * Copyright 2005, Broadcom Corporation ++ * The chipcommon core provides chip identification, SB control, ++ * jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer, ++ * gpio interface, extbus, and support for serial and parallel flashes. ++ * ++ * $Id: sbchipc.h,v 1.1.1.14 2006/04/15 01:29:08 michael Exp $ ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -6319,654 +6063,896 @@ diff -Naur linux.old/arch/mips/bcm947xx/nvram_linux.c linux.dev/arch/mips/bcm947 + * + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#ifndef _SBCHIPC_H ++#define _SBCHIPC_H + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include + -+/* In BSS to minimize text size and page aligned so it can be mmap()-ed */ -+static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE))); ++#ifndef _LANGUAGE_ASSEMBLY + -+#ifdef MODULE ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ + -+#define early_nvram_get(name) nvram_get(name) ++typedef volatile struct { ++ uint32 chipid; /* 0x0 */ ++ uint32 capabilities; ++ uint32 corecontrol; /* corerev >= 1 */ ++ uint32 bist; + -+#else /* !MODULE */ ++ /* OTP */ ++ uint32 otpstatus; /* 0x10, corerev >= 10 */ ++ uint32 otpcontrol; ++ uint32 otpprog; ++ uint32 PAD; + -+/* Global SB handle */ -+extern void *bcm947xx_sbh; -+extern spinlock_t bcm947xx_sbh_lock; ++ /* Interrupt control */ ++ uint32 intstatus; /* 0x20 */ ++ uint32 intmask; ++ uint32 chipcontrol; /* 0x28, rev >= 11 */ ++ uint32 chipstatus; /* 0x2c, rev >= 11 */ + -+static int cfe_env; -+extern char *cfe_env_get(char *nv_buf, const char *name); ++ /* Jtag Master */ ++ uint32 jtagcmd; /* 0x30, rev >= 10 */ ++ uint32 jtagir; ++ uint32 jtagdr; ++ uint32 jtagctrl; + -+/* Convenience */ -+#define sbh bcm947xx_sbh -+#define sbh_lock bcm947xx_sbh_lock -+#define KB * 1024 -+#define MB * 1024 * 1024 ++ /* serial flash interface registers */ ++ uint32 flashcontrol; /* 0x40 */ ++ uint32 flashaddress; ++ uint32 flashdata; ++ uint32 PAD[1]; + -+/* Probe for NVRAM header */ -+static void __init -+early_nvram_init(void) -+{ -+ struct nvram_header *header; -+ chipcregs_t *cc; -+ struct sflash *info = NULL; -+ int i; -+ uint32 base, off, lim; -+ u32 *src, *dst; ++ /* Silicon backplane configuration broadcast control */ ++ uint32 broadcastaddress; /* 0x50 */ ++ uint32 broadcastdata; ++ uint32 PAD[2]; + -+ if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) { -+ base = KSEG1ADDR(SB_FLASH2); -+ switch (readl(&cc->capabilities) & CAP_FLASH_MASK) { -+ case PFLASH: -+ lim = SB_FLASH2_SZ; -+ break; ++ /* gpio - cleared only by power-on-reset */ ++ uint32 gpioin; /* 0x60 */ ++ uint32 gpioout; ++ uint32 gpioouten; ++ uint32 gpiocontrol; ++ uint32 gpiointpolarity; ++ uint32 gpiointmask; ++ uint32 PAD[2]; + -+ case SFLASH_ST: -+ case SFLASH_AT: -+ if ((info = sflash_init(cc)) == NULL) -+ return; -+ lim = info->size; -+ break; ++ /* Watchdog timer */ ++ uint32 watchdog; /* 0x80 */ ++ uint32 PAD[1]; + -+ case FLASH_NONE: -+ default: -+ return; -+ } -+ } else { -+ /* extif assumed, Stop at 4 MB */ -+ base = KSEG1ADDR(SB_FLASH1); -+ lim = SB_FLASH1_SZ; -+ } ++ /* GPIO based LED powersave registers corerev >= 16 */ ++ uint32 gpiotimerval; /* 0x88 */ ++ uint32 gpiotimeroutmask; + -+ /* XXX: hack for supporting the CFE environment stuff on WGT634U */ -+ src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000); -+ dst = (u32 *) nvram_buf; -+ if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) { -+ printk("early_nvram_init: WGT634U NVRAM found.\n"); ++ /* clock control */ ++ uint32 clockcontrol_n; /* 0x90 */ ++ uint32 clockcontrol_sb; /* aka m0 */ ++ uint32 clockcontrol_pci; /* aka m1 */ ++ uint32 clockcontrol_m2; /* mii/uart/mipsref */ ++ uint32 clockcontrol_m3; /* cpu */ ++ uint32 clkdiv; /* corerev >= 3 */ ++ uint32 PAD[2]; + -+ for (i = 0; i < 0x1ff0; i++) { -+ if (*src == 0xFFFFFFFF) -+ break; -+ *dst++ = *src++; -+ } -+ cfe_env = 1; -+ return; -+ } ++ /* pll delay registers (corerev >= 4) */ ++ uint32 pll_on_delay; /* 0xb0 */ ++ uint32 fref_sel_delay; ++ uint32 slow_clk_ctl; /* 5 < corerev < 10 */ ++ uint32 PAD[1]; + -+ off = FLASH_MIN; -+ while (off <= lim) { -+ /* Windowed flash access */ -+ header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); -+ if (header->magic == NVRAM_MAGIC) -+ goto found; -+ off <<= 1; -+ } ++ /* Instaclock registers (corerev >= 10) */ ++ uint32 system_clk_ctl; /* 0xc0 */ ++ uint32 clkstatestretch; ++ uint32 PAD[14]; + -+ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ -+ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB); -+ if (header->magic == NVRAM_MAGIC) -+ goto found; -+ -+ header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); -+ if (header->magic == NVRAM_MAGIC) -+ goto found; -+ -+ printk("early_nvram_init: NVRAM not found\n"); -+ return; ++ /* ExtBus control registers (corerev >= 3) */ ++ uint32 pcmcia_config; /* 0x100 */ ++ uint32 pcmcia_memwait; ++ uint32 pcmcia_attrwait; ++ uint32 pcmcia_iowait; ++ uint32 ide_config; ++ uint32 ide_memwait; ++ uint32 ide_attrwait; ++ uint32 ide_iowait; ++ uint32 prog_config; ++ uint32 prog_waitcount; ++ uint32 flash_config; ++ uint32 flash_waitcount; ++ uint32 PAD[44]; + -+found: -+ src = (u32 *) header; -+ dst = (u32 *) nvram_buf; -+ for (i = 0; i < sizeof(struct nvram_header); i += 4) -+ *dst++ = *src++; -+ for (; i < header->len && i < NVRAM_SPACE; i += 4) -+ *dst++ = ltoh32(*src++); -+} ++ /* Clock control and hardware workarounds */ ++ uint32 clk_ctl_st; ++ uint32 hw_war; ++ uint32 PAD[70]; + -+/* Early (before mm or mtd) read-only access to NVRAM */ -+static char * __init -+early_nvram_get(const char *name) -+{ -+ char *var, *value, *end, *eq; ++ /* uarts */ ++ uint8 uart0data; /* 0x300 */ ++ uint8 uart0imr; ++ uint8 uart0fcr; ++ uint8 uart0lcr; ++ uint8 uart0mcr; ++ uint8 uart0lsr; ++ uint8 uart0msr; ++ uint8 uart0scratch; ++ uint8 PAD[248]; /* corerev >= 1 */ + -+ if (!name) -+ return NULL; ++ uint8 uart1data; /* 0x400 */ ++ uint8 uart1imr; ++ uint8 uart1fcr; ++ uint8 uart1lcr; ++ uint8 uart1mcr; ++ uint8 uart1lsr; ++ uint8 uart1msr; ++ uint8 uart1scratch; ++} chipcregs_t; + -+ /* Too early? */ -+ if (sbh == NULL) -+ return NULL; ++#endif /* _LANGUAGE_ASSEMBLY */ + -+ if (!nvram_buf[0]) -+ early_nvram_init(); ++#define CC_CHIPID 0 ++#define CC_CAPABILITIES 4 ++#define CC_JTAGCMD 0x30 ++#define CC_JTAGIR 0x34 ++#define CC_JTAGDR 0x38 ++#define CC_JTAGCTRL 0x3c ++#define CC_WATCHDOG 0x80 ++#define CC_CLKC_N 0x90 ++#define CC_CLKC_M0 0x94 ++#define CC_CLKC_M1 0x98 ++#define CC_CLKC_M2 0x9c ++#define CC_CLKC_M3 0xa0 ++#define CC_CLKDIV 0xa4 ++#define CC_SYS_CLK_CTL 0xc0 ++#define CC_OTP 0x800 + -+ if (cfe_env) -+ return cfe_env_get(nvram_buf, name); ++/* chipid */ ++#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ ++#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ ++#define CID_REV_SHIFT 16 /* Chip Revision shift */ ++#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ ++#define CID_PKG_SHIFT 20 /* Package Option shift */ ++#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ ++#define CID_CC_SHIFT 24 + -+ /* Look for name=value and return value */ -+ var = &nvram_buf[sizeof(struct nvram_header)]; -+ end = nvram_buf + sizeof(nvram_buf) - 2; -+ end[0] = end[1] = '\0'; -+ for (; *var; var = value + strlen(value) + 1) { -+ if (!(eq = strchr(var, '='))) -+ break; -+ value = eq + 1; -+ if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0) -+ return value; -+ } ++/* capabilities */ ++#define CAP_UARTS_MASK 0x00000003 /* Number of uarts */ ++#define CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ ++#define CAP_UCLKSEL 0x00000018 /* UARTs clock select */ ++#define CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ ++#define CAP_UARTGPIO 0x00000020 /* UARTs own Gpio's 15:12 */ ++#define CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ ++#define CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ ++#define CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ ++#define CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ ++#define CAP_FLASH_MASK 0x00000700 /* Type of flash */ ++#define CAP_PLL_MASK 0x00038000 /* Type of PLL */ ++#define CAP_PWR_CTL 0x00040000 /* Power control */ ++#define CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ ++#define CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ ++#define CAP_OTPSIZE_BASE 5 /* OTP Size base */ ++#define CAP_JTAGP 0x00400000 /* JTAG Master Present */ ++#define CAP_ROM 0x00800000 /* Internal boot rom active */ ++#define CAP_BKPLN64 0x08000000 /* 64-bit backplane */ + -+ return NULL; -+} ++/* PLL type */ ++#define PLL_NONE 0x00000000 ++#define PLL_TYPE1 0x00010000 /* 48Mhz base, 3 dividers */ ++#define PLL_TYPE2 0x00020000 /* 48Mhz, 4 dividers */ ++#define PLL_TYPE3 0x00030000 /* 25Mhz, 2 dividers */ ++#define PLL_TYPE4 0x00008000 /* 48Mhz, 4 dividers */ ++#define PLL_TYPE5 0x00018000 /* 25Mhz, 4 dividers */ ++#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */ ++#define PLL_TYPE7 0x00038000 /* 25Mhz, 4 dividers */ + -+#endif /* !MODULE */ ++/* corecontrol */ ++#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */ ++#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ + -+extern char * _nvram_get(const char *name); -+extern int _nvram_set(const char *name, const char *value); -+extern int _nvram_unset(const char *name); -+extern int _nvram_getall(char *buf, int count); -+extern int _nvram_commit(struct nvram_header *header); -+extern int _nvram_init(void); -+extern void _nvram_exit(void); ++/* chipcontrol */ ++#define CHIPCTRL_4321A0_DEFAULT 0x3a4 ++#define CHIPCTRL_4321A1_DEFAULT 0x0a4 + -+/* Globals */ -+static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED; -+static struct semaphore nvram_sem; -+static unsigned long nvram_offset = 0; -+static int nvram_major = -1; -+static devfs_handle_t nvram_handle = NULL; -+static struct mtd_info *nvram_mtd = NULL; ++/* Fields in the otpstatus register */ ++#define OTPS_PROGFAIL 0x80000000 ++#define OTPS_PROTECT 0x00000007 ++#define OTPS_HW_PROTECT 0x00000001 ++#define OTPS_SW_PROTECT 0x00000002 ++#define OTPS_CID_PROTECT 0x00000004 + -+int -+_nvram_read(char *buf) -+{ -+ struct nvram_header *header = (struct nvram_header *) buf; -+ size_t len; ++/* Fields in the otpcontrol register */ ++#define OTPC_RECWAIT 0xff000000 ++#define OTPC_PROGWAIT 0x00ffff00 ++#define OTPC_PRW_SHIFT 8 ++#define OTPC_MAXFAIL 0x00000038 ++#define OTPC_VSEL 0x00000006 ++#define OTPC_SELVL 0x00000001 + -+ if (!nvram_mtd || -+ MTD_READ(nvram_mtd, nvram_mtd->size - NVRAM_SPACE, NVRAM_SPACE, &len, buf) || -+ len != NVRAM_SPACE || -+ header->magic != NVRAM_MAGIC) { -+ /* Maybe we can recover some data from early initialization */ -+ memcpy(buf, nvram_buf, NVRAM_SPACE); -+ } ++/* Fields in otpprog */ ++#define OTPP_COL_MASK 0x000000ff ++#define OTPP_ROW_MASK 0x0000ff00 ++#define OTPP_ROW_SHIFT 8 ++#define OTPP_READERR 0x10000000 ++#define OTPP_VALUE 0x20000000 ++#define OTPP_VALUE_SHIFT 29 ++#define OTPP_READ 0x40000000 ++#define OTPP_START 0x80000000 ++#define OTPP_BUSY 0x80000000 + -+ return 0; -+} ++/* jtagcmd */ ++#define JCMD_START 0x80000000 ++#define JCMD_BUSY 0x80000000 ++#define JCMD_PAUSE 0x40000000 ++#define JCMD0_ACC_MASK 0x0000f000 ++#define JCMD0_ACC_IRDR 0x00000000 ++#define JCMD0_ACC_DR 0x00001000 ++#define JCMD0_ACC_IR 0x00002000 ++#define JCMD0_ACC_RESET 0x00003000 ++#define JCMD0_ACC_IRPDR 0x00004000 ++#define JCMD0_ACC_PDR 0x00005000 ++#define JCMD0_IRW_MASK 0x00000f00 ++#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */ ++#define JCMD_ACC_IRDR 0x00000000 ++#define JCMD_ACC_DR 0x00010000 ++#define JCMD_ACC_IR 0x00020000 ++#define JCMD_ACC_RESET 0x00030000 ++#define JCMD_ACC_IRPDR 0x00040000 ++#define JCMD_ACC_PDR 0x00050000 ++#define JCMD_IRW_MASK 0x00001f00 ++#define JCMD_IRW_SHIFT 8 ++#define JCMD_DRW_MASK 0x0000003f + -+struct nvram_tuple * -+_nvram_realloc(struct nvram_tuple *t, const char *name, const char *value) -+{ -+ if ((nvram_offset + strlen(value) + 1) > NVRAM_SPACE) -+ return NULL; ++/* jtagctrl */ ++#define JCTRL_FORCE_CLK 4 /* Force clock */ ++#define JCTRL_EXT_EN 2 /* Enable external targets */ ++#define JCTRL_EN 1 /* Enable Jtag master */ + -+ if (!t) { -+ if (!(t = kmalloc(sizeof(struct nvram_tuple) + strlen(name) + 1, GFP_ATOMIC))) -+ return NULL; ++/* Fields in clkdiv */ ++#define CLKD_SFLASH 0x0f000000 ++#define CLKD_SFLASH_SHIFT 24 ++#define CLKD_OTP 0x000f0000 ++#define CLKD_OTP_SHIFT 16 ++#define CLKD_JTAG 0x00000f00 ++#define CLKD_JTAG_SHIFT 8 ++#define CLKD_UART 0x000000ff + -+ /* Copy name */ -+ t->name = (char *) &t[1]; -+ strcpy(t->name, name); ++/* intstatus/intmask */ ++#define CI_GPIO 0x00000001 /* gpio intr */ ++#define CI_EI 0x00000002 /* ro: ext intr pin (corerev >= 3) */ ++#define CI_WDRESET 0x80000000 /* watchdog reset occurred */ + -+ t->value = NULL; -+ } ++/* slow_clk_ctl */ ++#define SCC_SS_MASK 0x00000007 /* slow clock source mask */ ++#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */ ++#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */ ++#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */ ++#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ ++#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled, ++ * 0: LPO is enabled ++ */ ++#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, ++ * 0: power logic control ++ */ ++#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors ++ * PLL clock disable requests from core ++ */ ++#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't ++ * disable crystal when appropriate ++ */ ++#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ ++#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ ++#define SCC_CD_SHIFT 16 + -+ /* Copy value */ -+ if (!t->value || strcmp(t->value, value)) { -+ t->value = &nvram_buf[nvram_offset]; -+ strcpy(t->value, value); -+ nvram_offset += strlen(value) + 1; -+ } -+ -+ return t; -+} ++/* system_clk_ctl */ ++#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */ ++#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */ ++#define SYCC_FP 0x00000004 /* ForcePLLOn */ ++#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */ ++#define SYCC_HR 0x00000010 /* Force HT */ ++#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ ++#define SYCC_CD_SHIFT 16 + -+void -+_nvram_free(struct nvram_tuple *t) -+{ -+ if (!t) -+ nvram_offset = 0; -+ else -+ kfree(t); -+} ++/* gpiotimerval */ ++#define GPIO_ONTIME_SHIFT 16 + -+int -+nvram_set(const char *name, const char *value) -+{ -+ unsigned long flags; -+ int ret; -+ struct nvram_header *header; ++/* clockcontrol_n */ ++#define CN_N1_MASK 0x3f /* n1 control */ ++#define CN_N2_MASK 0x3f00 /* n2 control */ ++#define CN_N2_SHIFT 8 ++#define CN_PLLC_MASK 0xf0000 /* pll control */ ++#define CN_PLLC_SHIFT 16 + -+ spin_lock_irqsave(&nvram_lock, flags); -+ if ((ret = _nvram_set(name, value))) { -+ /* Consolidate space and try again */ -+ if ((header = kmalloc(NVRAM_SPACE, GFP_ATOMIC))) { -+ if (_nvram_commit(header) == 0) -+ ret = _nvram_set(name, value); -+ kfree(header); -+ } -+ } -+ spin_unlock_irqrestore(&nvram_lock, flags); ++/* clockcontrol_sb/pci/uart */ ++#define CC_M1_MASK 0x3f /* m1 control */ ++#define CC_M2_MASK 0x3f00 /* m2 control */ ++#define CC_M2_SHIFT 8 ++#define CC_M3_MASK 0x3f0000 /* m3 control */ ++#define CC_M3_SHIFT 16 ++#define CC_MC_MASK 0x1f000000 /* mux control */ ++#define CC_MC_SHIFT 24 + -+ return ret; -+} ++/* N3M Clock control magic field values */ ++#define CC_F6_2 0x02 /* A factor of 2 in */ ++#define CC_F6_3 0x03 /* 6-bit fields like */ ++#define CC_F6_4 0x05 /* N1, M1 or M3 */ ++#define CC_F6_5 0x09 ++#define CC_F6_6 0x11 ++#define CC_F6_7 0x21 + -+char * -+real_nvram_get(const char *name) -+{ -+ unsigned long flags; -+ char *value; ++#define CC_F5_BIAS 5 /* 5-bit fields get this added */ + -+ spin_lock_irqsave(&nvram_lock, flags); -+ value = _nvram_get(name); -+ spin_unlock_irqrestore(&nvram_lock, flags); ++#define CC_MC_BYPASS 0x08 ++#define CC_MC_M1 0x04 ++#define CC_MC_M1M2 0x02 ++#define CC_MC_M1M2M3 0x01 ++#define CC_MC_M1M3 0x11 + -+ return value; -+} ++/* Type 2 Clock control magic field values */ ++#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */ ++#define CC_T2M2_BIAS 3 /* m2 bias */ + -+char * -+nvram_get(const char *name) -+{ -+ if (nvram_major >= 0) -+ return real_nvram_get(name); -+ else -+ return early_nvram_get(name); -+} ++#define CC_T2MC_M1BYP 1 ++#define CC_T2MC_M2BYP 2 ++#define CC_T2MC_M3BYP 4 + -+int -+nvram_unset(const char *name) -+{ -+ unsigned long flags; -+ int ret; ++/* Type 6 Clock control magic field values */ ++#define CC_T6_MMASK 1 /* bits of interest in m */ ++#define CC_T6_M0 120000000 /* sb clock for m = 0 */ ++#define CC_T6_M1 100000000 /* sb clock for m = 1 */ ++#define SB2MIPS_T6(sb) (2 * (sb)) + -+ spin_lock_irqsave(&nvram_lock, flags); -+ ret = _nvram_unset(name); -+ spin_unlock_irqrestore(&nvram_lock, flags); ++/* Common clock base */ ++#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */ ++#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLL's */ + -+ return ret; -+} ++/* Clock control values for 200Mhz in 5350 */ ++#define CLKC_5350_N 0x0311 ++#define CLKC_5350_M 0x04020009 + -+static void -+erase_callback(struct erase_info *done) -+{ -+ wait_queue_head_t *wait_q = (wait_queue_head_t *) done->priv; -+ wake_up(wait_q); -+} ++/* Flash types in the chipcommon capabilities register */ ++#define FLASH_NONE 0x000 /* No flash */ ++#define SFLASH_ST 0x100 /* ST serial flash */ ++#define SFLASH_AT 0x200 /* Atmel serial flash */ ++#define PFLASH 0x700 /* Parallel flash */ + -+int -+nvram_commit(void) -+{ -+ char *buf; -+ size_t erasesize, len; -+ unsigned int i; -+ int ret; -+ struct nvram_header *header; -+ unsigned long flags; -+ u_int32_t offset; -+ DECLARE_WAITQUEUE(wait, current); -+ wait_queue_head_t wait_q; -+ struct erase_info erase; ++/* Bits in the ExtBus config registers */ ++#define CC_CFG_EN 0x0001 /* Enable */ ++#define CC_CFG_EM_MASK 0x000e /* Extif Mode */ ++#define CC_CFG_EM_ASYNC 0x0000 /* Async/Parallel flash */ ++#define CC_CFG_EM_SYNC 0x0002 /* Synchronous */ ++#define CC_CFG_EM_PCMCIA 0x0004 /* PCMCIA */ ++#define CC_CFG_EM_IDE 0x0006 /* IDE */ ++#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ ++#define CC_CFG_CD_MASK 0x0060 /* Sync: Clock divisor */ ++#define CC_CFG_CE 0x0080 /* Sync: Clock enable */ ++#define CC_CFG_SB 0x0100 /* Sync: Size/Bytestrobe */ + -+ if (!nvram_mtd) { -+ printk("nvram_commit: NVRAM not found\n"); -+ return -ENODEV; -+ } ++/* ExtBus address space */ ++#define CC_EB_BASE 0x1a000000 /* Chipc ExtBus base address */ ++#define CC_EB_PCMCIA_MEM 0x1a000000 /* PCMCIA 0 memory base address */ ++#define CC_EB_PCMCIA_IO 0x1a200000 /* PCMCIA 0 I/O base address */ ++#define CC_EB_PCMCIA_CFG 0x1a400000 /* PCMCIA 0 config base address */ ++#define CC_EB_IDE 0x1a800000 /* IDE memory base */ ++#define CC_EB_PCMCIA1_MEM 0x1a800000 /* PCMCIA 1 memory base address */ ++#define CC_EB_PCMCIA1_IO 0x1aa00000 /* PCMCIA 1 I/O base address */ ++#define CC_EB_PCMCIA1_CFG 0x1ac00000 /* PCMCIA 1 config base address */ ++#define CC_EB_PROGIF 0x1b000000 /* ProgIF Async/Sync base address */ + -+ if (in_interrupt()) { -+ printk("nvram_commit: not committing in interrupt\n"); -+ return -EINVAL; -+ } + -+ /* Backup sector blocks to be erased */ -+ erasesize = ROUNDUP(NVRAM_SPACE, nvram_mtd->erasesize); -+ if (!(buf = kmalloc(erasesize, GFP_KERNEL))) { -+ printk("nvram_commit: out of memory\n"); -+ return -ENOMEM; -+ } ++/* Start/busy bit in flashcontrol */ ++#define SFLASH_OPCODE 0x000000ff ++#define SFLASH_ACTION 0x00000700 ++#define SFLASH_START 0x80000000 ++#define SFLASH_BUSY SFLASH_START + -+ down(&nvram_sem); ++/* flashcontrol action codes */ ++#define SFLASH_ACT_OPONLY 0x0000 /* Issue opcode only */ ++#define SFLASH_ACT_OP1D 0x0100 /* opcode + 1 data byte */ ++#define SFLASH_ACT_OP3A 0x0200 /* opcode + 3 address bytes */ ++#define SFLASH_ACT_OP3A1D 0x0300 /* opcode + 3 addres & 1 data bytes */ ++#define SFLASH_ACT_OP3A4D 0x0400 /* opcode + 3 addres & 4 data bytes */ ++#define SFLASH_ACT_OP3A4X4D 0x0500 /* opcode + 3 addres, 4 don't care & 4 data bytes */ ++#define SFLASH_ACT_OP3A1X4D 0x0700 /* opcode + 3 addres, 1 don't care & 4 data bytes */ + -+ if ((i = erasesize - NVRAM_SPACE) > 0) { -+ offset = nvram_mtd->size - erasesize; -+ len = 0; -+ ret = MTD_READ(nvram_mtd, offset, i, &len, buf); -+ if (ret || len != i) { -+ printk("nvram_commit: read error ret = %d, len = %d/%d\n", ret, len, i); -+ ret = -EIO; -+ goto done; -+ } -+ header = (struct nvram_header *)(buf + i); -+ } else { -+ offset = nvram_mtd->size - NVRAM_SPACE; -+ header = (struct nvram_header *)buf; -+ } ++/* flashcontrol action+opcodes for ST flashes */ ++#define SFLASH_ST_WREN 0x0006 /* Write Enable */ ++#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */ ++#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */ ++#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */ ++#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */ ++#define SFLASH_ST_PP 0x0302 /* Page Program */ ++#define SFLASH_ST_SE 0x02d8 /* Sector Erase */ ++#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */ ++#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */ ++#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */ + -+ /* Regenerate NVRAM */ -+ spin_lock_irqsave(&nvram_lock, flags); -+ ret = _nvram_commit(header); -+ spin_unlock_irqrestore(&nvram_lock, flags); -+ if (ret) -+ goto done; ++/* Status register bits for ST flashes */ ++#define SFLASH_ST_WIP 0x01 /* Write In Progress */ ++#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */ ++#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */ ++#define SFLASH_ST_BP_SHIFT 2 ++#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */ + -+ /* Erase sector blocks */ -+ init_waitqueue_head(&wait_q); -+ for (; offset < nvram_mtd->size - NVRAM_SPACE + header->len; offset += nvram_mtd->erasesize) { -+ erase.mtd = nvram_mtd; -+ erase.addr = offset; -+ erase.len = nvram_mtd->erasesize; -+ erase.callback = erase_callback; -+ erase.priv = (u_long) &wait_q; ++/* flashcontrol action+opcodes for Atmel flashes */ ++#define SFLASH_AT_READ 0x07e8 ++#define SFLASH_AT_PAGE_READ 0x07d2 ++#define SFLASH_AT_BUF1_READ ++#define SFLASH_AT_BUF2_READ ++#define SFLASH_AT_STATUS 0x01d7 ++#define SFLASH_AT_BUF1_WRITE 0x0384 ++#define SFLASH_AT_BUF2_WRITE 0x0387 ++#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283 ++#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286 ++#define SFLASH_AT_BUF1_PROGRAM 0x0288 ++#define SFLASH_AT_BUF2_PROGRAM 0x0289 ++#define SFLASH_AT_PAGE_ERASE 0x0281 ++#define SFLASH_AT_BLOCK_ERASE 0x0250 ++#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382 ++#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385 ++#define SFLASH_AT_BUF1_LOAD 0x0253 ++#define SFLASH_AT_BUF2_LOAD 0x0255 ++#define SFLASH_AT_BUF1_COMPARE 0x0260 ++#define SFLASH_AT_BUF2_COMPARE 0x0261 ++#define SFLASH_AT_BUF1_REPROGRAM 0x0258 ++#define SFLASH_AT_BUF2_REPROGRAM 0x0259 + -+ set_current_state(TASK_INTERRUPTIBLE); -+ add_wait_queue(&wait_q, &wait); ++/* Status register bits for Atmel flashes */ ++#define SFLASH_AT_READY 0x80 ++#define SFLASH_AT_MISMATCH 0x40 ++#define SFLASH_AT_ID_MASK 0x38 ++#define SFLASH_AT_ID_SHIFT 3 + -+ /* Unlock sector blocks */ -+ if (nvram_mtd->unlock) -+ nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize); ++/* OTP regions */ ++#define OTP_HW_REGION OTPS_HW_PROTECT ++#define OTP_SW_REGION OTPS_SW_PROTECT ++#define OTP_CID_REGION OTPS_CID_PROTECT + -+ if ((ret = MTD_ERASE(nvram_mtd, &erase))) { -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&wait_q, &wait); -+ printk("nvram_commit: erase error\n"); -+ goto done; -+ } ++/* OTP regions (Byte offsets from otp size) */ ++#define OTP_SWLIM_OFF (-8) ++#define OTP_CIDBASE_OFF 0 ++#define OTP_CIDLIM_OFF 8 + -+ /* Wait for erase to finish */ -+ schedule(); -+ remove_wait_queue(&wait_q, &wait); -+ } ++/* Predefined OTP words (Word offset from otp size) */ ++#define OTP_BOUNDARY_OFF (-4) ++#define OTP_HWSIGN_OFF (-3) ++#define OTP_SWSIGN_OFF (-2) ++#define OTP_CIDSIGN_OFF (-1) + -+ /* Write partition up to end of data area */ -+ offset = nvram_mtd->size - erasesize; -+ i = erasesize - NVRAM_SPACE + header->len; -+ ret = MTD_WRITE(nvram_mtd, offset, i, &len, buf); -+ if (ret || len != i) { -+ printk("nvram_commit: write error\n"); -+ ret = -EIO; -+ goto done; -+ } ++#define OTP_CID_OFF 0 ++#define OTP_PKG_OFF 1 ++#define OTP_FID_OFF 2 ++#define OTP_RSV_OFF 3 ++#define OTP_LIM_OFF 4 + -+ offset = nvram_mtd->size - erasesize; -+ ret = MTD_READ(nvram_mtd, offset, 4, &len, buf); ++#define OTP_SIGNATURE 0x578a ++#define OTP_MAGIC 0x4e56 + -+ done: -+ up(&nvram_sem); -+ kfree(buf); -+ return ret; -+} -+ -+int -+nvram_getall(char *buf, int count) -+{ -+ unsigned long flags; -+ int ret; -+ -+ spin_lock_irqsave(&nvram_lock, flags); -+ ret = _nvram_getall(buf, count); -+ spin_unlock_irqrestore(&nvram_lock, flags); ++/* ++ * These are the UART port assignments, expressed as offsets from the base ++ * register. These assignments should hold for any serial port based on ++ * a 8250, 16450, or 16550(A). ++ */ + -+ return ret; -+} ++#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ ++#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ ++#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ ++#define UART_IER 1 /* In/Out: Interrupt Enable Register (DLAB=0) */ ++#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ ++#define UART_IIR 2 /* In: Interrupt Identity Register */ ++#define UART_FCR 2 /* Out: FIFO Control Register */ ++#define UART_LCR 3 /* Out: Line Control Register */ ++#define UART_MCR 4 /* Out: Modem Control Register */ ++#define UART_LSR 5 /* In: Line Status Register */ ++#define UART_MSR 6 /* In: Modem Status Register */ ++#define UART_SCR 7 /* I/O: Scratch Register */ ++#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ ++#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ ++#define UART_MCR_OUT2 0x08 /* MCR GPIO out 2 */ ++#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ ++#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ ++#define UART_LSR_RXRDY 0x01 /* Receiver ready */ ++#define UART_FCR_FIFO_ENABLE 1 /* FIFO control register bit controlling FIFO enable/disable */ + -+EXPORT_SYMBOL(nvram_get); -+EXPORT_SYMBOL(nvram_getall); -+EXPORT_SYMBOL(nvram_set); -+EXPORT_SYMBOL(nvram_unset); -+EXPORT_SYMBOL(nvram_commit); ++/* Interrupt Enable Register (IER) bits */ ++#define UART_IER_EDSSI 8 /* enable modem status interrupt */ ++#define UART_IER_ELSI 4 /* enable receiver line status interrupt */ ++#define UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */ ++#define UART_IER_ERBFI 1 /* enable data available interrupt */ + -+/* User mode interface below */ ++#endif /* _SBCHIPC_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbconfig.h linux.dev/arch/mips/bcm947xx/include/sbconfig.h +--- linux.old/arch/mips/bcm947xx/include/sbconfig.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbconfig.h 2006-04-27 22:14:11.000000000 +0200 +@@ -0,0 +1,369 @@ ++/* ++ * Broadcom SiliconBackplane hardware register definitions. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: sbconfig.h,v 1.1.1.11 2006/02/27 03:43:16 honor Exp $ ++ */ + -+static ssize_t -+dev_nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ char tmp[100], *name = tmp, *value; -+ ssize_t ret; -+ unsigned long off; ++#ifndef _SBCONFIG_H ++#define _SBCONFIG_H + -+ if (count > sizeof(tmp)) { -+ if (!(name = kmalloc(count, GFP_KERNEL))) -+ return -ENOMEM; -+ } ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif + -+ if (copy_from_user(name, buf, count)) { -+ ret = -EFAULT; -+ goto done; -+ } ++/* ++ * SiliconBackplane Address Map. ++ * All regions may not exist on all chips. ++ */ ++#define SB_SDRAM_BASE 0x00000000 /* Physical SDRAM */ ++#define SB_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */ ++#define SB_PCI_MEM_SZ (64 * 1024 * 1024) ++#define SB_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */ ++#define SB_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ ++#define SB_ENUM_BASE 0x18000000 /* Enumeration space base */ ++#define SB_ENUM_LIM 0x18010000 /* Enumeration space limit */ + -+ if (*name == '\0') { -+ /* Get all variables */ -+ ret = nvram_getall(name, count); -+ if (ret == 0) { -+ if (copy_to_user(buf, name, count)) { -+ ret = -EFAULT; -+ goto done; -+ } -+ ret = count; -+ } -+ } else { -+ if (!(value = nvram_get(name))) { -+ ret = 0; -+ goto done; -+ } ++#define SB_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ ++#define SB_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ + -+ /* Provide the offset into mmap() space */ -+ off = (unsigned long) value - (unsigned long) nvram_buf; ++#define SB_EXTIF_BASE 0x1f000000 /* External Interface region base address */ ++#define SB_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ ++#define SB_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ + -+ if (put_user(off, (unsigned long *) buf)) { -+ ret = -EFAULT; -+ goto done; -+ } ++#define SB_ROM 0x20000000 /* ARM ROM */ ++#define SB_SRAM2 0x80000000 /* ARM SRAM Region 2 */ ++#define SB_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */ ++#define SB_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */ + -+ ret = sizeof(unsigned long); -+ } ++#define SB_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */ ++#define SB_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */ ++#define SB_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), low 32 bits ++ */ ++#define SB_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), high 32 bits ++ */ ++#define SB_EUART (SB_EXTIF_BASE + 0x00800000) ++#define SB_LED (SB_EXTIF_BASE + 0x00900000) + -+ flush_cache_all(); -+ -+done: -+ if (name != tmp) -+ kfree(name); + -+ return ret; -+} ++/* enumeration space related defs */ ++#define SB_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ ++#define SB_MAXCORES ((SB_ENUM_LIM - SB_ENUM_BASE)/SB_CORE_SIZE) ++#define SB_MAXFUNCS 4 /* max. # functions per core */ ++#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */ ++#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */ + -+static ssize_t -+dev_nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -+{ -+ char tmp[100], *name = tmp, *value; -+ ssize_t ret; ++/* mips address */ ++#define SB_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */ + -+ if (count > sizeof(tmp)) { -+ if (!(name = kmalloc(count, GFP_KERNEL))) -+ return -ENOMEM; -+ } ++/* ++ * Sonics Configuration Space Registers. ++ */ ++#define SBIPSFLAG 0x08 ++#define SBTPSFLAG 0x18 ++#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */ ++#define SBTMERRLOG 0x50 /* sonics >= 2.3 */ ++#define SBADMATCH3 0x60 ++#define SBADMATCH2 0x68 ++#define SBADMATCH1 0x70 ++#define SBIMSTATE 0x90 ++#define SBINTVEC 0x94 ++#define SBTMSTATELOW 0x98 ++#define SBTMSTATEHIGH 0x9c ++#define SBBWA0 0xa0 ++#define SBIMCONFIGLOW 0xa8 ++#define SBIMCONFIGHIGH 0xac ++#define SBADMATCH0 0xb0 ++#define SBTMCONFIGLOW 0xb8 ++#define SBTMCONFIGHIGH 0xbc ++#define SBBCONFIG 0xc0 ++#define SBBSTATE 0xc8 ++#define SBACTCNFG 0xd8 ++#define SBFLAGST 0xe8 ++#define SBIDLOW 0xf8 ++#define SBIDHIGH 0xfc + -+ if (copy_from_user(name, buf, count)) { -+ ret = -EFAULT; -+ goto done; -+ } ++/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have ++ * a few registers *below* that line. I think it would be very confusing to try ++ * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here, ++ */ + -+ value = name; -+ name = strsep(&value, "="); -+ if (value) -+ ret = nvram_set(name, value) ? : count; -+ else -+ ret = nvram_unset(name) ? : count; ++#define SBIMERRLOGA 0xea8 ++#define SBIMERRLOG 0xeb0 ++#define SBTMPORTCONNID0 0xed8 ++#define SBTMPORTLOCK0 0xef8 + -+ done: -+ if (name != tmp) -+ kfree(name); ++#ifndef _LANGUAGE_ASSEMBLY + -+ return ret; -+} ++typedef volatile struct _sbconfig { ++ uint32 PAD[2]; ++ uint32 sbipsflag; /* initiator port ocp slave flag */ ++ uint32 PAD[3]; ++ uint32 sbtpsflag; /* target port ocp slave flag */ ++ uint32 PAD[11]; ++ uint32 sbtmerrloga; /* (sonics >= 2.3) */ ++ uint32 PAD; ++ uint32 sbtmerrlog; /* (sonics >= 2.3) */ ++ uint32 PAD[3]; ++ uint32 sbadmatch3; /* address match3 */ ++ uint32 PAD; ++ uint32 sbadmatch2; /* address match2 */ ++ uint32 PAD; ++ uint32 sbadmatch1; /* address match1 */ ++ uint32 PAD[7]; ++ uint32 sbimstate; /* initiator agent state */ ++ uint32 sbintvec; /* interrupt mask */ ++ uint32 sbtmstatelow; /* target state */ ++ uint32 sbtmstatehigh; /* target state */ ++ uint32 sbbwa0; /* bandwidth allocation table0 */ ++ uint32 PAD; ++ uint32 sbimconfiglow; /* initiator configuration */ ++ uint32 sbimconfighigh; /* initiator configuration */ ++ uint32 sbadmatch0; /* address match0 */ ++ uint32 PAD; ++ uint32 sbtmconfiglow; /* target configuration */ ++ uint32 sbtmconfighigh; /* target configuration */ ++ uint32 sbbconfig; /* broadcast configuration */ ++ uint32 PAD; ++ uint32 sbbstate; /* broadcast state */ ++ uint32 PAD[3]; ++ uint32 sbactcnfg; /* activate configuration */ ++ uint32 PAD[3]; ++ uint32 sbflagst; /* current sbflags */ ++ uint32 PAD[3]; ++ uint32 sbidlow; /* identification */ ++ uint32 sbidhigh; /* identification */ ++} sbconfig_t; + -+static int -+dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ if (cmd != NVRAM_MAGIC) -+ return -EINVAL; -+ return nvram_commit(); -+} ++#endif /* _LANGUAGE_ASSEMBLY */ + -+static int -+dev_nvram_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ unsigned long offset = virt_to_phys(nvram_buf); ++/* sbipsflag */ ++#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */ ++#define SBIPS_INT1_SHIFT 0 ++#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */ ++#define SBIPS_INT2_SHIFT 8 ++#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */ ++#define SBIPS_INT3_SHIFT 16 ++#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */ ++#define SBIPS_INT4_SHIFT 24 + -+ if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start, -+ vma->vm_page_prot)) -+ return -EAGAIN; ++/* sbtpsflag */ ++#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */ ++#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */ + -+ return 0; -+} ++/* sbtmerrlog */ ++#define SBTMEL_CM 0x00000007 /* command */ ++#define SBTMEL_CI 0x0000ff00 /* connection id */ ++#define SBTMEL_EC 0x0f000000 /* error code */ ++#define SBTMEL_ME 0x80000000 /* multiple error */ + -+static int -+dev_nvram_open(struct inode *inode, struct file * file) -+{ -+ MOD_INC_USE_COUNT; -+ return 0; -+} -+ -+static int -+dev_nvram_release(struct inode *inode, struct file * file) -+{ -+ MOD_DEC_USE_COUNT; -+ return 0; -+} ++/* sbimstate */ ++#define SBIM_PC 0xf /* pipecount */ ++#define SBIM_AP_MASK 0x30 /* arbitration policy */ ++#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */ ++#define SBIM_AP_TS 0x10 /* use timesliaces only */ ++#define SBIM_AP_TK 0x20 /* use token only */ ++#define SBIM_AP_RSV 0x30 /* reserved */ ++#define SBIM_IBE 0x20000 /* inbanderror */ ++#define SBIM_TO 0x40000 /* timeout */ ++#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ ++#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ + -+static struct file_operations dev_nvram_fops = { -+ owner: THIS_MODULE, -+ open: dev_nvram_open, -+ release: dev_nvram_release, -+ read: dev_nvram_read, -+ write: dev_nvram_write, -+ ioctl: dev_nvram_ioctl, -+ mmap: dev_nvram_mmap, -+}; ++/* sbtmstatelow */ ++#define SBTML_RESET 0x1 /* reset */ ++#define SBTML_REJ_MASK 0x6 /* reject */ ++#define SBTML_REJ_SHIFT 1 ++#define SBTML_CLK 0x10000 /* clock enable */ ++#define SBTML_FGC 0x20000 /* force gated clocks on */ ++#define SBTML_FL_MASK 0x3ffc0000 /* core-specific flags */ ++#define SBTML_PE 0x40000000 /* pme enable */ ++#define SBTML_BE 0x80000000 /* bist enable */ + -+static void -+dev_nvram_exit(void) -+{ -+ int order = 0; -+ struct page *page, *end; ++/* sbtmstatehigh */ ++#define SBTMH_SERR 0x1 /* serror */ ++#define SBTMH_INT 0x2 /* interrupt */ ++#define SBTMH_BUSY 0x4 /* busy */ ++#define SBTMH_TO 0x00000020 /* timeout (sonics >= 2.3) */ ++#define SBTMH_FL_MASK 0x1fff0000 /* core-specific flags */ ++#define SBTMH_DMA64 0x10000000 /* supports DMA with 64-bit addresses */ ++#define SBTMH_GCR 0x20000000 /* gated clock request */ ++#define SBTMH_BISTF 0x40000000 /* bist failed */ ++#define SBTMH_BISTD 0x80000000 /* bist done */ + -+ if (nvram_handle) -+ devfs_unregister(nvram_handle); + -+ if (nvram_major >= 0) -+ devfs_unregister_chrdev(nvram_major, "nvram"); ++/* sbbwa0 */ ++#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */ ++#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */ ++#define SBBWA_TAB1_SHIFT 16 + -+ if (nvram_mtd) -+ put_mtd_device(nvram_mtd); ++/* sbimconfiglow */ ++#define SBIMCL_STO_MASK 0x7 /* service timeout */ ++#define SBIMCL_RTO_MASK 0x70 /* request timeout */ ++#define SBIMCL_RTO_SHIFT 4 ++#define SBIMCL_CID_MASK 0xff0000 /* connection id */ ++#define SBIMCL_CID_SHIFT 16 + -+ while ((PAGE_SIZE << order) < NVRAM_SPACE) -+ order++; -+ end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1); -+ for (page = virt_to_page(nvram_buf); page <= end; page++) -+ mem_map_unreserve(page); ++/* sbimconfighigh */ ++#define SBIMCH_IEM_MASK 0xc /* inband error mode */ ++#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */ ++#define SBIMCH_TEM_SHIFT 4 ++#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */ ++#define SBIMCH_BEM_SHIFT 6 + -+ _nvram_exit(); -+} ++/* sbadmatch0 */ ++#define SBAM_TYPE_MASK 0x3 /* address type */ ++#define SBAM_AD64 0x4 /* reserved */ ++#define SBAM_ADINT0_MASK 0xf8 /* type0 size */ ++#define SBAM_ADINT0_SHIFT 3 ++#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */ ++#define SBAM_ADINT1_SHIFT 3 ++#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */ ++#define SBAM_ADINT2_SHIFT 3 ++#define SBAM_ADEN 0x400 /* enable */ ++#define SBAM_ADNEG 0x800 /* negative decode */ ++#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */ ++#define SBAM_BASE0_SHIFT 8 ++#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */ ++#define SBAM_BASE1_SHIFT 12 ++#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */ ++#define SBAM_BASE2_SHIFT 16 + -+static int __init -+dev_nvram_init(void) -+{ -+ int order = 0, ret = 0; -+ struct page *page, *end; -+ unsigned int i; ++/* sbtmconfiglow */ ++#define SBTMCL_CD_MASK 0xff /* clock divide */ ++#define SBTMCL_CO_MASK 0xf800 /* clock offset */ ++#define SBTMCL_CO_SHIFT 11 ++#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */ ++#define SBTMCL_IF_SHIFT 18 ++#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */ ++#define SBTMCL_IM_SHIFT 24 + -+ /* Allocate and reserve memory to mmap() */ -+ while ((PAGE_SIZE << order) < NVRAM_SPACE) -+ order++; -+ end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1); -+ for (page = virt_to_page(nvram_buf); page <= end; page++) -+ mem_map_reserve(page); ++/* sbtmconfighigh */ ++#define SBTMCH_BM_MASK 0x3 /* busy mode */ ++#define SBTMCH_RM_MASK 0x3 /* retry mode */ ++#define SBTMCH_RM_SHIFT 2 ++#define SBTMCH_SM_MASK 0x30 /* stop mode */ ++#define SBTMCH_SM_SHIFT 4 ++#define SBTMCH_EM_MASK 0x300 /* sb error mode */ ++#define SBTMCH_EM_SHIFT 8 ++#define SBTMCH_IM_MASK 0xc00 /* int mode */ ++#define SBTMCH_IM_SHIFT 10 + -+#ifdef CONFIG_MTD -+ /* Find associated MTD device */ -+ for (i = 0; i < MAX_MTD_DEVICES; i++) { -+ nvram_mtd = get_mtd_device(NULL, i); -+ if (nvram_mtd) { -+ if (!strcmp(nvram_mtd->name, "nvram") && -+ nvram_mtd->size >= NVRAM_SPACE) -+ break; -+ put_mtd_device(nvram_mtd); -+ } -+ } -+ if (i >= MAX_MTD_DEVICES) -+ nvram_mtd = NULL; -+#endif ++/* sbbconfig */ ++#define SBBC_LAT_MASK 0x3 /* sb latency */ ++#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */ ++#define SBBC_MAX0_SHIFT 16 ++#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */ ++#define SBBC_MAX1_SHIFT 20 + -+ /* Initialize hash table lock */ -+ spin_lock_init(&nvram_lock); ++/* sbbstate */ ++#define SBBS_SRD 0x1 /* st reg disable */ ++#define SBBS_HRD 0x2 /* hold reg disable */ + -+ /* Initialize commit semaphore */ -+ init_MUTEX(&nvram_sem); ++/* sbidlow */ ++#define SBIDL_CS_MASK 0x3 /* config space */ ++#define SBIDL_AR_MASK 0x38 /* # address ranges supported */ ++#define SBIDL_AR_SHIFT 3 ++#define SBIDL_SYNCH 0x40 /* sync */ ++#define SBIDL_INIT 0x80 /* initiator */ ++#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */ ++#define SBIDL_MINLAT_SHIFT 8 ++#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */ ++#define SBIDL_MAXLAT_SHIFT 12 ++#define SBIDL_FIRST 0x10000 /* this initiator is first */ ++#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */ ++#define SBIDL_CW_SHIFT 18 ++#define SBIDL_TP_MASK 0xf00000 /* target ports */ ++#define SBIDL_TP_SHIFT 20 ++#define SBIDL_IP_MASK 0xf000000 /* initiator ports */ ++#define SBIDL_IP_SHIFT 24 ++#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */ ++#define SBIDL_RV_SHIFT 28 ++#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */ ++#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */ + -+ /* Register char device */ -+ if ((nvram_major = devfs_register_chrdev(0, "nvram", &dev_nvram_fops)) < 0) { -+ ret = nvram_major; -+ goto err; -+ } ++/* sbidhigh */ ++#define SBIDH_RC_MASK 0x000f /* revision code */ ++#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ ++#define SBIDH_RCE_SHIFT 8 ++#define SBCOREREV(sbidh) \ ++ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) ++#define SBIDH_CC_MASK 0x8ff0 /* core code */ ++#define SBIDH_CC_SHIFT 4 ++#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ ++#define SBIDH_VC_SHIFT 16 + -+ /* Initialize hash table */ -+ _nvram_init(); ++#define SB_COMMIT 0xfd8 /* update buffered registers value */ + -+ /* Create /dev/nvram handle */ -+ nvram_handle = devfs_register(NULL, "nvram", DEVFS_FL_NONE, nvram_major, 0, -+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &dev_nvram_fops, NULL); ++/* vendor codes */ ++#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */ + -+ /* Set the SDRAM NCDL value into NVRAM if not already done */ -+ if (getintvar(NULL, "sdram_ncdl") == 0) { -+ unsigned int ncdl; -+ char buf[] = "0x00000000"; ++/* core codes */ ++#define SB_NODEV 0x700 /* Invalid coreid */ ++#define SB_CC 0x800 /* chipcommon core */ ++#define SB_ILINE20 0x801 /* iline20 core */ ++#define SB_SDRAM 0x803 /* sdram core */ ++#define SB_PCI 0x804 /* pci core */ ++#define SB_MIPS 0x805 /* mips core */ ++#define SB_ENET 0x806 /* enet mac core */ ++#define SB_CODEC 0x807 /* v90 codec core */ ++#define SB_USB 0x808 /* usb 1.1 host/device core */ ++#define SB_ADSL 0x809 /* ADSL core */ ++#define SB_ILINE100 0x80a /* iline100 core */ ++#define SB_IPSEC 0x80b /* ipsec core */ ++#define SB_PCMCIA 0x80d /* pcmcia core */ ++#define SB_SDIOD SB_PCMCIA /* pcmcia core has sdio device */ ++#define SB_SOCRAM 0x80e /* internal memory core */ ++#define SB_MEMC 0x80f /* memc sdram core */ ++#define SB_EXTIF 0x811 /* external interface core */ ++#define SB_D11 0x812 /* 802.11 MAC core */ ++#define SB_MIPS33 0x816 /* mips3302 core */ ++#define SB_USB11H 0x817 /* usb 1.1 host core */ ++#define SB_USB11D 0x818 /* usb 1.1 device core */ ++#define SB_USB20H 0x819 /* usb 2.0 host core */ ++#define SB_USB20D 0x81a /* usb 2.0 device core */ ++#define SB_SDIOH 0x81b /* sdio host core */ ++#define SB_ROBO 0x81c /* roboswitch core */ ++#define SB_ATA100 0x81d /* parallel ATA core */ ++#define SB_SATAXOR 0x81e /* serial ATA & XOR DMA core */ ++#define SB_GIGETH 0x81f /* gigabit ethernet core */ ++#define SB_PCIE 0x820 /* pci express core */ ++#define SB_MIMO 0x821 /* MIMO phy core */ ++#define SB_SRAMC 0x822 /* SRAM controller core */ ++#define SB_MINIMAC 0x823 /* MINI MAC/phy core */ ++#define SB_ARM11 0x824 /* ARM 1176 core */ ++#define SB_ARM7 0x825 /* ARM 7tdmi core */ + -+ if ((ncdl = sb_memc_get_ncdl(sbh))) { -+ sprintf(buf, "0x%08x", ncdl); -+ nvram_set("sdram_ncdl", buf); -+ nvram_commit(); -+ } -+ } ++#define SB_CC_IDX 0 /* chipc, when present, is always core 0 */ + -+ return 0; ++/* Not really related to Silicon Backplane, but a couple of software ++ * conventions for the use the flash space: ++ */ + -+ err: -+ dev_nvram_exit(); -+ return ret; -+} ++/* Minumum amount of flash we support */ ++#define FLASH_MIN 0x00020000 /* Minimum flash size */ + -+module_init(dev_nvram_init); -+module_exit(dev_nvram_exit); -diff -Naur linux.old/arch/mips/bcm947xx/pcibios.c linux.dev/arch/mips/bcm947xx/pcibios.c ---- linux.old/arch/mips/bcm947xx/pcibios.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/pcibios.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,355 @@ -+/* -+ * Low-Level PCI and SB support for BCM47xx (Linux support code) -+ * -+ * Copyright 2005, Broadcom Corporation ++/* A boot/binary may have an embedded block that describes its size */ ++#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */ ++#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */ ++#define BISZ_MAGIC_IDX 0 /* Word 0: magic */ ++#define BISZ_TXTST_IDX 1 /* 1: text start */ ++#define BISZ_TXTEND_IDX 2 /* 2: text start */ ++#define BISZ_DATAST_IDX 3 /* 3: text start */ ++#define BISZ_DATAEND_IDX 4 /* 4: text start */ ++#define BISZ_BSSST_IDX 5 /* 5: text start */ ++#define BISZ_BSSEND_IDX 6 /* 6: text start */ ++#define BISZ_SIZE 7 /* descriptor size in 32-bit intergers */ ++ ++#endif /* _SBCONFIG_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbextif.h linux.dev/arch/mips/bcm947xx/include/sbextif.h +--- linux.old/arch/mips/bcm947xx/include/sbextif.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbextif.h 2006-04-27 22:13:03.000000000 +0200 +@@ -0,0 +1,243 @@ ++/* ++ * Hardware-specific External Interface I/O core definitions ++ * for the BCM47xx family of SiliconBackplane-based chips. ++ * ++ * The External Interface core supports a total of three external chip selects ++ * supporting external interfaces. One of the external chip selects is ++ * used for Flash, one is used for PCMCIA, and the other may be ++ * programmed to support either a synchronous interface or an ++ * asynchronous interface. The asynchronous interface can be used to ++ * support external devices such as UARTs and the BCM2019 Bluetooth ++ * baseband processor. ++ * The external interface core also contains 2 on-chip 16550 UARTs, clock ++ * frequency control, a watchdog interrupt timer, and a GPIO interface. ++ * ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -6974,403 +6960,437 @@ diff -Naur linux.old/arch/mips/bcm947xx/pcibios.c linux.dev/arch/mips/bcm947xx/p + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * $Id$ ++ * $Id: sbextif.h,v 1.1.1.8 2006/02/27 03:43:16 honor Exp $ + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Global SB handle */ -+extern sb_t *bcm947xx_sbh; -+extern spinlock_t bcm947xx_sbh_lock; -+ -+/* Convenience */ -+#define sbh bcm947xx_sbh -+#define sbh_lock bcm947xx_sbh_lock ++#ifndef _SBEXTIF_H ++#define _SBEXTIF_H + -+static int -+sbpci_read_config_byte(struct pci_dev *dev, int where, u8 *value) -+{ -+ unsigned long flags; -+ int ret; ++/* external interface address space */ ++#define EXTIF_PCMCIA_MEMBASE(x) (x) ++#define EXTIF_PCMCIA_IOBASE(x) ((x) + 0x100000) ++#define EXTIF_PCMCIA_CFGBASE(x) ((x) + 0x200000) ++#define EXTIF_CFGIF_BASE(x) ((x) + 0x800000) ++#define EXTIF_FLASH_BASE(x) ((x) + 0xc00000) + -+ spin_lock_irqsave(&sbh_lock, flags); -+ ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, value, sizeof(*value)); -+ spin_unlock_irqrestore(&sbh_lock, flags); -+ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -+} ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ + -+static int -+sbpci_read_config_word(struct pci_dev *dev, int where, u16 *value) -+{ -+ unsigned long flags; -+ int ret; ++/* ++ * The multiple instances of output and output enable registers ++ * are present to allow driver software for multiple cores to control ++ * gpio outputs without needing to share a single register pair. ++ */ ++struct gpiouser { ++ uint32 out; ++ uint32 outen; ++}; ++#define NGPIOUSER 5 + -+ spin_lock_irqsave(&sbh_lock, flags); -+ ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, value, sizeof(*value)); -+ spin_unlock_irqrestore(&sbh_lock, flags); -+ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -+} ++typedef volatile struct { ++ uint32 corecontrol; ++ uint32 extstatus; ++ uint32 PAD[2]; + -+static int -+sbpci_read_config_dword(struct pci_dev *dev, int where, u32 *value) -+{ -+ unsigned long flags; -+ int ret; ++ /* pcmcia control registers */ ++ uint32 pcmcia_config; ++ uint32 pcmcia_memwait; ++ uint32 pcmcia_attrwait; ++ uint32 pcmcia_iowait; + -+ spin_lock_irqsave(&sbh_lock, flags); -+ ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, value, sizeof(*value)); -+ spin_unlock_irqrestore(&sbh_lock, flags); -+ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -+} ++ /* programmable interface control registers */ ++ uint32 prog_config; ++ uint32 prog_waitcount; + -+static int -+sbpci_write_config_byte(struct pci_dev *dev, int where, u8 value) -+{ -+ unsigned long flags; -+ int ret; ++ /* flash control registers */ ++ uint32 flash_config; ++ uint32 flash_waitcount; ++ uint32 PAD[4]; + -+ spin_lock_irqsave(&sbh_lock, flags); -+ ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, &value, sizeof(value)); -+ spin_unlock_irqrestore(&sbh_lock, flags); -+ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -+} ++ uint32 watchdog; + -+static int -+sbpci_write_config_word(struct pci_dev *dev, int where, u16 value) -+{ -+ unsigned long flags; -+ int ret; ++ /* clock control */ ++ uint32 clockcontrol_n; ++ uint32 clockcontrol_sb; ++ uint32 clockcontrol_pci; ++ uint32 clockcontrol_mii; ++ uint32 PAD[3]; + -+ spin_lock_irqsave(&sbh_lock, flags); -+ ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, &value, sizeof(value)); -+ spin_unlock_irqrestore(&sbh_lock, flags); -+ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -+} ++ /* gpio */ ++ uint32 gpioin; ++ struct gpiouser gpio[NGPIOUSER]; ++ uint32 PAD; ++ uint32 ejtagouten; ++ uint32 gpiointpolarity; ++ uint32 gpiointmask; ++ uint32 PAD[153]; + -+static int -+sbpci_write_config_dword(struct pci_dev *dev, int where, u32 value) -+{ -+ unsigned long flags; -+ int ret; ++ uint8 uartdata; ++ uint8 PAD[3]; ++ uint8 uartimer; ++ uint8 PAD[3]; ++ uint8 uartfcr; ++ uint8 PAD[3]; ++ uint8 uartlcr; ++ uint8 PAD[3]; ++ uint8 uartmcr; ++ uint8 PAD[3]; ++ uint8 uartlsr; ++ uint8 PAD[3]; ++ uint8 uartmsr; ++ uint8 PAD[3]; ++ uint8 uartscratch; ++ uint8 PAD[3]; ++} extifregs_t; + -+ spin_lock_irqsave(&sbh_lock, flags); -+ ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, &value, sizeof(value)); -+ spin_unlock_irqrestore(&sbh_lock, flags); -+ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -+} ++/* corecontrol */ ++#define CC_UE (1 << 0) /* uart enable */ + -+static struct pci_ops pcibios_ops = { -+ sbpci_read_config_byte, -+ sbpci_read_config_word, -+ sbpci_read_config_dword, -+ sbpci_write_config_byte, -+ sbpci_write_config_word, -+ sbpci_write_config_dword -+}; ++/* extstatus */ ++#define ES_EM (1 << 0) /* endian mode (ro) */ ++#define ES_EI (1 << 1) /* external interrupt pin (ro) */ ++#define ES_GI (1 << 2) /* gpio interrupt pin (ro) */ + ++/* gpio bit mask */ ++#define GPIO_BIT0 (1 << 0) ++#define GPIO_BIT1 (1 << 1) ++#define GPIO_BIT2 (1 << 2) ++#define GPIO_BIT3 (1 << 3) ++#define GPIO_BIT4 (1 << 4) ++#define GPIO_BIT5 (1 << 5) ++#define GPIO_BIT6 (1 << 6) ++#define GPIO_BIT7 (1 << 7) + -+void __init -+pcibios_init(void) -+{ -+ ulong flags; + -+ if (!(sbh = sb_kattach())) -+ panic("sb_kattach failed"); -+ spin_lock_init(&sbh_lock); ++/* pcmcia/prog/flash_config */ ++#define CF_EN (1 << 0) /* enable */ ++#define CF_EM_MASK 0xe /* mode */ ++#define CF_EM_SHIFT 1 ++#define CF_EM_FLASH 0x0 /* flash/asynchronous mode */ ++#define CF_EM_SYNC 0x2 /* synchronous mode */ ++#define CF_EM_PCMCIA 0x4 /* pcmcia mode */ ++#define CF_DS (1 << 4) /* destsize: 0=8bit, 1=16bit */ ++#define CF_BS (1 << 5) /* byteswap */ ++#define CF_CD_MASK 0xc0 /* clock divider */ ++#define CF_CD_SHIFT 6 ++#define CF_CD_DIV2 0x0 /* backplane/2 */ ++#define CF_CD_DIV3 0x40 /* backplane/3 */ ++#define CF_CD_DIV4 0x80 /* backplane/4 */ ++#define CF_CE (1 << 8) /* clock enable */ ++#define CF_SB (1 << 9) /* size/bytestrobe (synch only) */ + -+ spin_lock_irqsave(&sbh_lock, flags); -+ sbpci_init(sbh); -+ spin_unlock_irqrestore(&sbh_lock, flags); ++/* pcmcia_memwait */ ++#define PM_W0_MASK 0x3f /* waitcount0 */ ++#define PM_W1_MASK 0x1f00 /* waitcount1 */ ++#define PM_W1_SHIFT 8 ++#define PM_W2_MASK 0x1f0000 /* waitcount2 */ ++#define PM_W2_SHIFT 16 ++#define PM_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PM_W3_SHIFT 24 + -+ set_io_port_base((unsigned long) ioremap_nocache(SB_PCI_MEM, 0x04000000)); ++/* pcmcia_attrwait */ ++#define PA_W0_MASK 0x3f /* waitcount0 */ ++#define PA_W1_MASK 0x1f00 /* waitcount1 */ ++#define PA_W1_SHIFT 8 ++#define PA_W2_MASK 0x1f0000 /* waitcount2 */ ++#define PA_W2_SHIFT 16 ++#define PA_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PA_W3_SHIFT 24 + -+ mdelay(300); //By Joey for Atheros Card ++/* pcmcia_iowait */ ++#define PI_W0_MASK 0x3f /* waitcount0 */ ++#define PI_W1_MASK 0x1f00 /* waitcount1 */ ++#define PI_W1_SHIFT 8 ++#define PI_W2_MASK 0x1f0000 /* waitcount2 */ ++#define PI_W2_SHIFT 16 ++#define PI_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PI_W3_SHIFT 24 + -+ /* Scan the SB bus */ -+ pci_scan_bus(0, &pcibios_ops, NULL); -+ -+} -+ -+char * __init -+pcibios_setup(char *str) -+{ -+ if (!strncmp(str, "ban=", 4)) { -+ sbpci_ban(simple_strtoul(str + 4, NULL, 0)); -+ return NULL; -+ } -+ -+ return (str); -+} -+ -+static u32 pci_iobase = 0x100; -+static u32 pci_membase = SB_PCI_DMA; ++/* prog_waitcount */ ++#define PW_W0_MASK 0x0000001f /* waitcount0 */ ++#define PW_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PW_W1_SHIFT 8 ++#define PW_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PW_W2_SHIFT 16 ++#define PW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PW_W3_SHIFT 24 + -+void __init -+pcibios_fixup_bus(struct pci_bus *b) -+{ -+ struct list_head *ln; -+ struct pci_dev *d; -+ struct resource *res; -+ int pos, size; -+ u32 *base; -+ u8 irq; ++#define PW_W0 0x0000000c ++#define PW_W1 0x00000a00 ++#define PW_W2 0x00020000 ++#define PW_W3 0x01000000 + -+ printk("PCI: Fixing up bus %d\n", b->number); ++/* flash_waitcount */ ++#define FW_W0_MASK 0x1f /* waitcount0 */ ++#define FW_W1_MASK 0x1f00 /* waitcount1 */ ++#define FW_W1_SHIFT 8 ++#define FW_W2_MASK 0x1f0000 /* waitcount2 */ ++#define FW_W2_SHIFT 16 ++#define FW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define FW_W3_SHIFT 24 + -+ /* Fix up SB */ -+ if (b->number == 0) { -+ for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { -+ d = pci_dev_b(ln); -+ /* Fix up interrupt lines */ -+ pci_read_config_byte(d, PCI_INTERRUPT_LINE, &irq); -+ d->irq = irq + 2; -+ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); -+ } -+ } ++/* watchdog */ ++#define WATCHDOG_CLOCK 48000000 /* Hz */ + -+ /* Fix up external PCI */ -+ else { -+ for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { -+ d = pci_dev_b(ln); -+ /* Fix up resource bases */ -+ for (pos = 0; pos < 6; pos++) { -+ res = &d->resource[pos]; -+ base = (res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase; -+ if (res->end) { -+ size = res->end - res->start + 1; -+ if (*base & (size - 1)) -+ *base = (*base + size) & ~(size - 1); -+ res->start = *base; -+ res->end = res->start + size - 1; -+ *base += size; -+ pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start); -+ } -+ /* Fix up PCI bridge BAR0 only */ -+ if (b->number == 1 && PCI_SLOT(d->devfn) == 0) -+ break; -+ } -+ /* Fix up interrupt lines */ -+ if (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL)) -+ d->irq = (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL))->irq; -+ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); -+ } -+ } -+} ++/* clockcontrol_n */ ++#define CN_N1_MASK 0x3f /* n1 control */ ++#define CN_N2_MASK 0x3f00 /* n2 control */ ++#define CN_N2_SHIFT 8 + -+unsigned int -+pcibios_assign_all_busses(void) -+{ -+ return 1; -+} ++/* clockcontrol_sb/pci/mii */ ++#define CC_M1_MASK 0x3f /* m1 control */ ++#define CC_M2_MASK 0x3f00 /* m2 control */ ++#define CC_M2_SHIFT 8 ++#define CC_M3_MASK 0x3f0000 /* m3 control */ ++#define CC_M3_SHIFT 16 ++#define CC_MC_MASK 0x1f000000 /* mux control */ ++#define CC_MC_SHIFT 24 + -+void -+pcibios_align_resource(void *data, struct resource *res, -+ unsigned long size, unsigned long align) -+{ -+} ++/* Clock control default values */ ++#define CC_DEF_N 0x0009 /* Default values for bcm4710 */ ++#define CC_DEF_100 0x04020011 ++#define CC_DEF_33 0x11030011 ++#define CC_DEF_25 0x11050011 + -+int -+pcibios_enable_resources(struct pci_dev *dev) -+{ -+ u16 cmd, old_cmd; -+ int idx; -+ struct resource *r; ++/* Clock control values for 125Mhz */ ++#define CC_125_N 0x0802 ++#define CC_125_M 0x04020009 ++#define CC_125_M25 0x11090009 ++#define CC_125_M33 0x11090005 + -+ /* External PCI only */ -+ if (dev->bus->number == 0) -+ return 0; ++/* Clock control magic field values */ ++#define CC_F6_2 0x02 /* A factor of 2 in */ ++#define CC_F6_3 0x03 /* 6-bit fields like */ ++#define CC_F6_4 0x05 /* N1, M1 or M3 */ ++#define CC_F6_5 0x09 ++#define CC_F6_6 0x11 ++#define CC_F6_7 0x21 + -+ pci_read_config_word(dev, PCI_COMMAND, &cmd); -+ old_cmd = cmd; -+ for(idx=0; idx<6; idx++) { -+ r = &dev->resource[idx]; -+ if (r->flags & IORESOURCE_IO) -+ cmd |= PCI_COMMAND_IO; -+ if (r->flags & IORESOURCE_MEM) -+ cmd |= PCI_COMMAND_MEMORY; -+ } -+ if (dev->resource[PCI_ROM_RESOURCE].start) -+ cmd |= PCI_COMMAND_MEMORY; -+ if (cmd != old_cmd) { -+ printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); -+ pci_write_config_word(dev, PCI_COMMAND, cmd); -+ } -+ return 0; -+} ++#define CC_F5_BIAS 5 /* 5-bit fields get this added */ + -+int -+pcibios_enable_device(struct pci_dev *dev, int mask) -+{ -+ ulong flags; -+ uint coreidx; ++#define CC_MC_BYPASS 0x08 ++#define CC_MC_M1 0x04 ++#define CC_MC_M1M2 0x02 ++#define CC_MC_M1M2M3 0x01 ++#define CC_MC_M1M3 0x11 + -+ /* External PCI device enable */ -+ if (dev->bus->number != 0) -+ return pcibios_enable_resources(dev); ++#define CC_CLOCK_BASE 24000000 /* Half the clock freq. in the 4710 */ + -+ /* These cores come out of reset enabled */ -+ if (dev->device == SB_MIPS || -+ dev->device == SB_MIPS33 || -+ dev->device == SB_EXTIF || -+ dev->device == SB_CC) -+ return 0; ++#endif /* _SBEXTIF_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbhndmips.h linux.dev/arch/mips/bcm947xx/include/sbhndmips.h +--- linux.old/arch/mips/bcm947xx/include/sbhndmips.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbhndmips.h 2006-04-27 20:43:56.000000000 +0200 +@@ -0,0 +1,47 @@ ++/* ++ * Broadcom SiliconBackplane MIPS definitions ++ * ++ * SB MIPS cores are custom MIPS32 processors with SiliconBackplane ++ * OCP interfaces. The CP0 processor ID is 0x00024000, where bits ++ * 23:16 mean Broadcom and bits 15:8 mean a MIPS core with an OCP ++ * interface. The core revision is stored in the SB ID register in SB ++ * configuration space. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: sbhndmips.h,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ ++ */ + -+ spin_lock_irqsave(&sbh_lock, flags); -+ coreidx = sb_coreidx(sbh); -+ if (!sb_setcoreidx(sbh, PCI_SLOT(dev->devfn))) -+ return PCIBIOS_DEVICE_NOT_FOUND; ++#ifndef _sbhndmips_h_ ++#define _sbhndmips_h_ + -+ /* -+ * The USB core requires a special bit to be set during core -+ * reset to enable host (OHCI) mode. Resetting the SB core in -+ * pcibios_enable_device() is a hack for compatibility with -+ * vanilla usb-ohci so that it does not have to know about -+ * SB. A driver that wants to use the USB core in device mode -+ * should know about SB and should reset the bit back to 0 -+ * after calling pcibios_enable_device(). -+ */ -+ if (sb_coreid(sbh) == SB_USB) { -+ sb_core_disable(sbh, sb_coreflags(sbh, 0, 0)); -+ sb_core_reset(sbh, 1 << 29); -+ } else -+ sb_core_reset(sbh, 0); ++#include + -+ sb_setcoreidx(sbh, coreidx); -+ spin_unlock_irqrestore(&sbh_lock, flags); -+ -+ return 0; -+} ++#ifndef _LANGUAGE_ASSEMBLY + -+void -+pcibios_update_resource(struct pci_dev *dev, struct resource *root, -+ struct resource *res, int resource) -+{ -+ unsigned long where, size; -+ u32 reg; ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ + -+ /* External PCI only */ -+ if (dev->bus->number == 0) -+ return; ++typedef volatile struct { ++ uint32 corecontrol; ++ uint32 PAD[2]; ++ uint32 biststatus; ++ uint32 PAD[4]; ++ uint32 intstatus; ++ uint32 intmask; ++ uint32 timer; ++} mipsregs_t; + -+ where = PCI_BASE_ADDRESS_0 + (resource * 4); -+ size = res->end - res->start; -+ pci_read_config_dword(dev, where, ®); -+ reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); -+ pci_write_config_dword(dev, where, reg); -+} ++#endif /* _LANGUAGE_ASSEMBLY */ + -+static void __init -+quirk_sbpci_bridge(struct pci_dev *dev) -+{ -+ if (dev->bus->number != 1 || PCI_SLOT(dev->devfn) != 0) -+ return; ++#endif /* _sbhndmips_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbmemc.h linux.dev/arch/mips/bcm947xx/include/sbmemc.h +--- linux.old/arch/mips/bcm947xx/include/sbmemc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbmemc.h 2006-04-27 22:12:41.000000000 +0200 +@@ -0,0 +1,147 @@ ++/* ++ * BCM47XX Sonics SiliconBackplane DDR/SDRAM controller core hardware definitions. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: sbmemc.h,v 1.6 2006/03/02 12:33:44 honor Exp $ ++ */ + -+ printk("PCI: Fixing up bridge\n"); ++#ifndef _SBMEMC_H ++#define _SBMEMC_H + -+ /* Enable PCI bridge bus mastering and memory space */ -+ pci_set_master(dev); -+ pcibios_enable_resources(dev); ++#ifdef _LANGUAGE_ASSEMBLY + -+ /* Enable PCI bridge BAR1 prefetch and burst */ -+ pci_write_config_dword(dev, PCI_BAR1_CONTROL, 3); -+} ++#define MEMC_CONTROL 0x00 ++#define MEMC_CONFIG 0x04 ++#define MEMC_REFRESH 0x08 ++#define MEMC_BISTSTAT 0x0c ++#define MEMC_MODEBUF 0x10 ++#define MEMC_BKCLS 0x14 ++#define MEMC_PRIORINV 0x18 ++#define MEMC_DRAMTIM 0x1c ++#define MEMC_INTSTAT 0x20 ++#define MEMC_INTMASK 0x24 ++#define MEMC_INTINFO 0x28 ++#define MEMC_NCDLCTL 0x30 ++#define MEMC_RDNCDLCOR 0x34 ++#define MEMC_WRNCDLCOR 0x38 ++#define MEMC_MISCDLYCTL 0x3c ++#define MEMC_DQSGATENCDL 0x40 ++#define MEMC_SPARE 0x44 ++#define MEMC_TPADDR 0x48 ++#define MEMC_TPDATA 0x4c ++#define MEMC_BARRIER 0x50 ++#define MEMC_CORE 0x54 + -+struct pci_fixup pcibios_fixups[] = { -+ { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, quirk_sbpci_bridge }, -+ { 0 } -+}; ++#else /* !_LANGUAGE_ASSEMBLY */ + -+/* -+ * If we set up a device for bus mastering, we need to check the latency -+ * timer as certain crappy BIOSes forget to set it properly. -+ */ -+unsigned int pcibios_max_latency = 255; ++/* Sonics side: MEMC core registers */ ++typedef volatile struct sbmemcregs { ++ uint32 control; ++ uint32 config; ++ uint32 refresh; ++ uint32 biststat; ++ uint32 modebuf; ++ uint32 bkcls; ++ uint32 priorinv; ++ uint32 dramtim; ++ uint32 intstat; ++ uint32 intmask; ++ uint32 intinfo; ++ uint32 reserved1; ++ uint32 ncdlctl; ++ uint32 rdncdlcor; ++ uint32 wrncdlcor; ++ uint32 miscdlyctl; ++ uint32 dqsgatencdl; ++ uint32 spare; ++ uint32 tpaddr; ++ uint32 tpdata; ++ uint32 barrier; ++ uint32 core; ++} sbmemcregs_t; + -+void pcibios_set_master(struct pci_dev *dev) -+{ -+ u8 lat; -+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); -+ if (lat < 16) -+ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; -+ else if (lat > pcibios_max_latency) -+ lat = pcibios_max_latency; -+ else -+ return; -+ printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat); -+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -+} ++#endif /* _LANGUAGE_ASSEMBLY */ + -diff -Naur linux.old/arch/mips/bcm947xx/prom.c linux.dev/arch/mips/bcm947xx/prom.c ---- linux.old/arch/mips/bcm947xx/prom.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/prom.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,41 @@ -+/* -+ * Early initialization code for BCM94710 boards -+ * -+ * Copyright 2004, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id: prom.c,v 1.1 2005/03/16 13:49:59 wbx Exp $ -+ */ ++/* MEMC Core Init values (OCP ID 0x80f) */ + -+#include -+#include -+#include -+#include -+#include ++/* For sdr: */ ++#define MEMC_SD_CONFIG_INIT 0x00048000 ++#define MEMC_SD_DRAMTIM2_INIT 0x000754d8 ++#define MEMC_SD_DRAMTIM3_INIT 0x000754da ++#define MEMC_SD_RDNCDLCOR_INIT 0x00000000 ++#define MEMC_SD_WRNCDLCOR_INIT 0x49351200 ++#define MEMC_SD1_WRNCDLCOR_INIT 0x14500200 /* For corerev 1 (4712) */ ++#define MEMC_SD_MISCDLYCTL_INIT 0x00061c1b ++#define MEMC_SD1_MISCDLYCTL_INIT 0x00021416 /* For corerev 1 (4712) */ ++#define MEMC_SD_CONTROL_INIT0 0x00000002 ++#define MEMC_SD_CONTROL_INIT1 0x00000008 ++#define MEMC_SD_CONTROL_INIT2 0x00000004 ++#define MEMC_SD_CONTROL_INIT3 0x00000010 ++#define MEMC_SD_CONTROL_INIT4 0x00000001 ++#define MEMC_SD_MODEBUF_INIT 0x00000000 ++#define MEMC_SD_REFRESH_INIT 0x0000840f + -+void __init -+prom_init(int argc, const char **argv) -+{ -+ unsigned long mem; + -+ mips_machgroup = MACH_GROUP_BRCM; -+ mips_machtype = MACH_BCM947XX; ++/* This is for SDRM8X8X4 */ ++#define MEMC_SDR_INIT 0x0008 ++#define MEMC_SDR_MODE 0x32 ++#define MEMC_SDR_NCDL 0x00020032 ++#define MEMC_SDR1_NCDL 0x0002020f /* For corerev 1 (4712) */ + -+ /* Figure out memory size by finding aliases */ -+ for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { -+ if (*(unsigned long *)((unsigned long)(prom_init) + mem) == -+ *(unsigned long *)(prom_init)) -+ break; -+ } -+ add_memory_region(0, mem, BOOT_MEM_RAM); -+} ++/* For ddr: */ ++#define MEMC_CONFIG_INIT 0x00048000 ++#define MEMC_DRAMTIM2_INIT 0x000754d8 ++#define MEMC_DRAMTIM25_INIT 0x000754d9 ++#define MEMC_RDNCDLCOR_INIT 0x00000000 ++#define MEMC_RDNCDLCOR_SIMINIT 0xf6f6f6f6 /* For hdl sim */ ++#define MEMC_WRNCDLCOR_INIT 0x49351200 ++#define MEMC_1_WRNCDLCOR_INIT 0x14500200 ++#define MEMC_DQSGATENCDL_INIT 0x00030000 ++#define MEMC_MISCDLYCTL_INIT 0x21061c1b ++#define MEMC_1_MISCDLYCTL_INIT 0x21021400 ++#define MEMC_NCDLCTL_INIT 0x00002001 ++#define MEMC_CONTROL_INIT0 0x00000002 ++#define MEMC_CONTROL_INIT1 0x00000008 ++#define MEMC_MODEBUF_INIT0 0x00004000 ++#define MEMC_CONTROL_INIT2 0x00000010 ++#define MEMC_MODEBUF_INIT1 0x00000100 ++#define MEMC_CONTROL_INIT3 0x00000010 ++#define MEMC_CONTROL_INIT4 0x00000008 ++#define MEMC_REFRESH_INIT 0x0000840f ++#define MEMC_CONTROL_INIT5 0x00000004 ++#define MEMC_MODEBUF_INIT2 0x00000000 ++#define MEMC_CONTROL_INIT6 0x00000010 ++#define MEMC_CONTROL_INIT7 0x00000001 + -+void __init -+prom_free_prom_memory(void) -+{ -+} -diff -Naur linux.old/arch/mips/bcm947xx/sbmips.c linux.dev/arch/mips/bcm947xx/sbmips.c ---- linux.old/arch/mips/bcm947xx/sbmips.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/sbmips.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,1038 @@ ++ ++/* This is for DDRM16X16X2 */ ++#define MEMC_DDR_INIT 0x0009 ++#define MEMC_DDR_MODE 0x62 ++#define MEMC_DDR_NCDL 0x0005050a ++#define MEMC_DDR1_NCDL 0x00000a0a /* For corerev 1 (4712) */ ++ ++/* mask for sdr/ddr calibration registers */ ++#define MEMC_RDNCDLCOR_RD_MASK 0x000000ff ++#define MEMC_WRNCDLCOR_WR_MASK 0x000000ff ++#define MEMC_DQSGATENCDL_G_MASK 0x000000ff ++ ++/* masks for miscdlyctl registers */ ++#define MEMC_MISC_SM_MASK 0x30000000 ++#define MEMC_MISC_SM_SHIFT 28 ++#define MEMC_MISC_SD_MASK 0x0f000000 ++#define MEMC_MISC_SD_SHIFT 24 ++ ++/* hw threshhold for calculating wr/rd for sdr memc */ ++#define MEMC_CD_THRESHOLD 128 ++ ++/* Low bit of init register says if memc is ddr or sdr */ ++#define MEMC_CONFIG_DDR 0x00000001 ++ ++#endif /* _SBMEMC_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbpci.h linux.dev/arch/mips/bcm947xx/include/sbpci.h +--- linux.old/arch/mips/bcm947xx/include/sbpci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbpci.h 2006-05-02 17:20:14.000000000 +0200 +@@ -0,0 +1,114 @@ +/* -+ * BCM47XX Sonics SiliconBackplane MIPS core routines ++ * HND SiliconBackplane PCI core hardware definitions. + * -+ * Copyright 2005, Broadcom Corporation ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -7378,1041 +7398,783 @@ diff -Naur linux.old/arch/mips/bcm947xx/sbmips.c linux.dev/arch/mips/bcm947xx/sb + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * $Id$ ++ * $Id: sbpci.h,v 1.1.1.11 2006/02/27 03:43:16 honor Exp $ + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * Returns TRUE if an external UART exists at the given base -+ * register. -+ */ -+static bool -+BCMINITFN(serial_exists)(uint8 *regs) -+{ -+ uint8 save_mcr, status1; ++#ifndef _sbpci_h_ ++#define _sbpci_h_ + -+ save_mcr = R_REG(®s[UART_MCR]); -+ W_REG(®s[UART_MCR], UART_MCR_LOOP | 0x0a); -+ status1 = R_REG(®s[UART_MSR]) & 0xf0; -+ W_REG(®s[UART_MCR], save_mcr); ++#ifndef _LANGUAGE_ASSEMBLY + -+ return (status1 == 0x90); -+} ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif + -+/* -+ * Initializes UART access. The callback function will be called once -+ * per found UART. -+ */ -+void -+BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift)) -+{ -+ void *regs; -+ ulong base; -+ uint irq; -+ int i, n; ++/* Sonics side: PCI core and host control registers */ ++typedef struct sbpciregs { ++ uint32 control; /* PCI control */ ++ uint32 PAD[3]; ++ uint32 arbcontrol; /* PCI arbiter control */ ++ uint32 PAD[3]; ++ uint32 intstatus; /* Interrupt status */ ++ uint32 intmask; /* Interrupt mask */ ++ uint32 sbtopcimailbox; /* Sonics to PCI mailbox */ ++ uint32 PAD[9]; ++ uint32 bcastaddr; /* Sonics broadcast address */ ++ uint32 bcastdata; /* Sonics broadcast data */ ++ uint32 PAD[2]; ++ uint32 gpioin; /* ro: gpio input (>=rev2) */ ++ uint32 gpioout; /* rw: gpio output (>=rev2) */ ++ uint32 gpioouten; /* rw: gpio output enable (>= rev2) */ ++ uint32 gpiocontrol; /* rw: gpio control (>= rev2) */ ++ uint32 PAD[36]; ++ uint32 sbtopci0; /* Sonics to PCI translation 0 */ ++ uint32 sbtopci1; /* Sonics to PCI translation 1 */ ++ uint32 sbtopci2; /* Sonics to PCI translation 2 */ ++ uint32 PAD[189]; ++ uint32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */ ++ uint16 sprom[36]; /* SPROM shadow Area */ ++ uint32 PAD[46]; ++} sbpciregs_t; + -+ if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) { -+ extifregs_t *eir = (extifregs_t *) regs; -+ sbconfig_t *sb; ++#endif /* _LANGUAGE_ASSEMBLY */ + -+ /* Determine external UART register base */ -+ sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF); -+ base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1))); -+ -+ /* Determine IRQ */ -+ irq = sb_irq(sbh); -+ -+ /* Disable GPIO interrupt initially */ -+ W_REG(&eir->gpiointpolarity, 0); -+ W_REG(&eir->gpiointmask, 0); -+ -+ /* Search for external UARTs */ -+ n = 2; -+ for (i = 0; i < 2; i++) { -+ regs = (void *) REG_MAP(base + (i * 8), 8); -+ if (BCMINIT(serial_exists)(regs)) { -+ /* Set GPIO 1 to be the external UART IRQ */ -+ W_REG(&eir->gpiointmask, 2); -+ if (add) -+ add(regs, irq, 13500000, 0); -+ } -+ } -+ -+ /* Add internal UART if enabled */ -+ if (R_REG(&eir->corecontrol) & CC_UE) -+ if (add) -+ add((void *) &eir->uartdata, irq, sb_clock(sbh), 2); -+ } else if ((regs = sb_setcore(sbh, SB_CC, 0))) { -+ chipcregs_t *cc = (chipcregs_t *) regs; -+ uint32 rev, cap, pll, baud_base, div; ++/* PCI control */ ++#define PCI_RST_OE 0x01 /* When set, drives PCI_RESET out to pin */ ++#define PCI_RST 0x02 /* Value driven out to pin */ ++#define PCI_CLK_OE 0x04 /* When set, drives clock as gated by PCI_CLK out to pin */ ++#define PCI_CLK 0x08 /* Gate for clock driven out to pin */ + -+ /* Determine core revision and capabilities */ -+ rev = sb_corerev(sbh); -+ cap = R_REG(&cc->capabilities); -+ pll = cap & CAP_PLL_MASK; ++/* PCI arbiter control */ ++#define PCI_INT_ARB 0x01 /* When set, use an internal arbiter */ ++#define PCI_EXT_ARB 0x02 /* When set, use an external arbiter */ ++/* ParkID - for PCI corerev >= 8 */ ++#define PCI_PARKID_MASK 0x1c /* Selects which agent is parked on an idle bus */ ++#define PCI_PARKID_SHIFT 2 ++#define PCI_PARKID_EXT0 0 /* External master 0 */ ++#define PCI_PARKID_EXT1 1 /* External master 1 */ ++#define PCI_PARKID_EXT2 2 /* External master 2 */ ++#define PCI_PARKID_INT 3 /* Internal master */ ++#define PCI_PARKID_LAST 4 /* Last active master */ + -+ /* Determine IRQ */ -+ irq = sb_irq(sbh); ++/* Interrupt status/mask */ ++#define PCI_INTA 0x01 /* PCI INTA# is asserted */ ++#define PCI_INTB 0x02 /* PCI INTB# is asserted */ ++#define PCI_SERR 0x04 /* PCI SERR# has been asserted (write one to clear) */ ++#define PCI_PERR 0x08 /* PCI PERR# has been asserted (write one to clear) */ ++#define PCI_PME 0x10 /* PCI PME# is asserted */ + -+ if (pll == PLL_TYPE1) { -+ /* PLL clock */ -+ baud_base = sb_clock_rate(pll, -+ R_REG(&cc->clockcontrol_n), -+ R_REG(&cc->clockcontrol_m2)); -+ div = 1; -+ } else { -+ if (rev >= 11) { -+ /* Fixed ALP clock */ -+ baud_base = 20000000; -+ div = 1; -+ /* Set the override bit so we don't divide it */ -+ W_REG(&cc->corecontrol, CC_UARTCLKO); -+ } else if (rev >= 3) { -+ /* Internal backplane clock */ -+ baud_base = sb_clock(sbh); -+ div = 2; /* Minimum divisor */ -+ W_REG(&cc->clkdiv, -+ ((R_REG(&cc->clkdiv) & ~CLKD_UART) | div)); -+ } else { -+ /* Fixed internal backplane clock */ -+ baud_base = 88000000; -+ div = 48; -+ } ++/* (General) PCI/SB mailbox interrupts, two bits per pci function */ ++#define MAILBOX_F0_0 0x100 /* function 0, int 0 */ ++#define MAILBOX_F0_1 0x200 /* function 0, int 1 */ ++#define MAILBOX_F1_0 0x400 /* function 1, int 0 */ ++#define MAILBOX_F1_1 0x800 /* function 1, int 1 */ ++#define MAILBOX_F2_0 0x1000 /* function 2, int 0 */ ++#define MAILBOX_F2_1 0x2000 /* function 2, int 1 */ ++#define MAILBOX_F3_0 0x4000 /* function 3, int 0 */ ++#define MAILBOX_F3_1 0x8000 /* function 3, int 1 */ + -+ /* Clock source depends on strapping if UartClkOverride is unset */ -+ if ((rev > 0) && -+ ((R_REG(&cc->corecontrol) & CC_UARTCLKO) == 0)) { -+ if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) { -+ /* Internal divided backplane clock */ -+ baud_base /= div; -+ } else { -+ /* Assume external clock of 1.8432 MHz */ -+ baud_base = 1843200; -+ } -+ } -+ } ++/* Sonics broadcast address */ ++#define BCAST_ADDR_MASK 0xff /* Broadcast register address */ + -+ /* Add internal UARTs */ -+ n = cap & CAP_UARTS_MASK; -+ for (i = 0; i < n; i++) { -+ /* Register offset changed after revision 0 */ -+ if (rev) -+ regs = (void *)((ulong) &cc->uart0data + (i * 256)); -+ else -+ regs = (void *)((ulong) &cc->uart0data + (i * 8)); ++/* Sonics to PCI translation types */ ++#define SBTOPCI0_MASK 0xfc000000 ++#define SBTOPCI1_MASK 0xfc000000 ++#define SBTOPCI2_MASK 0xc0000000 ++#define SBTOPCI_MEM 0 ++#define SBTOPCI_IO 1 ++#define SBTOPCI_CFG0 2 ++#define SBTOPCI_CFG1 3 ++#define SBTOPCI_PREF 0x4 /* prefetch enable */ ++#define SBTOPCI_BURST 0x8 /* burst enable */ ++#define SBTOPCI_RC_MASK 0x30 /* read command (>= rev11) */ ++#define SBTOPCI_RC_READ 0x00 /* memory read */ ++#define SBTOPCI_RC_READLINE 0x10 /* memory read line */ ++#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */ + -+ if (add) -+ add(regs, irq, baud_base, 0); -+ } -+ } -+} ++/* PCI core index in SROM shadow area */ ++#define SRSH_PI_OFFSET 0 /* first word */ ++#define SRSH_PI_MASK 0xf000 /* bit 15:12 */ ++#define SRSH_PI_SHIFT 12 /* bit 15:12 */ + ++#endif /* _sbpci_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbpcie.h linux.dev/arch/mips/bcm947xx/include/sbpcie.h +--- linux.old/arch/mips/bcm947xx/include/sbpcie.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbpcie.h 2006-04-27 20:42:22.000000000 +0200 +@@ -0,0 +1,200 @@ +/* -+ * Initialize jtag master and return handle for -+ * jtag_rwreg. Returns NULL on failure. ++ * BCM43XX SiliconBackplane PCIE core hardware definitions. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: sbpcie.h,v 1.1.1.2 2006/02/27 03:43:16 honor Exp $ + */ -+void * -+sb_jtagm_init(sb_t *sbh, uint clkd, bool exttap) -+{ -+ void *regs; + -+ if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) { -+ chipcregs_t *cc = (chipcregs_t *) regs; -+ uint32 tmp; -+ -+ /* -+ * Determine jtagm availability from -+ * core revision and capabilities. -+ */ -+ tmp = sb_corerev(sbh); -+ /* -+ * Corerev 10 has jtagm, but the only chip -+ * with it does not have a mips, and -+ * the layout of the jtagcmd register is -+ * different. We'll only accept >= 11. -+ */ -+ if (tmp < 11) -+ return (NULL); ++#ifndef _SBPCIE_H ++#define _SBPCIE_H + -+ tmp = R_REG(&cc->capabilities); -+ if ((tmp & CAP_JTAGP) == 0) -+ return (NULL); ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif + -+ /* Set clock divider if requested */ -+ if (clkd != 0) { -+ tmp = R_REG(&cc->clkdiv); -+ tmp = (tmp & ~CLKD_JTAG) | -+ ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG); -+ W_REG(&cc->clkdiv, tmp); -+ } ++/* PCIE Enumeration space offsets */ ++#define PCIE_CORE_CONFIG_OFFSET 0x0 ++#define PCIE_FUNC0_CONFIG_OFFSET 0x400 ++#define PCIE_FUNC1_CONFIG_OFFSET 0x500 ++#define PCIE_FUNC2_CONFIG_OFFSET 0x600 ++#define PCIE_FUNC3_CONFIG_OFFSET 0x700 ++#define PCIE_SPROM_SHADOW_OFFSET 0x800 ++#define PCIE_SBCONFIG_OFFSET 0xE00 + -+ /* Enable jtagm */ -+ tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0); -+ W_REG(&cc->jtagctrl, tmp); -+ } ++/* PCIE Bar0 Address Mapping. Each function maps 16KB config space */ ++#define PCIE_DEV_BAR0_SIZE 0x4000 ++#define PCIE_BAR0_WINMAPCORE_OFFSET 0x0 ++#define PCIE_BAR0_EXTSPROM_OFFSET 0x1000 ++#define PCIE_BAR0_PCIECORE_OFFSET 0x2000 ++#define PCIE_BAR0_CCCOREREG_OFFSET 0x3000 + -+ return (regs); -+} ++/* SB side: PCIE core and host control registers */ ++typedef struct sbpcieregs { ++ uint32 PAD[3]; ++ uint32 biststatus; /* bist Status: 0x00C */ ++ uint32 PAD[6]; ++ uint32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */ ++ uint32 PAD[54]; ++ uint32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ ++ uint32 sbtopcie1; /* sb to pcie translation 1: 0x104 */ ++ uint32 sbtopcie2; /* sb to pcie translation 2: 0x108 */ ++ uint32 PAD[4]; + -+void -+sb_jtagm_disable(void *h) -+{ -+ chipcregs_t *cc = (chipcregs_t *)h; ++ /* pcie core supports in direct access to config space */ ++ uint32 configaddr; /* pcie config space access: Address field: 0x120 */ ++ uint32 configdata; /* pcie config space access: Data field: 0x124 */ + -+ W_REG(&cc->jtagctrl, R_REG(&cc->jtagctrl) & ~JCTRL_EN); -+} ++ /* mdio access to serdes */ ++ uint32 mdiocontrol; /* controls the mdio access: 0x128 */ ++ uint32 mdiodata; /* Data to the mdio access: 0x12c */ + -+/* -+ * Read/write a jtag register. Assumes a target with -+ * 8 bit IR and 32 bit DR. -+ */ -+#define IRWIDTH 8 -+#define DRWIDTH 32 -+uint32 -+jtag_rwreg(void *h, uint32 ir, uint32 dr) -+{ -+ chipcregs_t *cc = (chipcregs_t *) h; -+ uint32 tmp; -+ -+ W_REG(&cc->jtagir, ir); -+ W_REG(&cc->jtagdr, dr); -+ tmp = JCMD_START | JCMD_ACC_IRDR | -+ ((IRWIDTH - 1) << JCMD_IRW_SHIFT) | -+ (DRWIDTH - 1); -+ W_REG(&cc->jtagcmd, tmp); -+ while (((tmp = R_REG(&cc->jtagcmd)) & JCMD_BUSY) == JCMD_BUSY) { -+ /* OSL_DELAY(1); */ -+ } ++ /* pcie protocol phy/dllp/tlp register access mechanism */ ++ uint32 pcieaddr; /* address of the internal registeru: 0x130 */ ++ uint32 pciedata; /* Data to/from the internal regsiter: 0x134 */ + -+ tmp = R_REG(&cc->jtagdr); -+ return (tmp); -+} ++ uint32 PAD[434]; ++ uint16 sprom[36]; /* SPROM shadow Area */ ++} sbpcieregs_t; + -+/* Returns the SB interrupt flag of the current core. */ -+uint32 -+sb_flag(sb_t *sbh) -+{ -+ void *regs; -+ sbconfig_t *sb; ++/* SB to PCIE translation masks */ ++#define SBTOPCIE0_MASK 0xfc000000 ++#define SBTOPCIE1_MASK 0xfc000000 ++#define SBTOPCIE2_MASK 0xc0000000 + -+ regs = sb_coreregs(sbh); -+ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); ++/* Access type bits (0:1) */ ++#define SBTOPCIE_MEM 0 ++#define SBTOPCIE_IO 1 ++#define SBTOPCIE_CFG0 2 ++#define SBTOPCIE_CFG1 3 + -+ return (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK); -+} ++/* Prefetch enable bit 2 */ ++#define SBTOPCIE_PF 4 + -+static const uint32 sbips_int_mask[] = { -+ 0, -+ SBIPS_INT1_MASK, -+ SBIPS_INT2_MASK, -+ SBIPS_INT3_MASK, -+ SBIPS_INT4_MASK -+}; ++/* Write Burst enable for memory write bit 3 */ ++#define SBTOPCIE_WR_BURST 8 + -+static const uint32 sbips_int_shift[] = { -+ 0, -+ 0, -+ SBIPS_INT2_SHIFT, -+ SBIPS_INT3_SHIFT, -+ SBIPS_INT4_SHIFT -+}; ++/* config access */ ++#define CONFIGADDR_FUNC_MASK 0x7000 ++#define CONFIGADDR_FUNC_SHF 12 ++#define CONFIGADDR_REG_MASK 0x0FFF ++#define CONFIGADDR_REG_SHF 0 + -+/* -+ * Returns the MIPS IRQ assignment of the current core. If unassigned, -+ * 0 is returned. -+ */ -+uint -+sb_irq(sb_t *sbh) -+{ -+ uint idx; -+ void *regs; -+ sbconfig_t *sb; -+ uint32 flag, sbipsflag; -+ uint irq = 0; ++/* PCIE protocol regs Indirect Address */ ++#define PCIEADDR_PROT_MASK 0x300 ++#define PCIEADDR_PROT_SHF 8 ++#define PCIEADDR_PL_TLP 0 ++#define PCIEADDR_PL_DLLP 1 ++#define PCIEADDR_PL_PLP 2 + -+ flag = sb_flag(sbh); ++/* PCIE protocol PHY diagnostic registers */ ++#define PCIE_PLP_MODEREG 0x200 /* Mode */ ++#define PCIE_PLP_STATUSREG 0x204 /* Status */ ++#define PCIE_PLP_LTSSMCTRLREG 0x208 /* LTSSM control */ ++#define PCIE_PLP_LTLINKNUMREG 0x20c /* Link Training Link number */ ++#define PCIE_PLP_LTLANENUMREG 0x210 /* Link Training Lane number */ ++#define PCIE_PLP_LTNFTSREG 0x214 /* Link Training N_FTS */ ++#define PCIE_PLP_ATTNREG 0x218 /* Attention */ ++#define PCIE_PLP_ATTNMASKREG 0x21C /* Attention Mask */ ++#define PCIE_PLP_RXERRCTR 0x220 /* Rx Error */ ++#define PCIE_PLP_RXFRMERRCTR 0x224 /* Rx Framing Error */ ++#define PCIE_PLP_RXERRTHRESHREG 0x228 /* Rx Error threshold */ ++#define PCIE_PLP_TESTCTRLREG 0x22C /* Test Control reg */ ++#define PCIE_PLP_SERDESCTRLOVRDREG 0x230 /* SERDES Control Override */ ++#define PCIE_PLP_TIMINGOVRDREG 0x234 /* Timing param override */ ++#define PCIE_PLP_RXTXSMDIAGREG 0x238 /* RXTX State Machine Diag */ ++#define PCIE_PLP_LTSSMDIAGREG 0x23C /* LTSSM State Machine Diag */ + -+ idx = sb_coreidx(sbh); ++/* PCIE protocol DLLP diagnostic registers */ ++#define PCIE_DLLP_LCREG 0x100 /* Link Control */ ++#define PCIE_DLLP_LSREG 0x104 /* Link Status */ ++#define PCIE_DLLP_LAREG 0x108 /* Link Attention */ ++#define PCIE_DLLP_LAMASKREG 0x10C /* Link Attention Mask */ ++#define PCIE_DLLP_NEXTTXSEQNUMREG 0x110 /* Next Tx Seq Num */ ++#define PCIE_DLLP_ACKEDTXSEQNUMREG 0x114 /* Acked Tx Seq Num */ ++#define PCIE_DLLP_PURGEDTXSEQNUMREG 0x118 /* Purged Tx Seq Num */ ++#define PCIE_DLLP_RXSEQNUMREG 0x11C /* Rx Sequence Number */ ++#define PCIE_DLLP_LRREG 0x120 /* Link Replay */ ++#define PCIE_DLLP_LACKTOREG 0x124 /* Link Ack Timeout */ ++#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */ ++#define PCIE_DLLP_RTRYWPREG 0x12C /* Retry buffer write ptr */ ++#define PCIE_DLLP_RTRYRPREG 0x130 /* Retry buffer Read ptr */ ++#define PCIE_DLLP_RTRYPPREG 0x134 /* Retry buffer Purged ptr */ ++#define PCIE_DLLP_RTRRWREG 0x138 /* Retry buffer Read/Write */ ++#define PCIE_DLLP_ECTHRESHREG 0x13C /* Error Count Threshold */ ++#define PCIE_DLLP_TLPERRCTRREG 0x140 /* TLP Error Counter */ ++#define PCIE_DLLP_ERRCTRREG 0x144 /* Error Counter */ ++#define PCIE_DLLP_NAKRXCTRREG 0x148 /* NAK Received Counter */ ++#define PCIE_DLLP_TESTREG 0x14C /* Test */ ++#define PCIE_DLLP_PKTBIST 0x150 /* Packet BIST */ + -+ if ((regs = sb_setcore(sbh, SB_MIPS, 0)) || -+ (regs = sb_setcore(sbh, SB_MIPS33, 0))) { -+ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); ++/* PCIE protocol TLP diagnostic registers */ ++#define PCIE_TLP_CONFIGREG 0x000 /* Configuration */ ++#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */ ++#define PCIE_TLP_WRDMAUPPER 0x010 /* Write DMA Upper Address */ ++#define PCIE_TLP_WRDMALOWER 0x014 /* Write DMA Lower Address */ ++#define PCIE_TLP_WRDMAREQ_LBEREG 0x018 /* Write DMA Len/ByteEn Req */ ++#define PCIE_TLP_RDDMAUPPER 0x01C /* Read DMA Upper Address */ ++#define PCIE_TLP_RDDMALOWER 0x020 /* Read DMA Lower Address */ ++#define PCIE_TLP_RDDMALENREG 0x024 /* Read DMA Len Req */ ++#define PCIE_TLP_MSIDMAUPPER 0x028 /* MSI DMA Upper Address */ ++#define PCIE_TLP_MSIDMALOWER 0x02C /* MSI DMA Lower Address */ ++#define PCIE_TLP_MSIDMALENREG 0x030 /* MSI DMA Len Req */ ++#define PCIE_TLP_SLVREQLENREG 0x034 /* Slave Request Len */ ++#define PCIE_TLP_FCINPUTSREQ 0x038 /* Flow Control Inputs */ ++#define PCIE_TLP_TXSMGRSREQ 0x03C /* Tx StateMachine and Gated Req */ ++#define PCIE_TLP_ADRACKCNTARBLEN 0x040 /* Address Ack XferCnt and ARB Len */ ++#define PCIE_TLP_DMACPLHDR0 0x044 /* DMA Completion Hdr 0 */ ++#define PCIE_TLP_DMACPLHDR1 0x048 /* DMA Completion Hdr 1 */ ++#define PCIE_TLP_DMACPLHDR2 0x04C /* DMA Completion Hdr 2 */ ++#define PCIE_TLP_DMACPLMISC0 0x050 /* DMA Completion Misc0 */ ++#define PCIE_TLP_DMACPLMISC1 0x054 /* DMA Completion Misc1 */ ++#define PCIE_TLP_DMACPLMISC2 0x058 /* DMA Completion Misc2 */ ++#define PCIE_TLP_SPTCTRLLEN 0x05C /* Split Controller Req len */ ++#define PCIE_TLP_SPTCTRLMSIC0 0x060 /* Split Controller Misc 0 */ ++#define PCIE_TLP_SPTCTRLMSIC1 0x064 /* Split Controller Misc 1 */ ++#define PCIE_TLP_BUSDEVFUNC 0x068 /* Bus/Device/Func */ ++#define PCIE_TLP_RESETCTR 0x06C /* Reset Counter */ ++#define PCIE_TLP_RTRYBUF 0x070 /* Retry Buffer value */ ++#define PCIE_TLP_TGTDEBUG1 0x074 /* Target Debug Reg1 */ ++#define PCIE_TLP_TGTDEBUG2 0x078 /* Target Debug Reg2 */ ++#define PCIE_TLP_TGTDEBUG3 0x07C /* Target Debug Reg3 */ ++#define PCIE_TLP_TGTDEBUG4 0x080 /* Target Debug Reg4 */ + -+ /* sbipsflag specifies which core is routed to interrupts 1 to 4 */ -+ sbipsflag = R_REG(&sb->sbipsflag); -+ for (irq = 1; irq <= 4; irq++) { -+ if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag) -+ break; -+ } -+ if (irq == 5) -+ irq = 0; -+ } -+ -+ sb_setcoreidx(sbh, idx); -+ -+ return irq; -+} ++/* MDIO control */ ++#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ ++#define MDIOCTL_DIVISOR_VAL 0x2 ++#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ ++#define MDIOCTL_ACCESS_DONE 0x100 /* Tranaction complete */ + -+/* Clears the specified MIPS IRQ. */ -+static void -+BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq) -+{ -+ void *regs; -+ sbconfig_t *sb; ++/* MDIO Data */ ++#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */ ++#define MDIODATA_TA 0x00020000 /* Turnaround */ ++#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ ++#define MDIODATA_REGADDR_MASK 0x003c0000 /* Regaddr Mask */ ++#define MDIODATA_DEVADDR_SHF 22 /* Physmedia devaddr shift */ ++#define MDIODATA_DEVADDR_MASK 0x0fc00000 /* Physmedia devaddr Mask */ ++#define MDIODATA_WRITE 0x10000000 /* write Transaction */ ++#define MDIODATA_READ 0x20000000 /* Read Transaction */ ++#define MDIODATA_START 0x40000000 /* start of Transaction */ + -+ if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) && -+ !(regs = sb_setcore(sbh, SB_MIPS33, 0))) -+ ASSERT(regs); -+ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); ++/* MDIO devices (SERDES modules) */ ++#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ ++#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ ++#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ + -+ if (irq == 0) -+ W_REG(&sb->sbintvec, 0); -+ else -+ OR_REG(&sb->sbipsflag, sbips_int_mask[irq]); -+} ++/* SERDES registers */ ++#define SERDES_RX_TIMER1 2 /* Rx Timer1 */ ++#define SERDES_RX_CDR 6 /* CDR */ ++#define SERDES_RX_CDRBW 7 /* CDR BW */ + ++#endif /* _SBPCIE_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbpcmcia.h linux.dev/arch/mips/bcm947xx/include/sbpcmcia.h +--- linux.old/arch/mips/bcm947xx/include/sbpcmcia.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbpcmcia.h 2006-04-27 20:29:47.000000000 +0200 +@@ -0,0 +1,147 @@ +/* -+ * Assigns the specified MIPS IRQ to the specified core. Shared MIPS -+ * IRQ 0 may be assigned more than once. ++ * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: sbpcmcia.h,v 1.1.1.9 2006/02/27 03:43:16 honor Exp $ + */ -+static void -+BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit) -+{ -+ void *regs; -+ sbconfig_t *sb; -+ uint32 flag; -+ -+ regs = sb_setcore(sbh, coreid, coreunit); -+ ASSERT(regs); -+ flag = sb_flag(sbh); + -+ if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) && -+ !(regs = sb_setcore(sbh, SB_MIPS33, 0))) -+ ASSERT(regs); -+ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); ++#ifndef _SBPCMCIA_H ++#define _SBPCMCIA_H + -+ if (irq == 0) -+ OR_REG(&sb->sbintvec, 1 << flag); -+ else { -+ flag <<= sbips_int_shift[irq]; -+ ASSERT(!(flag & ~sbips_int_mask[irq])); -+ flag |= R_REG(&sb->sbipsflag) & ~sbips_int_mask[irq]; -+ W_REG(&sb->sbipsflag, flag); -+ } -+} + -+/* -+ * Initializes clocks and interrupts. SB and NVRAM access must be -+ * initialized prior to calling. ++/* All the addresses that are offsets in attribute space are divided ++ * by two to account for the fact that odd bytes are invalid in ++ * attribute space and our read/write routines make the space appear ++ * as if they didn't exist. Still we want to show the original numbers ++ * as documented in the hnd_pcmcia core manual. + */ -+void -+BCMINITFN(sb_mips_init)(sb_t *sbh) -+{ -+ ulong hz, ns, tmp; -+ extifregs_t *eir; -+ chipcregs_t *cc; -+ char *value; -+ uint irq; + -+ /* Figure out current SB clock speed */ -+ if ((hz = sb_clock(sbh)) == 0) -+ hz = 100000000; -+ ns = 1000000000 / hz; ++/* PCMCIA Function Configuration Registers */ ++#define PCMCIA_FCR (0x700 / 2) + -+ /* Setup external interface timing */ -+ if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) { -+ /* Initialize extif so we can get to the LEDs and external UART */ -+ W_REG(&eir->prog_config, CF_EN); ++#define FCR0_OFF 0 ++#define FCR1_OFF (0x40 / 2) ++#define FCR2_OFF (0x80 / 2) ++#define FCR3_OFF (0xc0 / 2) + -+ /* Set timing for the flash */ -+ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ -+ tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */ -+ tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ -+ W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */ ++#define PCMCIA_FCR0 (0x700 / 2) ++#define PCMCIA_FCR1 (0x740 / 2) ++#define PCMCIA_FCR2 (0x780 / 2) ++#define PCMCIA_FCR3 (0x7c0 / 2) + -+ /* Set programmable interface timing for external uart */ -+ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ -+ tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */ -+ tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */ -+ tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ -+ W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */ -+ } else if ((cc = sb_setcore(sbh, SB_CC, 0))) { -+ /* Set timing for the flash */ -+ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ -+ tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */ -+ tmp |= CEIL(120, ns); /* W0 = 120nS */ -+ -+ // Added by Chen-I for 5365 -+ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) -+ { -+ W_REG(&cc->flash_waitcount, tmp); -+ W_REG(&cc->pcmcia_memwait, tmp); -+ } -+ else -+ { -+ if (sb_corerev(sbh) < 9) -+ W_REG(&cc->flash_waitcount, tmp); ++/* Standard PCMCIA FCR registers */ + -+ if ((sb_corerev(sbh) < 9) || -+ ((BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID) && BCMINIT(sb_chiprev)(sbh) == 0)) { -+ W_REG(&cc->pcmcia_memwait, tmp); -+ } -+ } -+ } ++#define PCMCIA_COR 0 + -+ /* Chip specific initialization */ -+ switch (BCMINIT(sb_chip)(sbh)) { -+ case BCM4710_DEVICE_ID: -+ /* Clear interrupt map */ -+ for (irq = 0; irq <= 4; irq++) -+ BCMINIT(sb_clearirq)(sbh, irq); -+ BCMINIT(sb_setirq)(sbh, 0, SB_CODEC, 0); -+ BCMINIT(sb_setirq)(sbh, 0, SB_EXTIF, 0); -+ BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 1); -+ BCMINIT(sb_setirq)(sbh, 3, SB_ILINE20, 0); -+ BCMINIT(sb_setirq)(sbh, 4, SB_PCI, 0); -+ ASSERT(eir); -+ value = BCMINIT(nvram_get)("et0phyaddr"); -+ if (value && !strcmp(value, "31")) { -+ /* Enable internal UART */ -+ W_REG(&eir->corecontrol, CC_UE); -+ /* Give USB its own interrupt */ -+ BCMINIT(sb_setirq)(sbh, 1, SB_USB, 0); -+ } else { -+ /* Disable internal UART */ -+ W_REG(&eir->corecontrol, 0); -+ /* Give Ethernet its own interrupt */ -+ BCMINIT(sb_setirq)(sbh, 1, SB_ENET, 0); -+ BCMINIT(sb_setirq)(sbh, 0, SB_USB, 0); -+ } -+ break; -+ case BCM5350_DEVICE_ID: -+ /* Clear interrupt map */ -+ for (irq = 0; irq <= 4; irq++) -+ BCMINIT(sb_clearirq)(sbh, irq); -+ BCMINIT(sb_setirq)(sbh, 0, SB_CC, 0); -+ BCMINIT(sb_setirq)(sbh, 1, SB_D11, 0); -+ BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 0); -+ BCMINIT(sb_setirq)(sbh, 3, SB_PCI, 0); -+ BCMINIT(sb_setirq)(sbh, 4, SB_USB, 0); -+ break; -+ } -+} ++#define COR_RST 0x80 ++#define COR_LEV 0x40 ++#define COR_IRQEN 0x04 ++#define COR_BLREN 0x01 ++#define COR_FUNEN 0x01 + -+uint32 -+BCMINITFN(sb_mips_clock)(sb_t *sbh) -+{ -+ extifregs_t *eir; -+ chipcregs_t *cc; -+ uint32 n, m; -+ uint idx; -+ uint32 pll_type, rate = 0; + -+ /* get index of the current core */ -+ idx = sb_coreidx(sbh); -+ pll_type = PLL_TYPE1; ++#define PCICIA_FCSR (2 / 2) ++#define PCICIA_PRR (4 / 2) ++#define PCICIA_SCR (6 / 2) ++#define PCICIA_ESR (8 / 2) + -+ /* switch to extif or chipc core */ -+ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) { -+ n = R_REG(&eir->clockcontrol_n); -+ m = R_REG(&eir->clockcontrol_sb); -+ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { -+ pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK; -+ n = R_REG(&cc->clockcontrol_n); -+ if ((pll_type == PLL_TYPE2) || -+ (pll_type == PLL_TYPE4) || -+ (pll_type == PLL_TYPE6) || -+ (pll_type == PLL_TYPE7)) -+ m = R_REG(&cc->clockcontrol_mips); -+ else if (pll_type == PLL_TYPE5) { -+ rate = 200000000; -+ goto out; -+ } -+ else if (pll_type == PLL_TYPE3) { -+ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) { /* 5365 is also type3 */ -+ rate = 200000000; -+ goto out; -+ } else -+ m = R_REG(&cc->clockcontrol_m2); /* 5350 uses m2 to control mips */ -+ } else -+ m = R_REG(&cc->clockcontrol_sb); -+ } else -+ goto out; + -+ // Added by Chen-I for 5365 -+ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) -+ rate = 100000000; -+ else -+ /* calculate rate */ -+ rate = sb_clock_rate(pll_type, n, m); ++#define PCM_MEMOFF 0x0000 ++#define F0_MEMOFF 0x1000 ++#define F1_MEMOFF 0x2000 ++#define F2_MEMOFF 0x3000 ++#define F3_MEMOFF 0x4000 + -+ if (pll_type == PLL_TYPE6) -+ rate = SB2MIPS_T6(rate); ++/* Memory base in the function fcr's */ ++#define MEM_ADDR0 (0x728 / 2) ++#define MEM_ADDR1 (0x72a / 2) ++#define MEM_ADDR2 (0x72c / 2) + -+out: -+ /* switch back to previous core */ -+ sb_setcoreidx(sbh, idx); ++/* PCMCIA base plus Srom access in fcr0: */ ++#define PCMCIA_ADDR0 (0x072e / 2) ++#define PCMCIA_ADDR1 (0x0730 / 2) ++#define PCMCIA_ADDR2 (0x0732 / 2) + -+ return rate; -+} ++#define MEM_SEG (0x0734 / 2) ++#define SROM_CS (0x0736 / 2) ++#define SROM_DATAL (0x0738 / 2) ++#define SROM_DATAH (0x073a / 2) ++#define SROM_ADDRL (0x073c / 2) ++#define SROM_ADDRH (0x073e / 2) + -+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) ++/* Values for srom_cs: */ ++#define SROM_IDLE 0 ++#define SROM_WRITE 1 ++#define SROM_READ 2 ++#define SROM_WEN 4 ++#define SROM_WDS 7 ++#define SROM_DONE 8 + -+static void -+BCMINITFN(handler)(void) -+{ -+ /* Step 11 */ -+ __asm__ ( -+ ".set\tmips32\n\t" -+ "ssnop\n\t" -+ "ssnop\n\t" -+ /* Disable interrupts */ -+ /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */ -+ "mfc0 $15, $12\n\t" -+ /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */ -+ "li $14, -31746\n\t" -+ "and $15, $15, $14\n\t" -+ "mtc0 $15, $12\n\t" -+ "eret\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ ".set\tmips0" -+ ); -+} ++/* CIS stuff */ + -+/* The following MUST come right after handler() */ -+static void -+BCMINITFN(afterhandler)(void) -+{ -+} ++/* The CIS stops where the FCRs start */ ++#define CIS_SIZE PCMCIA_FCR + -+/* -+ * Set the MIPS, backplane and PCI clocks as closely as possible. -+ */ -+bool -+BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock) -+{ -+ extifregs_t *eir = NULL; -+ chipcregs_t *cc = NULL; -+ mipsregs_t *mipsr = NULL; -+ volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2; -+ uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg; -+ uint32 pll_type, sync_mode; -+ uint ic_size, ic_lsize; -+ uint idx, i; -+ typedef struct { -+ uint32 mipsclock; -+ uint16 n; -+ uint32 sb; -+ uint32 pci33; -+ uint32 pci25; -+ } n3m_table_t; -+ static n3m_table_t BCMINITDATA(type1_table)[] = { -+ { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, /* 96.000 32.000 24.000 */ -+ { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, /* 100.000 33.333 25.000 */ -+ { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, /* 104.000 31.200 24.960 */ -+ { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, /* 108.000 32.400 24.923 */ -+ { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, /* 112.000 32.000 24.889 */ -+ { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, /* 115.200 32.000 24.000 */ -+ { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, /* 120.000 30.000 24.000 */ -+ { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, /* 124.800 31.200 24.960 */ -+ { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, /* 128.000 32.000 24.000 */ -+ { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, /* 132.000 33.000 24.750 */ -+ { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, /* 136.000 32.640 24.727 */ -+ { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, /* 140.000 30.000 24.706 */ -+ { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, /* 144.000 30.857 24.686 */ -+ { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, /* 150.857 33.000 24.000 */ -+ { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, /* 152.000 32.571 24.000 */ -+ { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, /* 156.000 31.200 24.960 */ -+ { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, /* 160.000 32.000 24.000 */ -+ { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, /* 163.200 32.640 24.727 */ -+ { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, /* 168.000 32.000 24.889 */ -+ { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, /* 176.000 33.000 24.000 */ -+ }; -+ typedef struct { -+ uint32 mipsclock; -+ uint16 n; -+ uint32 m2; /* that is the clockcontrol_m2 */ -+ } type3_table_t; -+ static type3_table_t type3_table[] = { /* for 5350, mips clock is always double sb clock */ -+ { 150000000, 0x311, 0x4020005 }, -+ { 200000000, 0x311, 0x4020003 }, -+ }; -+ typedef struct { -+ uint32 mipsclock; -+ uint32 sbclock; -+ uint16 n; -+ uint32 sb; -+ uint32 pci33; -+ uint32 m2; -+ uint32 m3; -+ uint32 ratio_cfg; -+ uint32 ratio_parm; -+ } n4m_table_t; ++/* Standard tuples we know about */ + -+ static n4m_table_t BCMINITDATA(type2_table)[] = { -+ { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9 }, -+ { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555 }, -+ { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555 }, -+ { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 }, -+ { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 }, -+ { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 }, -+ { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9 }, -+ { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 }, -+ { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555 }, -+ { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555 }, -+ { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 }, -+ { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 }, -+ { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 }, -+ { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 }, -+ { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 }, -+ { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01020600, 0x05000100, 8, 0x012a00a9 }, -+ { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01000100, 0x05000100, 11, 0x0aaa0555 } -+ }; ++#define CISTPL_MANFID 0x20 /* Manufacturer and device id */ ++#define CISTPL_FUNCE 0x22 /* Function extensions */ ++#define CISTPL_CFTABLE 0x1b /* Config table entry */ + -+ static n4m_table_t BCMINITDATA(type4_table)[] = { -+ { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 }, -+ { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 }, -+ { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11, 0x0aaa0555 }, -+ { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11, 0x0aaa0555 }, -+ { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8, 0x012a00a9 }, -+ { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13, 0x254a14a9 }, -+ { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11, 0x0aaa0555 }, -+ { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9, 0x02520129 }, -+ { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 }, -+ { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 }, -+ { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13, 0x254a14a9 }, -+ { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 }, -+ { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 }, -+ { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9, 0x02520129 }, -+ { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11, 0x0aaa0555 } -+ }; ++/* Function extensions for LANs */ + -+ static n4m_table_t BCMINITDATA(type7_table)[] = { -+ { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 }, -+ { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 }, -+ { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11, 0x0aaa0555 }, -+ { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 }, -+ { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 }, -+ { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 }, -+ { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 }, -+ { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 }, -+ { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11, 0x0aaa0555 }, -+ { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11, 0x0aaa0555 } -+ }; ++#define LAN_TECH 1 /* Technology type */ ++#define LAN_SPEED 2 /* Raw bit rate */ ++#define LAN_MEDIA 3 /* Transmission media */ ++#define LAN_NID 4 /* Node identification (aka MAC addr) */ ++#define LAN_CONN 5 /* Connector standard */ + -+ ulong start, end, dst; -+ bool ret = FALSE; + -+ /* get index of the current core */ -+ idx = sb_coreidx(sbh); -+ clockcontrol_m2 = NULL; ++/* CFTable */ ++#define CFTABLE_REGWIN_2K 0x08 /* 2k reg windows size */ ++#define CFTABLE_REGWIN_4K 0x10 /* 4k reg windows size */ ++#define CFTABLE_REGWIN_8K 0x20 /* 8k reg windows size */ + -+ /* switch to extif or chipc core */ -+ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) { -+ pll_type = PLL_TYPE1; -+ clockcontrol_n = &eir->clockcontrol_n; -+ clockcontrol_sb = &eir->clockcontrol_sb; -+ clockcontrol_pci = &eir->clockcontrol_pci; -+ clockcontrol_m2 = &cc->clockcontrol_m2; -+ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { -+ pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK; -+ if (pll_type == PLL_TYPE6) { -+ clockcontrol_n = NULL; -+ clockcontrol_sb = NULL; -+ clockcontrol_pci = NULL; -+ } else { -+ clockcontrol_n = &cc->clockcontrol_n; -+ clockcontrol_sb = &cc->clockcontrol_sb; -+ clockcontrol_pci = &cc->clockcontrol_pci; -+ clockcontrol_m2 = &cc->clockcontrol_m2; -+ } -+ } else -+ goto done; ++/* Vendor unique tuples are 0x80-0x8f. Within Broadcom we'll ++ * take one for HNBU, and use "extensions" (a la FUNCE) within it. ++ */ + -+ if (pll_type == PLL_TYPE6) { -+ /* Silence compilers */ -+ orig_n = orig_sb = orig_pci = 0; -+ } else { -+ /* Store the current clock register values */ -+ orig_n = R_REG(clockcontrol_n); -+ orig_sb = R_REG(clockcontrol_sb); -+ orig_pci = R_REG(clockcontrol_pci); -+ } ++#define CISTPL_BRCM_HNBU 0x80 + -+ if (pll_type == PLL_TYPE1) { -+ /* Keep the current PCI clock if not specified */ -+ if (pciclock == 0) { -+ pciclock = sb_clock_rate(pll_type, R_REG(clockcontrol_n), R_REG(clockcontrol_pci)); -+ pciclock = (pciclock <= 25000000) ? 25000000 : 33000000; -+ } ++/* Subtypes of BRCM_HNBU: */ + -+ /* Search for the closest MIPS clock less than or equal to a preferred value */ -+ for (i = 0; i < ARRAYSIZE(BCMINIT(type1_table)); i++) { -+ ASSERT(BCMINIT(type1_table)[i].mipsclock == -+ sb_clock_rate(pll_type, BCMINIT(type1_table)[i].n, BCMINIT(type1_table)[i].sb)); -+ if (BCMINIT(type1_table)[i].mipsclock > mipsclock) -+ break; -+ } -+ if (i == 0) { -+ ret = FALSE; -+ goto done; -+ } else { -+ ret = TRUE; -+ i--; -+ } -+ ASSERT(BCMINIT(type1_table)[i].mipsclock <= mipsclock); ++#define HNBU_SROMREV 0x00 /* A byte with sromrev, 1 if not present */ ++#define HNBU_CHIPID 0x01 /* Two 16bit values: PCI vendor & device id */ ++#define HNBU_BOARDREV 0x02 /* One byte board revision */ ++#define HNBU_PAPARMS 0x03 /* PA parameters: 8 (sromrev == 1) ++ * or 9 (sromrev > 1) bytes ++ */ ++#define HNBU_OEM 0x04 /* Eight bytes OEM data (sromrev == 1) */ ++#define HNBU_CC 0x05 /* Default country code (sromrev == 1) */ ++#define HNBU_AA 0x06 /* Antennas available */ ++#define HNBU_AG 0x07 /* Antenna gain */ ++#define HNBU_BOARDFLAGS 0x08 /* board flags (2 or 4 bytes) */ ++#define HNBU_LEDS 0x09 /* LED set */ ++#define HNBU_CCODE 0x0a /* Country code (2 bytes ascii + 1 byte cctl) ++ * in rev 2 ++ */ ++#define HNBU_CCKPO 0x0b /* 2 byte cck power offsets in rev 3 */ ++#define HNBU_OFDMPO 0x0c /* 4 byte 11g ofdm power offsets in rev 3 */ ++#define HNBU_GPIOTIMER 0x0d /* 2 bytes with on/off values in rev 3 */ + -+ /* No PLL change */ -+ if ((orig_n == BCMINIT(type1_table)[i].n) && -+ (orig_sb == BCMINIT(type1_table)[i].sb) && -+ (orig_pci == BCMINIT(type1_table)[i].pci33)) -+ goto done; + -+ /* Set the PLL controls */ -+ W_REG(clockcontrol_n, BCMINIT(type1_table)[i].n); -+ W_REG(clockcontrol_sb, BCMINIT(type1_table)[i].sb); -+ if (pciclock == 25000000) -+ W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci25); -+ else -+ W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci33); ++/* sbtmstatelow */ ++#define SBTML_INT_ACK 0x40000 /* ack the sb interrupt */ ++#define SBTML_INT_EN 0x20000 /* enable sb interrupt */ + -+ /* Reset */ -+ sb_watchdog(sbh, 1); ++/* sbtmstatehigh */ ++#define SBTMH_INT_STATUS 0x40000 /* sb interrupt status */ + -+ while (1); -+ } else if ((pll_type == PLL_TYPE3) && -+ (BCMINIT(sb_chip)(sbh) != BCM5365_DEVICE_ID)) { -+ /* 5350 */ -+ /* Search for the closest MIPS clock less than or equal to a preferred value */ ++#endif /* _SBPCMCIA_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbsdram.h linux.dev/arch/mips/bcm947xx/include/sbsdram.h +--- linux.old/arch/mips/bcm947xx/include/sbsdram.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbsdram.h 2006-04-27 20:36:08.000000000 +0200 +@@ -0,0 +1,85 @@ ++/* ++ * BCM47XX Sonics SiliconBackplane SDRAM controller core hardware definitions. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: sbsdram.h,v 1.1.1.9 2006/03/02 13:03:52 honor Exp $ ++ */ + -+ for (i = 0; i < ARRAYSIZE(type3_table); i++) { -+ if (type3_table[i].mipsclock > mipsclock) -+ break; -+ } -+ if (i == 0) { -+ ret = FALSE; -+ goto done; -+ } else { -+ ret = TRUE; -+ i--; -+ } -+ ASSERT(type3_table[i].mipsclock <= mipsclock); ++#ifndef _SBSDRAM_H ++#define _SBSDRAM_H + -+ /* No PLL change */ -+ orig_m2 = R_REG(&cc->clockcontrol_m2); -+ if ((orig_n == type3_table[i].n) && -+ (orig_m2 == type3_table[i].m2)) { -+ goto done; -+ } ++#ifndef _LANGUAGE_ASSEMBLY + -+ /* Set the PLL controls */ -+ W_REG(clockcontrol_n, type3_table[i].n); -+ W_REG(clockcontrol_m2, type3_table[i].m2); ++/* Sonics side: SDRAM core registers */ ++typedef volatile struct sbsdramregs { ++ uint32 initcontrol; /* Generates external SDRAM initialization sequence */ ++ uint32 config; /* Initializes external SDRAM mode register */ ++ uint32 refresh; /* Controls external SDRAM refresh rate */ ++ uint32 pad1; ++ uint32 pad2; ++} sbsdramregs_t; + -+ /* Reset */ -+ sb_watchdog(sbh, 1); -+ while (1); -+ } else if ((pll_type == PLL_TYPE2) || -+ (pll_type == PLL_TYPE4) || -+ (pll_type == PLL_TYPE6) || -+ (pll_type == PLL_TYPE7)) { -+ n4m_table_t *table = NULL, *te; -+ uint tabsz = 0; ++/* SDRAM simulation */ ++#ifdef RAMSZ ++#define SDRAMSZ RAMSZ ++#else ++#define SDRAMSZ (4 * 1024 * 1024) ++#endif + -+ ASSERT(cc); ++extern uchar sdrambuf[SDRAMSZ]; + -+ orig_mips = R_REG(&cc->clockcontrol_mips); ++#endif /* _LANGUAGE_ASSEMBLY */ + -+ if (pll_type == PLL_TYPE6) { -+ uint32 new_mips = 0; ++/* SDRAM initialization control (initcontrol) register bits */ ++#define SDRAM_CBR 0x0001 /* Writing 1 generates refresh cycle and toggles bit */ ++#define SDRAM_PRE 0x0002 /* Writing 1 generates precharge cycle and toggles bit */ ++#define SDRAM_MRS 0x0004 /* Writing 1 generates mode register select cycle and toggles bit */ ++#define SDRAM_EN 0x0008 /* When set, enables access to SDRAM */ ++#define SDRAM_16Mb 0x0000 /* Use 16 Megabit SDRAM */ ++#define SDRAM_64Mb 0x0010 /* Use 64 Megabit SDRAM */ ++#define SDRAM_128Mb 0x0020 /* Use 128 Megabit SDRAM */ ++#define SDRAM_RSVMb 0x0030 /* Use special SDRAM */ ++#define SDRAM_RST 0x0080 /* Writing 1 causes soft reset of controller */ ++#define SDRAM_SELFREF 0x0100 /* Writing 1 enables self refresh mode */ ++#define SDRAM_PWRDOWN 0x0200 /* Writing 1 causes controller to power down */ ++#define SDRAM_32BIT 0x0400 /* When set, indicates 32 bit SDRAM interface */ ++#define SDRAM_9BITCOL 0x0800 /* When set, indicates 9 bit column */ + -+ ret = TRUE; -+ if (mipsclock <= SB2MIPS_T6(CC_T6_M1)) -+ new_mips = CC_T6_MMASK; ++/* SDRAM configuration (config) register bits */ ++#define SDRAM_BURSTFULL 0x0000 /* Use full page bursts */ ++#define SDRAM_BURST8 0x0001 /* Use burst of 8 */ ++#define SDRAM_BURST4 0x0002 /* Use burst of 4 */ ++#define SDRAM_BURST2 0x0003 /* Use burst of 2 */ ++#define SDRAM_CAS3 0x0000 /* Use CAS latency of 3 */ ++#define SDRAM_CAS2 0x0004 /* Use CAS latency of 2 */ + -+ if (orig_mips == new_mips) -+ goto done; ++/* SDRAM refresh control (refresh) register bits */ ++#define SDRAM_REF(p) (((p)&0xff) | SDRAM_REF_EN) /* Refresh period */ ++#define SDRAM_REF_EN 0x8000 /* Writing 1 enables periodic refresh */ + -+ W_REG(&cc->clockcontrol_mips, new_mips); -+ goto end_fill; -+ } ++/* SDRAM Core default Init values (OCP ID 0x803) */ ++#define SDRAM_INIT MEM4MX16X2 ++#define SDRAM_CONFIG SDRAM_BURSTFULL ++#define SDRAM_REFRESH SDRAM_REF(0x40) + -+ if (pll_type == PLL_TYPE2) { -+ table = BCMINIT(type2_table); -+ tabsz = ARRAYSIZE(BCMINIT(type2_table)); -+ } else if (pll_type == PLL_TYPE4) { -+ table = BCMINIT(type4_table); -+ tabsz = ARRAYSIZE(BCMINIT(type4_table)); -+ } else if (pll_type == PLL_TYPE7) { -+ table = BCMINIT(type7_table); -+ tabsz = ARRAYSIZE(BCMINIT(type7_table)); -+ } else -+ ASSERT("No table for plltype" == NULL); ++#define MEM1MX16 0x009 /* 2 MB */ ++#define MEM1MX16X2 0x409 /* 4 MB */ ++#define MEM2MX8X2 0x809 /* 4 MB */ ++#define MEM2MX8X4 0xc09 /* 8 MB */ ++#define MEM2MX32 0x439 /* 8 MB */ ++#define MEM4MX16 0x019 /* 8 MB */ ++#define MEM4MX16X2 0x419 /* 16 MB */ ++#define MEM8MX8X2 0x819 /* 16 MB */ ++#define MEM8MX16 0x829 /* 16 MB */ ++#define MEM4MX32 0x429 /* 16 MB */ ++#define MEM8MX8X4 0xc19 /* 32 MB */ ++#define MEM8MX16X2 0xc29 /* 32 MB */ + -+ /* Store the current clock register values */ -+ orig_m2 = R_REG(&cc->clockcontrol_m2); -+ orig_ratio_parm = 0; -+ orig_ratio_cfg = 0; ++#endif /* _SBSDRAM_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbsocram.h linux.dev/arch/mips/bcm947xx/include/sbsocram.h +--- linux.old/arch/mips/bcm947xx/include/sbsocram.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbsocram.h 2006-04-27 22:13:19.000000000 +0200 +@@ -0,0 +1,64 @@ ++/* ++ * BCM47XX Sonics SiliconBackplane embedded ram core ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: sbsocram.h,v 1.1.1.3 2006/02/27 03:43:16 honor Exp $ ++ */ + -+ /* Look up current ratio */ -+ for (i = 0; i < tabsz; i++) { -+ if ((orig_n == table[i].n) && -+ (orig_sb == table[i].sb) && -+ (orig_pci == table[i].pci33) && -+ (orig_m2 == table[i].m2) && -+ (orig_mips == table[i].m3)) { -+ orig_ratio_parm = table[i].ratio_parm; -+ orig_ratio_cfg = table[i].ratio_cfg; -+ break; -+ } -+ } -+ -+ /* Search for the closest MIPS clock greater or equal to a preferred value */ -+ for (i = 0; i < tabsz; i++) { -+ ASSERT(table[i].mipsclock == -+ sb_clock_rate(pll_type, table[i].n, table[i].m3)); -+ if ((mipsclock <= table[i].mipsclock) && -+ ((sbclock == 0) || (sbclock <= table[i].sbclock))) -+ break; -+ } -+ if (i == tabsz) { -+ ret = FALSE; -+ goto done; -+ } else { -+ te = &table[i]; -+ ret = TRUE; -+ } -+ -+ /* No PLL change */ -+ if ((orig_n == te->n) && -+ (orig_sb == te->sb) && -+ (orig_pci == te->pci33) && -+ (orig_m2 == te->m2) && -+ (orig_mips == te->m3)) -+ goto done; -+ -+ /* Set the PLL controls */ -+ W_REG(clockcontrol_n, te->n); -+ W_REG(clockcontrol_sb, te->sb); -+ W_REG(clockcontrol_pci, te->pci33); -+ W_REG(&cc->clockcontrol_m2, te->m2); -+ W_REG(&cc->clockcontrol_mips, te->m3); -+ -+ /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */ -+ if ((pll_type == PLL_TYPE7) && -+ (te->sb != te->m2) && -+ (sb_clock_rate(pll_type, te->n, te->m2) == 120000000)) -+ W_REG(&cc->chipcontrol, R_REG(&cc->chipcontrol) | 0x100); -+ -+ /* No ratio change */ -+ if (orig_ratio_parm == te->ratio_parm) -+ goto end_fill; -+ -+ icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize); -+ -+ /* Preload the code into the cache */ -+ start = ((ulong) &&start_fill) & ~(ic_lsize - 1); -+ end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1); -+ while (start < end) { -+ cache_op(start, Fill_I); -+ start += ic_lsize; -+ } -+ -+ /* Copy the handler */ -+ start = (ulong) &BCMINIT(handler); -+ end = (ulong) &BCMINIT(afterhandler); -+ dst = KSEG1ADDR(0x180); -+ for (i = 0; i < (end - start); i += 4) -+ *((ulong *)(dst + i)) = *((ulong *)(start + i)); -+ -+ /* Preload handler into the cache one line at a time */ -+ for (i = 0; i < (end - start); i += 4) -+ cache_op(dst + i, Fill_I); -+ -+ /* Clear BEV bit */ -+ MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV); -+ -+ /* Enable interrupts */ -+ MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE)); ++#ifndef _SBSOCRAM_H ++#define _SBSOCRAM_H + -+ /* Enable MIPS timer interrupt */ -+ if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) && -+ !(mipsr = sb_setcore(sbh, SB_MIPS33, 0))) -+ ASSERT(mipsr); -+ W_REG(&mipsr->intmask, 1); ++#define SR_COREINFO 0x00 ++#define SR_BWALLOC 0x04 ++#define SR_BISTSTAT 0x0c ++#define SR_BANKINDEX 0x10 ++#define SR_BANKSTBYCTL 0x14 + -+ start_fill: -+ /* step 1, set clock ratios */ -+ MTC0(C0_BROADCOM, 3, te->ratio_parm); -+ MTC0(C0_BROADCOM, 1, te->ratio_cfg); + -+ /* step 2: program timer intr */ -+ W_REG(&mipsr->timer, 100); -+ (void) R_REG(&mipsr->timer); ++#ifndef _LANGUAGE_ASSEMBLY + -+ /* step 3, switch to async */ -+ sync_mode = MFC0(C0_BROADCOM, 4); -+ MTC0(C0_BROADCOM, 4, 1 << 22); ++/* Memcsocram core registers */ ++typedef volatile struct sbsocramregs { ++ uint32 coreinfo; ++ uint32 bwalloc; ++ uint32 PAD; ++ uint32 biststat; ++ uint32 bankidx; ++ uint32 standbyctrl; ++} sbsocramregs_t; + -+ /* step 4, set cfg active */ -+ MTC0(C0_BROADCOM, 2, 0x9); ++#endif + ++/* Coreinfo register */ ++#define SRCI_PT_MASK 0x30000 ++#define SRCI_PT_SHIFT 16 + -+ /* steps 5 & 6 */ -+ __asm__ __volatile__ ( -+ ".set\tmips3\n\t" -+ "wait\n\t" -+ ".set\tmips0" -+ ); ++/* In corerev 0, the memory size is 2 to the power of the ++ * base plus 16 plus to the contents of the memsize field plus 1. ++ */ ++#define SRCI_MS0_MASK 0xf ++#define SR_MS0_BASE 16 + -+ /* step 7, clear cfg_active */ -+ MTC0(C0_BROADCOM, 2, 0); ++/* ++ * In corerev 1 the bank size is 2 ^ the bank size field plus 14, ++ * the memory size is number of banks times bank size. ++ * The same applies to rom size. ++ */ ++#define SRCI_ROMNB_MASK 0xf000 ++#define SRCI_ROMNB_SHIFT 12 ++#define SRCI_ROMBSZ_MASK 0xf00 ++#define SRCI_ROMBSZ_SHIFT 8 ++#define SRCI_SRNB_MASK 0xf0 ++#define SRCI_SRNB_SHIFT 4 ++#define SRCI_SRBSZ_MASK 0xf ++#define SRCI_SRBSZ_SHIFT 0 ++ ++#define SR_BSZ_BASE 14 ++#endif /* _SBSOCRAM_H */ +diff -urN linux.old/arch/mips/bcm947xx/include/sbutils.h linux.dev/arch/mips/bcm947xx/include/sbutils.h +--- linux.old/arch/mips/bcm947xx/include/sbutils.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sbutils.h 2006-04-27 23:09:25.000000000 +0200 +@@ -0,0 +1,150 @@ ++/* ++ * Misc utility routines for accessing chip-specific features ++ * of Broadcom HNBU SiliconBackplane-based chips. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: sbutils.h,v 1.4 2006/04/08 07:12:42 honor Exp $ ++ */ + -+ /* Additional Step: set back to orig sync mode */ -+ MTC0(C0_BROADCOM, 4, sync_mode); ++#ifndef _sbutils_h_ ++#define _sbutils_h_ + -+ /* step 8, fake soft reset */ -+ MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | 4); ++/* ++ * Datastructure to export all chip specific common variables ++ * public (read-only) portion of sbutils handle returned by ++ * sb_attach()/sb_kattach() ++*/ + -+ end_fill: -+ /* step 9 set watchdog timer */ -+ sb_watchdog(sbh, 20); -+ (void) R_REG(&cc->chipid); -+ -+ /* step 11 */ -+ __asm__ __volatile__ ( -+ ".set\tmips3\n\t" -+ "sync\n\t" -+ "wait\n\t" -+ ".set\tmips0" -+ ); -+ while (1); -+ } ++struct sb_pub { + -+done: -+ /* switch back to previous core */ -+ sb_setcoreidx(sbh, idx); ++ uint bustype; /* SB_BUS, PCI_BUS */ ++ uint buscoretype; /* SB_PCI, SB_PCMCIA, SB_PCIE */ ++ uint buscorerev; /* buscore rev */ ++ uint buscoreidx; /* buscore index */ ++ int ccrev; /* chip common core rev */ ++ uint boardtype; /* board type */ ++ uint boardvendor; /* board vendor */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint chippkg; /* chip package option */ ++ uint sonicsrev; /* sonics backplane rev */ ++}; + -+ return ret; -+} ++typedef const struct sb_pub sb_t; + +/* -+ * This also must be run from the cache on 47xx -+ * so there are no mips core BIU ops in progress -+ * when the PFC is enabled. ++ * Many of the routines below take an 'sbh' handle as their first arg. ++ * Allocate this by calling sb_attach(). Free it by calling sb_detach(). ++ * At any one time, the sbh is logically focused on one particular sb core ++ * (the "current core"). ++ * Use sb_setcore() or sb_setcoreidx() to change the association to another core. + */ + -+static void -+BCMINITFN(_enable_pfc)(uint32 mode) -+{ -+ /* write range */ -+ *(volatile uint32 *)PFC_CR1 = 0xffff0000; -+ -+ /* enable */ -+ *(volatile uint32 *)PFC_CR0 = mode; -+} -+ -+void -+BCMINITFN(enable_pfc)(uint32 mode) -+{ -+ ulong start, end; -+ int i; -+ -+ /* If auto then choose the correct mode for this -+ platform, currently we only ever select one mode */ -+ if (mode == PFC_AUTO) -+ mode = PFC_INST; -+ -+ /* enable prefetch cache if available */ -+ if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) { -+ start = (ulong) &BCMINIT(_enable_pfc); -+ end = (ulong) &BCMINIT(enable_pfc); ++#define SB_OSH NULL /* Use for sb_kattach when no osh is available */ ++/* exported externs */ ++extern sb_t *sb_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, ++ void *sdh, char **vars, uint *varsz); ++extern sb_t *sb_kattach(void); ++extern void sb_detach(sb_t *sbh); ++extern uint sb_chip(sb_t *sbh); ++extern uint sb_chiprev(sb_t *sbh); ++extern uint sb_chipcrev(sb_t *sbh); ++extern uint sb_chippkg(sb_t *sbh); ++extern uint sb_pcirev(sb_t *sbh); ++extern bool sb_war16165(sb_t *sbh); ++extern uint sb_pcmciarev(sb_t *sbh); ++extern uint sb_boardvendor(sb_t *sbh); ++extern uint sb_boardtype(sb_t *sbh); ++extern uint sb_bus(sb_t *sbh); ++extern uint sb_buscoretype(sb_t *sbh); ++extern uint sb_buscorerev(sb_t *sbh); ++extern uint sb_corelist(sb_t *sbh, uint coreid[]); ++extern uint sb_coreid(sb_t *sbh); ++extern uint sb_coreidx(sb_t *sbh); ++extern uint sb_coreunit(sb_t *sbh); ++extern uint sb_corevendor(sb_t *sbh); ++extern uint sb_corerev(sb_t *sbh); ++extern void *sb_osh(sb_t *sbh); ++extern void sb_setosh(sb_t *sbh, osl_t *osh); ++extern void *sb_coreregs(sb_t *sbh); ++extern uint32 sb_coreflags(sb_t *sbh, uint32 mask, uint32 val); ++extern uint32 sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val); ++extern bool sb_iscoreup(sb_t *sbh); ++extern void *sb_setcoreidx(sb_t *sbh, uint coreidx); ++extern void *sb_setcore(sb_t *sbh, uint coreid, uint coreunit); ++extern int sb_corebist(sb_t *sbh); ++extern void sb_commit(sb_t *sbh); ++extern uint32 sb_base(uint32 admatch); ++extern uint32 sb_size(uint32 admatch); ++extern void sb_core_reset(sb_t *sbh, uint32 bits, uint32 resetbits); ++extern void sb_core_tofixup(sb_t *sbh); ++extern void sb_core_disable(sb_t *sbh, uint32 bits); ++extern uint32 sb_clock_rate(uint32 pll_type, uint32 n, uint32 m); ++extern uint32 sb_clock(sb_t *sbh); ++extern void sb_pci_setup(sb_t *sbh, uint coremask); ++extern void sb_pcmcia_init(sb_t *sbh); ++extern void sb_watchdog(sb_t *sbh, uint ticks); ++extern void *sb_gpiosetcore(sb_t *sbh); ++extern uint32 sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); ++extern uint32 sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); ++extern uint32 sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); ++extern uint32 sb_gpioin(sb_t *sbh); ++extern uint32 sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); ++extern uint32 sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority); ++extern uint32 sb_gpioled(sb_t *sbh, uint32 mask, uint32 val); ++extern uint32 sb_gpioreserve(sb_t *sbh, uint32 gpio_num, uint8 priority); ++extern uint32 sb_gpiorelease(sb_t *sbh, uint32 gpio_num, uint8 priority); + -+ /* Preload handler into the cache one line at a time */ -+ for (i = 0; i < (end - start); i += 4) -+ cache_op(start + i, Fill_I); ++extern void sb_clkctl_init(sb_t *sbh); ++extern uint16 sb_clkctl_fast_pwrup_delay(sb_t *sbh); ++extern bool sb_clkctl_clk(sb_t *sbh, uint mode); ++extern int sb_clkctl_xtal(sb_t *sbh, uint what, bool on); ++extern void sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, void *intrsrestore_fn, ++ void *intrsenabled_fn, void *intr_arg); ++extern uint32 sb_set_initiator_to(sb_t *sbh, uint32 to); ++extern int sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, ++ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, ++ uint8 *pciheader); ++extern uint sb_pcie_readreg(void *sbh, void* arg1, uint offset); ++extern uint sb_pcie_writereg(sb_t *sbh, void *arg1, uint offset, uint val); ++extern uint32 sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 val); ++extern bool sb_backplane64(sb_t *sbh); ++extern void sb_btcgpiowar(sb_t *sbh); + -+ BCMINIT(_enable_pfc)(mode); -+ } -+} + -+/* returns the ncdl value to be programmed into sdram_ncdl for calibration */ -+uint32 -+BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh) -+{ -+ sbmemcregs_t *memc; -+ uint32 ret = 0; -+ uint32 config, rd, wr, misc, dqsg, cd, sm, sd; -+ uint idx, rev; + -+ idx = sb_coreidx(sbh); + -+ memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0); -+ if (memc == 0) -+ goto out; ++extern bool sb_deviceremoved(sb_t *sbh); ++extern uint32 sb_socram_size(sb_t *sbh); + -+ rev = sb_corerev(sbh); ++/* ++* Build device path. Path size must be >= SB_DEVPATH_BUFSZ. ++* The returned path is NULL terminated and has trailing '/'. ++* Return 0 on success, nonzero otherwise. ++*/ ++extern int sb_devpath(sb_t *sbh, char *path, int size); + -+ config = R_REG(&memc->config); -+ wr = R_REG(&memc->wrncdlcor); -+ rd = R_REG(&memc->rdncdlcor); -+ misc = R_REG(&memc->miscdlyctl); -+ dqsg = R_REG(&memc->dqsgatencdl); ++/* clkctl xtal what flags */ ++#define XTAL 0x1 /* primary crystal oscillator (2050) */ ++#define PLL 0x2 /* main chip pll */ + -+ rd &= MEMC_RDNCDLCOR_RD_MASK; -+ wr &= MEMC_WRNCDLCOR_WR_MASK; -+ dqsg &= MEMC_DQSGATENCDL_G_MASK; ++/* clkctl clk mode */ ++#define CLK_FAST 0 /* force fast (pll) clock */ ++#define CLK_DYNAMIC 2 /* enable dynamic clock control */ + -+ if (config & MEMC_CONFIG_DDR) { -+ ret = (wr << 16) | (rd << 8) | dqsg; -+ } else { -+ if (rev > 0) -+ cd = rd; -+ else -+ cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD); -+ sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT; -+ sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT; -+ ret = (sm << 16) | (sd << 8) | cd; -+ } + -+out: -+ /* switch back to previous core */ -+ sb_setcoreidx(sbh, idx); ++/* GPIO usage priorities */ ++#define GPIO_DRV_PRIORITY 0 /* Driver */ ++#define GPIO_APP_PRIORITY 1 /* Application */ + -+ return ret; -+} ++/* device path */ ++#define SB_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ + -diff -Naur linux.old/arch/mips/bcm947xx/sbpci.c linux.dev/arch/mips/bcm947xx/sbpci.c ---- linux.old/arch/mips/bcm947xx/sbpci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/sbpci.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,588 @@ ++#endif /* _sbutils_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/sflash.h linux.dev/arch/mips/bcm947xx/include/sflash.h +--- linux.old/arch/mips/bcm947xx/include/sflash.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/sflash.h 2006-04-27 22:13:51.000000000 +0200 +@@ -0,0 +1,36 @@ +/* -+ * Low-Level PCI and SB support for BCM47xx ++ * Broadcom SiliconBackplane chipcommon serial flash interface + * -+ * Copyright 2005, Broadcom Corporation ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -8420,9061 +8182,6930 @@ diff -Naur linux.old/arch/mips/bcm947xx/sbpci.c linux.dev/arch/mips/bcm947xx/sbp + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * $Id$ ++ * $Id: sflash.h,v 1.1.1.8 2006/02/27 03:43:16 honor Exp $ + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#ifndef _sflash_h_ ++#define _sflash_h_ + -+/* Can free sbpci_init() memory after boot */ -+#ifndef linux -+#define __init -+#endif ++#include ++#include + -+/* Emulated configuration space */ -+static pci_config_regs sb_config_regs[SB_MAXCORES]; ++struct sflash { ++ uint blocksize; /* Block size */ ++ uint numblocks; /* Number of blocks */ ++ uint32 type; /* Type */ ++ uint size; /* Total size in bytes */ ++}; + -+/* Banned cores */ -+static uint16 pci_ban[32] = { 0 }; -+static uint pci_banned = 0; ++/* Utility functions */ ++extern int sflash_poll(chipcregs_t *cc, uint offset); ++extern int sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf); ++extern int sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf); ++extern int sflash_erase(chipcregs_t *cc, uint offset); ++extern int sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf); ++extern struct sflash * sflash_init(chipcregs_t *cc); + -+/* CardBus mode */ -+static bool cardbus = FALSE; ++#endif /* _sflash_h_ */ +diff -urN linux.old/arch/mips/bcm947xx/include/trxhdr.h linux.dev/arch/mips/bcm947xx/include/trxhdr.h +--- linux.old/arch/mips/bcm947xx/include/trxhdr.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/trxhdr.h 2006-04-27 19:24:19.000000000 +0200 +@@ -0,0 +1,33 @@ ++/* ++ * TRX image file header format. ++ * ++ * Copyright 2005, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id$ ++ */ + -+/* Disable PCI host core */ -+static bool pci_disabled = FALSE; ++#include ++ ++#define TRX_MAGIC 0x30524448 /* "HDR0" */ ++#define TRX_VERSION 1 ++#define TRX_MAX_LEN 0x3A0000 ++#define TRX_NO_HEADER 1 /* Do not write TRX header */ ++#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ ++#define TRX_MAX_OFFSET 3 ++ ++struct trx_header { ++ uint32 magic; /* "HDR0" */ ++ uint32 len; /* Length of file including header */ ++ uint32 crc32; /* 32-bit CRC from flag_version to end of file */ ++ uint32 flag_version; /* 0:15 flags, 16:31 version */ ++ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ ++}; + ++/* Compatibility */ ++typedef struct trx_header TRXHDR, *PTRXHDR; +diff -urN linux.old/arch/mips/bcm947xx/include/typedefs.h linux.dev/arch/mips/bcm947xx/include/typedefs.h +--- linux.old/arch/mips/bcm947xx/include/typedefs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/include/typedefs.h 2006-04-27 23:47:30.000000000 +0200 +@@ -0,0 +1,361 @@ +/* -+ * Functions for accessing external PCI configuration space ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * $Id: typedefs.h,v 1.1.1.12 2006/04/08 06:13:40 honor Exp $ + */ + -+/* Assume one-hot slot wiring */ -+#define PCI_SLOT_MAX 16 ++#ifndef _TYPEDEFS_H_ ++#define _TYPEDEFS_H_ + -+static uint32 -+config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off) -+{ -+ uint coreidx; -+ sbpciregs_t *regs; -+ uint32 addr = 0; + -+ /* CardBusMode supports only one device */ -+ if (cardbus && dev > 1) -+ return 0; ++/* Define 'SITE_TYPEDEFS' in the compile to include a site specific ++ * typedef file "site_typedefs.h". ++ * ++ * If 'SITE_TYPEDEFS' is not defined, then the "Inferred Typedefs" ++ * section of this file makes inferences about the compile environment ++ * based on defined symbols and possibly compiler pragmas. ++ * ++ * Following these two sections is the "Default Typedefs" ++ * section. This section is only prcessed if 'USE_TYPEDEF_DEFAULTS' is ++ * defined. This section has a default set of typedefs and a few ++ * proprocessor symbols (TRUE, FALSE, NULL, ...). ++ */ + -+ coreidx = sb_coreidx(sbh); -+ regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0); ++#ifdef SITE_TYPEDEFS + -+ /* Type 0 transaction */ -+ if (bus == 1) { -+ /* Skip unwired slots */ -+ if (dev < PCI_SLOT_MAX) { -+ /* Slide the PCI window to the appropriate slot */ -+ W_REG(®s->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK)); -+ addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) | -+ (func << 8) | (off & ~3); -+ } -+ } ++/* ++ * Site Specific Typedefs ++ * ++ */ + -+ /* Type 1 transaction */ -+ else { -+ W_REG(®s->sbtopci1, SBTOPCI_CFG1); -+ addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3); -+ } ++#include "site_typedefs.h" + -+ sb_setcoreidx(sbh, coreidx); ++#else + -+ return addr; -+} ++/* ++ * Inferred Typedefs ++ * ++ */ + -+static int -+extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) -+{ -+ uint32 addr, *reg = NULL, val; -+ int ret = 0; ++/* Infer the compile environment based on preprocessor symbols and pramas. ++ * Override type definitions as needed, and include configuration dependent ++ * header files to define types. ++ */ + -+ if (pci_disabled || -+ !(addr = config_cmd(sbh, bus, dev, func, off)) || -+ !(reg = (uint32 *) REG_MAP(addr, len)) || -+ BUSPROBE(val, reg)) -+ val = 0xffffffff; ++#ifdef __cplusplus + -+ val >>= 8 * (off & 3); -+ if (len == 4) -+ *((uint32 *) buf) = val; -+ else if (len == 2) -+ *((uint16 *) buf) = (uint16) val; -+ else if (len == 1) -+ *((uint8 *) buf) = (uint8) val; -+ else -+ ret = -1; ++#define TYPEDEF_BOOL ++#ifndef FALSE ++#define FALSE false ++#endif ++#ifndef TRUE ++#define TRUE true ++#endif + -+ if (reg) -+ REG_UNMAP(reg); ++#else /* ! __cplusplus */ + -+ return ret; -+} ++#if defined(_WIN32) + -+static int -+extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) -+{ -+ uint32 addr, *reg = NULL, val; -+ int ret = 0; ++#define TYPEDEF_BOOL ++typedef unsigned char bool; /* consistent w/BOOL */ + -+ if (pci_disabled || -+ !(addr = config_cmd(sbh, bus, dev, func, off)) || -+ !(reg = (uint32 *) REG_MAP(addr, len)) || -+ BUSPROBE(val, reg)) -+ goto done; ++#endif /* _WIN32 */ + -+ if (len == 4) -+ val = *((uint32 *) buf); -+ else if (len == 2) { -+ val &= ~(0xffff << (8 * (off & 3))); -+ val |= *((uint16 *) buf) << (8 * (off & 3)); -+ } else if (len == 1) { -+ val &= ~(0xff << (8 * (off & 3))); -+ val |= *((uint8 *) buf) << (8 * (off & 3)); -+ } else -+ ret = -1; ++#endif /* ! __cplusplus */ + -+ W_REG(reg, val); ++/* use the Windows ULONG_PTR type when compiling for 64 bit */ ++#if defined(_WIN64) ++#include ++#define TYPEDEF_UINTPTR ++typedef ULONG_PTR uintptr; ++#endif + -+ done: -+ if (reg) -+ REG_UNMAP(reg); + -+ return ret; -+} ++#if defined(_MINOSL_) ++#define _NEED_SIZE_T_ ++#endif + -+/* -+ * Functions for accessing translated SB configuration space -+ */ ++#if defined(_NEED_SIZE_T_) ++typedef long unsigned int size_t; ++#endif + -+static int -+sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) -+{ -+ pci_config_regs *cfg; ++#ifdef __DJGPP__ ++typedef long unsigned int size_t; ++#endif /* __DJGPP__ */ + -+ if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs)) -+ return -1; -+ cfg = &sb_config_regs[dev]; ++#ifdef _MSC_VER /* Microsoft C */ ++#define TYPEDEF_INT64 ++#define TYPEDEF_UINT64 ++typedef signed __int64 int64; ++typedef unsigned __int64 uint64; ++#endif + -+ ASSERT(ISALIGNED(off, len)); -+ ASSERT(ISALIGNED((uintptr)buf, len)); ++#if defined(MACOSX) ++#define TYPEDEF_BOOL ++#endif + -+ if (len == 4) -+ *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off))); -+ else if (len == 2) -+ *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off))); -+ else if (len == 1) -+ *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off)); -+ else -+ return -1; ++#if defined(__NetBSD__) ++#define TYPEDEF_ULONG ++#endif + -+ return 0; -+} + -+static int -+sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) -+{ -+ uint coreidx, n; -+ void *regs; -+ sbconfig_t *sb; -+ pci_config_regs *cfg; ++#if defined(linux) ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#endif + -+ if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs)) -+ return -1; -+ cfg = &sb_config_regs[dev]; ++#if !defined(linux) && !defined(_WIN32) && !defined(_CFE_) && \ ++ !defined(_HNDRTE_) && !defined(_MINOSL_) && !defined(__DJGPP__) ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#endif + -+ ASSERT(ISALIGNED(off, len)); -+ ASSERT(ISALIGNED((uintptr)buf, len)); + -+ /* Emulate BAR sizing */ -+ if (off >= OFFSETOF(pci_config_regs, base[0]) && off <= OFFSETOF(pci_config_regs, base[3]) && -+ len == 4 && *((uint32 *) buf) == ~0) { -+ coreidx = sb_coreidx(sbh); -+ if ((regs = sb_setcoreidx(sbh, dev))) { -+ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); -+ /* Highest numbered address match register */ -+ n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT; -+ if (off == OFFSETOF(pci_config_regs, base[0])) -+ cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1); -+ else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1) -+ cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1); -+ else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2) -+ cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1); -+ else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3) -+ cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1); -+ } -+ sb_setcoreidx(sbh, coreidx); -+ return 0; -+ } ++/* Do not support the (u)int64 types with strict ansi for GNU C */ ++#if defined(__GNUC__) && defined(__STRICT_ANSI__) ++#define TYPEDEF_INT64 ++#define TYPEDEF_UINT64 ++#endif + -+ if (len == 4) -+ *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf)); -+ else if (len == 2) -+ *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf)); -+ else if (len == 1) -+ *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf); -+ else -+ return -1; ++/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode ++ * for singned or unsigned ++ */ ++#if defined(__ICL) + -+ return 0; -+} ++#define TYPEDEF_INT64 + -+int -+sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) -+{ -+ if (bus == 0) -+ return sb_read_config(sbh, bus, dev, func, off, buf, len); -+ else -+ return extpci_read_config(sbh, bus, dev, func, off, buf, len); -+} ++#if defined(__STDC__) ++#define TYPEDEF_UINT64 ++#endif + -+int -+sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) -+{ -+ if (bus == 0) -+ return sb_write_config(sbh, bus, dev, func, off, buf, len); -+ else -+ return extpci_write_config(sbh, bus, dev, func, off, buf, len); -+} ++#endif /* __ICL */ + -+void -+sbpci_ban(uint16 core) -+{ -+ if (pci_banned < ARRAYSIZE(pci_ban)) -+ pci_ban[pci_banned++] = core; -+} ++#if !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && \ ++ !defined(__DJGPP__) + -+static int -+sbpci_init_pci(sb_t *sbh) -+{ -+ uint chip, chiprev, chippkg, host; -+ uint32 boardflags; -+ sbpciregs_t *pci; -+ sbconfig_t *sb; -+ uint32 val; ++/* pick up ushort & uint from standard types.h */ ++#if defined(linux) && defined(__KERNEL__) + -+ chip = sb_chip(sbh); -+ chiprev = sb_chiprev(sbh); -+ chippkg = sb_chippkg(sbh); ++#include /* sys/types.h and linux/types.h are oil and water */ + -+ if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) { -+ printf("PCI: no core\n"); -+ pci_disabled = TRUE; -+ return -1; -+ } -+ sb_core_reset(sbh, 0); ++#else + -+ boardflags = (uint32) getintvar(NULL, "boardflags"); ++#include + -+ if ((chip == BCM4310_DEVICE_ID) && (chiprev == 0)) -+ pci_disabled = TRUE; ++#endif + -+ /* -+ * The 200-pin BCM4712 package does not bond out PCI. Even when -+ * PCI is bonded out, some boards may leave the pins -+ * floating. -+ */ -+ if (((chip == BCM4712_DEVICE_ID) && -+ ((chippkg == BCM4712SMALL_PKG_ID) || -+ (chippkg == BCM4712MID_PKG_ID))) || -+ (boardflags & BFL_NOPCI)) -+ pci_disabled = TRUE; ++#endif /* !_WIN32 && !PMON && !_CFE_ && !_HNDRTE_ && !_MINOSL_ && !__DJGPP__ */ + -+ /* -+ * If the PCI core should not be touched (disabled, not bonded -+ * out, or pins floating), do not even attempt to access core -+ * registers. Otherwise, try to determine if it is in host -+ * mode. -+ */ -+ if (pci_disabled) -+ host = 0; -+ else -+ host = !BUSPROBE(val, &pci->control); ++#if defined(MACOSX) + -+ if (!host) { -+ /* Disable PCI interrupts in client mode */ -+ sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF); -+ W_REG(&sb->sbintvec, 0); ++#ifdef __BIG_ENDIAN__ ++#define IL_BIGENDIAN ++#else ++#ifdef IL_BIGENDIAN ++#error "IL_BIGENDIAN was defined for a little-endian compile" ++#endif ++#endif /* __BIG_ENDIAN__ */ + -+ /* Disable the PCI bridge in client mode */ -+ sbpci_ban(SB_PCI); -+ printf("PCI: Disabled\n"); -+ } else { -+ /* Reset the external PCI bus and enable the clock */ -+ W_REG(&pci->control, 0x5); /* enable the tristate drivers */ -+ W_REG(&pci->control, 0xd); /* enable the PCI clock */ -+ OSL_DELAY(150); /* delay > 100 us */ -+ W_REG(&pci->control, 0xf); /* deassert PCI reset */ -+ W_REG(&pci->arbcontrol, PCI_INT_ARB); /* use internal arbiter */ -+ OSL_DELAY(1); /* delay 1 us */ ++#if !defined(__cplusplus) + -+ /* Enable CardBusMode */ -+ cardbus = nvram_match("cardbus", "1"); -+ if (cardbus) { -+ printf("PCI: Enabling CardBus\n"); -+ /* GPIO 1 resets the CardBus device on bcm94710ap */ -+ sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY); -+ sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY); -+ W_REG(&pci->sprom[0], R_REG(&pci->sprom[0]) | 0x400); -+ } ++#if defined(__i386__) ++typedef unsigned char bool; ++#else ++typedef unsigned int bool; ++#endif ++#define TYPE_BOOL 1 ++enum { ++ false = 0, ++ true = 1 ++}; + -+ /* 64 MB I/O access window */ -+ W_REG(&pci->sbtopci0, SBTOPCI_IO); -+ /* 64 MB configuration access window */ -+ W_REG(&pci->sbtopci1, SBTOPCI_CFG0); -+ /* 1 GB memory access window */ -+ W_REG(&pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA); ++#if defined(KERNEL) ++#include ++#endif /* KERNEL */ + -+ /* Enable PCI bridge BAR0 prefetch and burst */ -+ val = 6; -+ sbpci_write_config(sbh, 1, 0, 0, PCI_CFG_CMD, &val, sizeof(val)); ++#endif /* __cplusplus */ + -+ /* Enable PCI interrupts */ -+ W_REG(&pci->intmask, PCI_INTA); -+ } -+ -+ return 0; -+} ++#endif /* MACOSX */ + -+static int -+sbpci_init_cores(sb_t *sbh) -+{ -+ uint chip, chiprev, chippkg, coreidx, i; -+ sbconfig_t *sb; -+ pci_config_regs *cfg; -+ void *regs; -+ char varname[8]; -+ uint wlidx = 0; -+ uint16 vendor, core; -+ uint8 class, subclass, progif; -+ uint32 val; -+ uint32 sbips_int_mask[] = { 0, SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, SBIPS_INT4_MASK }; -+ uint32 sbips_int_shift[] = { 0, 0, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, SBIPS_INT4_SHIFT }; + -+ chip = sb_chip(sbh); -+ chiprev = sb_chiprev(sbh); -+ chippkg = sb_chippkg(sbh); -+ coreidx = sb_coreidx(sbh); ++/* use the default typedefs in the next section of this file */ ++#define USE_TYPEDEF_DEFAULTS + -+ /* Scan the SB bus */ -+ bzero(sb_config_regs, sizeof(sb_config_regs)); -+ for (cfg = sb_config_regs; cfg < &sb_config_regs[SB_MAXCORES]; cfg++) { -+ cfg->vendor = 0xffff; -+ if (!(regs = sb_setcoreidx(sbh, cfg - sb_config_regs))) -+ continue; -+ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); ++#endif /* SITE_TYPEDEFS */ + -+ /* Read ID register and parse vendor and core */ -+ val = R_REG(&sb->sbidhigh); -+ vendor = (val & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT; -+ core = (val & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT; -+ progif = 0; + -+ /* Check if this core is banned */ -+ for (i = 0; i < pci_banned; i++) -+ if (core == pci_ban[i]) -+ break; -+ if (i < pci_banned) -+ continue; ++/* ++ * Default Typedefs ++ * ++ */ + -+ /* Known vendor translations */ -+ switch (vendor) { -+ case SB_VEND_BCM: -+ vendor = VENDOR_BROADCOM; -+ break; -+ } ++#ifdef USE_TYPEDEF_DEFAULTS ++#undef USE_TYPEDEF_DEFAULTS + -+ /* Determine class based on known core codes */ -+ switch (core) { -+ case SB_ILINE20: -+ class = PCI_CLASS_NET; -+ subclass = PCI_NET_ETHER; -+ core = BCM47XX_ILINE_ID; -+ break; -+ case SB_ILINE100: -+ class = PCI_CLASS_NET; -+ subclass = PCI_NET_ETHER; -+ core = BCM4610_ILINE_ID; -+ break; -+ case SB_ENET: -+ class = PCI_CLASS_NET; -+ subclass = PCI_NET_ETHER; -+ core = BCM47XX_ENET_ID; -+ break; -+ case SB_SDRAM: -+ case SB_MEMC: -+ class = PCI_CLASS_MEMORY; -+ subclass = PCI_MEMORY_RAM; -+ break; -+ case SB_PCI: -+ class = PCI_CLASS_BRIDGE; -+ subclass = PCI_BRIDGE_PCI; -+ break; -+ case SB_MIPS: -+ case SB_MIPS33: -+ class = PCI_CLASS_CPU; -+ subclass = PCI_CPU_MIPS; -+ break; -+ case SB_CODEC: -+ class = PCI_CLASS_COMM; -+ subclass = PCI_COMM_MODEM; -+ core = BCM47XX_V90_ID; -+ break; -+ case SB_USB: -+ class = PCI_CLASS_SERIAL; -+ subclass = PCI_SERIAL_USB; -+ progif = 0x10; /* OHCI */ -+ core = BCM47XX_USB_ID; -+ break; -+ case SB_USB11H: -+ class = PCI_CLASS_SERIAL; -+ subclass = PCI_SERIAL_USB; -+ progif = 0x10; /* OHCI */ -+ core = BCM47XX_USBH_ID; -+ break; -+ case SB_USB11D: -+ class = PCI_CLASS_SERIAL; -+ subclass = PCI_SERIAL_USB; -+ core = BCM47XX_USBD_ID; -+ break; -+ case SB_IPSEC: -+ class = PCI_CLASS_CRYPT; -+ subclass = PCI_CRYPT_NETWORK; -+ core = BCM47XX_IPSEC_ID; -+ break; -+ case SB_ROBO: -+ class = PCI_CLASS_NET; -+ subclass = PCI_NET_OTHER; -+ core = BCM47XX_ROBO_ID; -+ break; -+ case SB_EXTIF: -+ case SB_CC: -+ class = PCI_CLASS_MEMORY; -+ subclass = PCI_MEMORY_FLASH; -+ break; -+ case SB_D11: -+ class = PCI_CLASS_NET; -+ subclass = PCI_NET_OTHER; -+ /* Let an nvram variable override this */ -+ sprintf(varname, "wl%did", wlidx); -+ wlidx++; -+ if ((core = getintvar(NULL, varname)) == 0) { -+ if (chip == BCM4712_DEVICE_ID) { -+ if (chippkg == BCM4712SMALL_PKG_ID) -+ core = BCM4306_D11G_ID; -+ else -+ core = BCM4306_D11DUAL_ID; -+ } else { -+ /* 4310 */ -+ core = BCM4310_D11B_ID; -+ } -+ } -+ break; ++#ifndef TYPEDEF_BOOL ++typedef /* @abstract@ */ unsigned char bool; ++#endif + -+ default: -+ class = subclass = progif = 0xff; -+ break; -+ } ++/* define uchar, ushort, uint, ulong */ + -+ /* Supported translations */ -+ cfg->vendor = htol16(vendor); -+ cfg->device = htol16(core); -+ cfg->rev_id = chiprev; -+ cfg->prog_if = progif; -+ cfg->sub_class = subclass; -+ cfg->base_class = class; -+ cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0))); -+ cfg->base[1] = htol32(sb_base(R_REG(&sb->sbadmatch1))); -+ cfg->base[2] = htol32(sb_base(R_REG(&sb->sbadmatch2))); -+ cfg->base[3] = htol32(sb_base(R_REG(&sb->sbadmatch3))); -+ cfg->base[4] = 0; -+ cfg->base[5] = 0; -+ if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI) -+ cfg->header_type = PCI_HEADER_BRIDGE; -+ else -+ cfg->header_type = PCI_HEADER_NORMAL; -+ /* Save core interrupt flag */ -+ cfg->int_pin = R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK; -+ /* Default to MIPS shared interrupt 0 */ -+ cfg->int_line = 0; -+ /* MIPS sbipsflag maps core interrupt flags to interrupts 1 through 4 */ -+ if ((regs = sb_setcore(sbh, SB_MIPS, 0)) || -+ (regs = sb_setcore(sbh, SB_MIPS33, 0))) { -+ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); -+ val = R_REG(&sb->sbipsflag); -+ for (cfg->int_line = 1; cfg->int_line <= 4; cfg->int_line++) { -+ if (((val & sbips_int_mask[cfg->int_line]) >> sbips_int_shift[cfg->int_line]) == cfg->int_pin) -+ break; -+ } -+ if (cfg->int_line > 4) -+ cfg->int_line = 0; -+ } -+ /* Emulated core */ -+ *((uint32 *) &cfg->sprom_control) = 0xffffffff; -+ } ++#ifndef TYPEDEF_UCHAR ++typedef unsigned char uchar; ++#endif + -+ sb_setcoreidx(sbh, coreidx); -+ return 0; -+} ++#ifndef TYPEDEF_USHORT ++typedef unsigned short ushort; ++#endif + -+int __init -+sbpci_init(sb_t *sbh) -+{ -+ sbpci_init_pci(sbh); -+ sbpci_init_cores(sbh); -+ return 0; -+} ++#ifndef TYPEDEF_UINT ++typedef unsigned int uint; ++#endif + -+void -+sbpci_check(sb_t *sbh) -+{ -+ uint coreidx; -+ sbpciregs_t *pci; -+ uint32 sbtopci1; -+ uint32 buf[64], *ptr, i; -+ ulong pa; -+ volatile uint j; ++#ifndef TYPEDEF_ULONG ++typedef unsigned long ulong; ++#endif + -+ coreidx = sb_coreidx(sbh); -+ pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0); -+ -+ /* Clear the test array */ -+ pa = (ulong) DMA_MAP(NULL, buf, sizeof(buf), DMA_RX, NULL); -+ ptr = (uint32 *) OSL_UNCACHED(&buf[0]); -+ memset(ptr, 0, sizeof(buf)); -+ -+ /* Point PCI window 1 to memory */ -+ sbtopci1 = R_REG(&pci->sbtopci1); -+ W_REG(&pci->sbtopci1, SBTOPCI_MEM | (pa & SBTOPCI1_MASK)); -+ -+ /* Fill the test array via PCI window 1 */ -+ ptr = (uint32 *) REG_MAP(SB_PCI_CFG + (pa & ~SBTOPCI1_MASK), sizeof(buf)); -+ for (i = 0; i < ARRAYSIZE(buf); i++) { -+ for (j = 0; j < 2; j++); -+ W_REG(&ptr[i], i); -+ } -+ REG_UNMAP(ptr); ++/* define [u]int8/16/32/64, uintptr */ + -+ /* Restore PCI window 1 */ -+ W_REG(&pci->sbtopci1, sbtopci1); ++#ifndef TYPEDEF_UINT8 ++typedef unsigned char uint8; ++#endif + -+ /* Check the test array */ -+ DMA_UNMAP(NULL, pa, sizeof(buf), DMA_RX, NULL); -+ ptr = (uint32 *) OSL_UNCACHED(&buf[0]); -+ for (i = 0; i < ARRAYSIZE(buf); i++) { -+ if (ptr[i] != i) -+ break; -+ } ++#ifndef TYPEDEF_UINT16 ++typedef unsigned short uint16; ++#endif + -+ /* Change the clock if the test fails */ -+ if (i < ARRAYSIZE(buf)) { -+ uint32 req, cur; ++#ifndef TYPEDEF_UINT32 ++typedef unsigned int uint32; ++#endif + -+ cur = sb_clock(sbh); -+ printf("PCI: Test failed at %d MHz\n", (cur + 500000) / 1000000); -+ for (req = 104000000; req < 176000000; req += 4000000) { -+ printf("PCI: Resetting to %d MHz\n", (req + 500000) / 1000000); -+ /* This will only reset if the clocks are valid and have changed */ -+ sb_mips_setclock(sbh, req, 0, 0); -+ } -+ /* Should not reach here */ -+ ASSERT(0); -+ } ++#ifndef TYPEDEF_UINT64 ++typedef unsigned long long uint64; ++#endif + -+ sb_setcoreidx(sbh, coreidx); -+} ++#ifndef TYPEDEF_UINTPTR ++typedef unsigned int uintptr; ++#endif + -diff -Naur linux.old/arch/mips/bcm947xx/setup.c linux.dev/arch/mips/bcm947xx/setup.c ---- linux.old/arch/mips/bcm947xx/setup.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/setup.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,234 @@ -+/* -+ * Generic setup routines for Broadcom MIPS boards -+ * -+ * Copyright (C) 2005 Felix Fietkau -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS SOFTWARE IS PROVIDED ``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. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ */ ++#ifndef TYPEDEF_INT8 ++typedef signed char int8; ++#endif + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#ifndef TYPEDEF_INT16 ++typedef signed short int16; ++#endif + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Global SB handle */ -+sb_t *bcm947xx_sbh = NULL; -+spinlock_t bcm947xx_sbh_lock = SPIN_LOCK_UNLOCKED; -+ -+/* Convenience */ -+#define sbh bcm947xx_sbh -+#define sbh_lock bcm947xx_sbh_lock -+ -+extern void bcm947xx_time_init(void); -+extern void bcm947xx_timer_setup(struct irqaction *irq); -+ -+#ifdef CONFIG_REMOTE_DEBUG -+extern void set_debug_traps(void); -+extern void rs_kgdb_hook(struct serial_state *); -+extern void breakpoint(void); ++#ifndef TYPEDEF_INT32 ++typedef signed int int32; +#endif + -+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -+extern struct ide_ops std_ide_ops; ++#ifndef TYPEDEF_INT64 ++typedef signed long long int64; +#endif + -+/* Kernel command line */ -+char arcs_cmdline[CL_SIZE] __initdata = CONFIG_CMDLINE; -+ -+void -+bcm947xx_machine_restart(char *command) -+{ -+ printk("Please stand by while rebooting the system...\n"); -+ -+ /* Set the watchdog timer to reset immediately */ -+ __cli(); -+ sb_watchdog(sbh, 1); -+ while (1); -+} ++/* define float32/64, float_t */ + -+void -+bcm947xx_machine_halt(void) -+{ -+ printk("System halted\n"); ++#ifndef TYPEDEF_FLOAT32 ++typedef float float32; ++#endif + -+ /* Disable interrupts and watchdog and spin forever */ -+ __cli(); -+ sb_watchdog(sbh, 0); -+ while (1); -+} ++#ifndef TYPEDEF_FLOAT64 ++typedef double float64; ++#endif + -+#ifdef CONFIG_SERIAL ++/* ++ * abstracted floating point type allows for compile time selection of ++ * single or double precision arithmetic. Compiling with -DFLOAT32 ++ * selects single precision; the default is double precision. ++ */ + -+static int ser_line = 0; ++#ifndef TYPEDEF_FLOAT_T + -+typedef struct { -+ void *regs; -+ uint irq; -+ uint baud_base; -+ uint reg_shift; -+} serial_port; ++#if defined(FLOAT32) ++typedef float32 float_t; ++#else /* default to double precision floating point */ ++typedef float64 float_t; ++#endif + -+static serial_port ports[4]; -+static int num_ports = 0; ++#endif /* TYPEDEF_FLOAT_T */ + -+static void -+serial_add(void *regs, uint irq, uint baud_base, uint reg_shift) -+{ -+ ports[num_ports].regs = regs; -+ ports[num_ports].irq = irq; -+ ports[num_ports].baud_base = baud_base; -+ ports[num_ports].reg_shift = reg_shift; -+ num_ports++; -+} ++/* define macro values */ + -+static void -+do_serial_add(serial_port *port) -+{ -+ void *regs; -+ uint irq; -+ uint baud_base; -+ uint reg_shift; -+ struct serial_struct s; -+ -+ regs = port->regs; -+ irq = port->irq; -+ baud_base = port->baud_base; -+ reg_shift = port->reg_shift; ++#ifndef FALSE ++#define FALSE 0 ++#endif + -+ memset(&s, 0, sizeof(s)); ++#ifndef TRUE ++#define TRUE 1 /* TRUE */ ++#endif + -+ s.line = ser_line++; -+ s.iomem_base = regs; -+ s.irq = irq + 2; -+ s.baud_base = baud_base / 16; -+ s.flags = ASYNC_BOOT_AUTOCONF; -+ s.io_type = SERIAL_IO_MEM; -+ s.iomem_reg_shift = reg_shift; ++#ifndef NULL ++#define NULL 0 ++#endif + -+ if (early_serial_setup(&s) != 0) { -+ printk(KERN_ERR "Serial setup failed!\n"); -+ } -+} ++#ifndef OFF ++#define OFF 0 ++#endif + -+#endif /* CONFIG_SERIAL */ ++#ifndef ON ++#define ON 1 /* ON = 1 */ ++#endif + -+void __init -+brcm_setup(void) -+{ -+ char *s; -+ int i; -+ char *value; ++#define AUTO (-1) /* Auto = -1 */ + -+ /* Get global SB handle */ -+ sbh = sb_kattach(); ++/* define PTRSZ, INLINE */ + -+ /* Initialize clocks and interrupts */ -+ sb_mips_init(sbh); ++#ifndef PTRSZ ++#define PTRSZ sizeof(char*) ++#endif + -+ if (BCM330X(current_cpu_data.processor_id) && -+ (read_c0_diag() & BRCM_PFC_AVAIL)) { -+ /* -+ * Now that the sbh is inited set the proper PFC value -+ */ -+ printk("Setting the PFC to its default value\n"); -+ enable_pfc(PFC_AUTO); -+ } ++#ifndef INLINE + ++#ifdef _MSC_VER + -+#ifdef CONFIG_SERIAL -+ sb_serial_init(sbh, serial_add); ++#define INLINE __inline + -+ /* reverse serial ports if nvram variable starts with console=ttyS1 */ -+ /* Initialize UARTs */ -+ s = nvram_get("kernel_args"); -+ if (!s) s = ""; -+ if (!strncmp(s, "console=ttyS1", 13)) { -+ for (i = num_ports; i; i--) -+ do_serial_add(&ports[i - 1]); -+ } else { -+ for (i = 0; i < num_ports; i++) -+ do_serial_add(&ports[i]); -+ } -+#endif ++#elif __GNUC__ + -+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -+ ide_ops = &std_ide_ops; -+#endif ++#define INLINE __inline__ + -+ /* Override default command line arguments */ -+ value = nvram_get("kernel_cmdline"); -+ if (value && strlen(value) && strncmp(value, "empty", 5)) -+ strncpy(arcs_cmdline, value, sizeof(arcs_cmdline)); ++#else + ++#define INLINE + -+ /* Generic setup */ -+ _machine_restart = bcm947xx_machine_restart; -+ _machine_halt = bcm947xx_machine_halt; -+ _machine_power_off = bcm947xx_machine_halt; ++#endif /* _MSC_VER */ + -+ board_time_init = bcm947xx_time_init; -+ board_timer_setup = bcm947xx_timer_setup; -+} ++#endif /* INLINE */ + -+const char * -+get_system_type(void) -+{ -+ static char s[32]; ++#undef TYPEDEF_BOOL ++#undef TYPEDEF_UCHAR ++#undef TYPEDEF_USHORT ++#undef TYPEDEF_UINT ++#undef TYPEDEF_ULONG ++#undef TYPEDEF_UINT8 ++#undef TYPEDEF_UINT16 ++#undef TYPEDEF_UINT32 ++#undef TYPEDEF_UINT64 ++#undef TYPEDEF_UINTPTR ++#undef TYPEDEF_INT8 ++#undef TYPEDEF_INT16 ++#undef TYPEDEF_INT32 ++#undef TYPEDEF_INT64 ++#undef TYPEDEF_FLOAT32 ++#undef TYPEDEF_FLOAT64 ++#undef TYPEDEF_FLOAT_T + -+ if (bcm947xx_sbh) { -+ sprintf(s, "Broadcom BCM%X chip rev %d", sb_chip(bcm947xx_sbh), -+ sb_chiprev(bcm947xx_sbh)); -+ return s; -+ } -+ else -+ return "Broadcom BCM947XX"; -+} ++#endif /* USE_TYPEDEF_DEFAULTS */ + -+void __init -+bus_error_init(void) -+{ -+} ++/* ++ * Including the bcmdefs.h here, to make sure everyone including typedefs.h ++ * gets this automatically ++*/ ++#include "bcmdefs.h" + -+EXPORT_SYMBOL(bcm947xx_sbh); -diff -Naur linux.old/arch/mips/bcm947xx/sflash.c linux.dev/arch/mips/bcm947xx/sflash.c ---- linux.old/arch/mips/bcm947xx/sflash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/sflash.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,418 @@ ++#endif /* _TYPEDEFS_H_ */ +diff -urN linux.old/arch/mips/bcm947xx/nvram.c linux.dev/arch/mips/bcm947xx/nvram.c +--- linux.old/arch/mips/bcm947xx/nvram.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/nvram.c 2006-04-27 23:11:58.000000000 +0200 +@@ -0,0 +1,315 @@ +/* -+ * Broadcom SiliconBackplane chipcommon serial flash interface ++ * NVRAM variable manipulation (common) + * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * Copyright 2004, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * $Id$ + */ + -+#include +#include -+#include -+#include -+#include ++#include ++#include ++#include +#include -+#include -+#include -+ -+/* Private global state */ -+static struct sflash sflash; ++#include + -+/* Issue a serial flash command */ -+static INLINE void -+sflash_cmd(chipcregs_t *cc, uint opcode) -+{ -+ W_REG(&cc->flashcontrol, SFLASH_START | opcode); -+ while (R_REG(&cc->flashcontrol) & SFLASH_BUSY); -+} ++extern struct nvram_tuple * BCMINIT(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value); ++extern void BCMINIT(_nvram_free)(struct nvram_tuple *t); ++extern int BCMINIT(_nvram_read)(void *buf); + -+/* Initialize serial flash access */ -+struct sflash * -+sflash_init(chipcregs_t *cc) -+{ -+ uint32 id, id2; ++char * BCMINIT(_nvram_get)(const char *name); ++int BCMINIT(_nvram_set)(const char *name, const char *value); ++int BCMINIT(_nvram_unset)(const char *name); ++int BCMINIT(_nvram_getall)(char *buf, int count); ++int BCMINIT(_nvram_commit)(struct nvram_header *header); ++int BCMINIT(_nvram_init)(void); ++void BCMINIT(_nvram_exit)(void); + -+ bzero(&sflash, sizeof(sflash)); ++static struct nvram_tuple * BCMINITDATA(nvram_hash)[257]; ++static struct nvram_tuple * nvram_dead; + -+ sflash.type = R_REG(&cc->capabilities) & CAP_FLASH_MASK; ++/* Free all tuples. Should be locked. */ ++static void ++BCMINITFN(nvram_free)(void) ++{ ++ uint i; ++ struct nvram_tuple *t, *next; + -+ switch (sflash.type) { -+ case SFLASH_ST: -+ /* Probe for ST chips */ -+ sflash_cmd(cc, SFLASH_ST_DP); -+ sflash_cmd(cc, SFLASH_ST_RES); -+ id = R_REG(&cc->flashdata); -+ switch (id) { -+ case 0x11: -+ /* ST M25P20 2 Mbit Serial Flash */ -+ sflash.blocksize = 64 * 1024; -+ sflash.numblocks = 4; -+ break; -+ case 0x12: -+ /* ST M25P40 4 Mbit Serial Flash */ -+ sflash.blocksize = 64 * 1024; -+ sflash.numblocks = 8; -+ break; -+ case 0x13: -+ /* ST M25P80 8 Mbit Serial Flash */ -+ sflash.blocksize = 64 * 1024; -+ sflash.numblocks = 16; -+ break; -+ case 0x14: -+ /* ST M25P16 16 Mbit Serial Flash */ -+ sflash.blocksize = 64 * 1024; -+ sflash.numblocks = 32; -+ break; -+ case 0x15: -+ /* ST M25P32 32 Mbit Serial Flash */ -+ sflash.blocksize = 64 * 1024; -+ sflash.numblocks = 64; -+ break; -+ case 0xbf: -+ W_REG(&cc->flashaddress, 1); -+ sflash_cmd(cc, SFLASH_ST_RES); -+ id2 = R_REG(&cc->flashdata); -+ if (id2 == 0x44) { -+ /* SST M25VF80 4 Mbit Serial Flash */ -+ sflash.blocksize = 64 * 1024; -+ sflash.numblocks = 8; -+ } -+ break; ++ /* Free hash table */ ++ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { ++ for (t = BCMINIT(nvram_hash)[i]; t; t = next) { ++ next = t->next; ++ BCMINIT(_nvram_free)(t); + } -+ break; ++ BCMINIT(nvram_hash)[i] = NULL; ++ } + -+ case SFLASH_AT: -+ /* Probe for Atmel chips */ -+ sflash_cmd(cc, SFLASH_AT_STATUS); -+ id = R_REG(&cc->flashdata) & 0x3c; -+ switch (id) { -+ case 0xc: -+ /* Atmel AT45DB011 1Mbit Serial Flash */ -+ sflash.blocksize = 256; -+ sflash.numblocks = 512; -+ break; -+ case 0x14: -+ /* Atmel AT45DB021 2Mbit Serial Flash */ -+ sflash.blocksize = 256; -+ sflash.numblocks = 1024; -+ break; -+ case 0x1c: -+ /* Atmel AT45DB041 4Mbit Serial Flash */ -+ sflash.blocksize = 256; -+ sflash.numblocks = 2048; -+ break; -+ case 0x24: -+ /* Atmel AT45DB081 8Mbit Serial Flash */ -+ sflash.blocksize = 256; -+ sflash.numblocks = 4096; -+ break; -+ case 0x2c: -+ /* Atmel AT45DB161 16Mbit Serial Flash */ -+ sflash.blocksize = 512; -+ sflash.numblocks = 4096; -+ break; -+ case 0x34: -+ /* Atmel AT45DB321 32Mbit Serial Flash */ -+ sflash.blocksize = 512; -+ sflash.numblocks = 8192; -+ break; -+ case 0x3c: -+ /* Atmel AT45DB642 64Mbit Serial Flash */ -+ sflash.blocksize = 1024; -+ sflash.numblocks = 8192; -+ break; -+ } -+ break; ++ /* Free dead table */ ++ for (t = nvram_dead; t; t = next) { ++ next = t->next; ++ BCMINIT(_nvram_free)(t); + } ++ nvram_dead = NULL; + -+ sflash.size = sflash.blocksize * sflash.numblocks; -+ return sflash.size ? &sflash : NULL; ++ /* Indicate to per-port code that all tuples have been freed */ ++ BCMINIT(_nvram_free)(NULL); +} + -+/* Read len bytes starting at offset into buf. Returns number of bytes read. */ -+int -+sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf) ++/* String hash */ ++static INLINE uint ++hash(const char *s) +{ -+ int cnt; -+ uint32 *from, *to; ++ uint hash = 0; + -+ if (!len) -+ return 0; ++ while (*s) ++ hash = 31 * hash + *s++; + -+ if ((offset + len) > sflash.size) -+ return -22; ++ return hash; ++} + -+ if ((len >= 4) && (offset & 3)) -+ cnt = 4 - (offset & 3); -+ else if ((len >= 4) && ((uint32)buf & 3)) -+ cnt = 4 - ((uint32)buf & 3); -+ else -+ cnt = len; ++/* (Re)initialize the hash table. Should be locked. */ ++static int ++BCMINITFN(nvram_rehash)(struct nvram_header *header) ++{ ++ char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq; + -+ from = (uint32 *)KSEG1ADDR(SB_FLASH2 + offset); -+ to = (uint32 *)buf; ++ /* (Re)initialize hash table */ ++ BCMINIT(nvram_free)(); + -+ if (cnt < 4) { -+ bcopy(from, to, cnt); -+ return cnt; ++ /* Parse and set "name=value\0 ... \0\0" */ ++ name = (char *) &header[1]; ++ end = (char *) header + NVRAM_SPACE - 2; ++ end[0] = end[1] = '\0'; ++ for (; *name; name = value + strlen(value) + 1) { ++ if (!(eq = strchr(name, '='))) ++ break; ++ *eq = '\0'; ++ value = eq + 1; ++ BCMINIT(_nvram_set)(name, value); ++ *eq = '='; + } + -+ while (cnt >= 4) { -+ *to++ = *from++; -+ cnt -= 4; ++ /* Set special SDRAM parameters */ ++ if (!BCMINIT(_nvram_get)("sdram_init")) { ++ sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16)); ++ BCMINIT(_nvram_set)("sdram_init", buf); ++ } ++ if (!BCMINIT(_nvram_get)("sdram_config")) { ++ sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff)); ++ BCMINIT(_nvram_set)("sdram_config", buf); ++ } ++ if (!BCMINIT(_nvram_get)("sdram_refresh")) { ++ sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff)); ++ BCMINIT(_nvram_set)("sdram_refresh", buf); ++ } ++ if (!BCMINIT(_nvram_get)("sdram_ncdl")) { ++ sprintf(buf, "0x%08X", header->config_ncdl); ++ BCMINIT(_nvram_set)("sdram_ncdl", buf); + } + -+ return (len - cnt); ++ return 0; +} + -+/* Poll for command completion. Returns zero when complete. */ -+int -+sflash_poll(chipcregs_t *cc, uint offset) ++/* Get the value of an NVRAM variable. Should be locked. */ ++char * ++BCMINITFN(_nvram_get)(const char *name) +{ -+ if (offset >= sflash.size) -+ return -22; ++ uint i; ++ struct nvram_tuple *t; ++ char *value; + -+ switch (sflash.type) { -+ case SFLASH_ST: -+ /* Check for ST Write In Progress bit */ -+ sflash_cmd(cc, SFLASH_ST_RDSR); -+ return R_REG(&cc->flashdata) & SFLASH_ST_WIP; -+ case SFLASH_AT: -+ /* Check for Atmel Ready bit */ -+ sflash_cmd(cc, SFLASH_AT_STATUS); -+ return !(R_REG(&cc->flashdata) & SFLASH_AT_READY); -+ } ++ if (!name) ++ return NULL; + -+ return 0; ++ /* Hash the name */ ++ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); ++ ++ /* Find the associated tuple in the hash table */ ++ for (t = BCMINIT(nvram_hash)[i]; t && strcmp(t->name, name); t = t->next); ++ ++ value = t ? t->value : NULL; ++ ++ return value; +} + -+/* Write len bytes starting at offset into buf. Returns number of bytes -+ * written. Caller should poll for completion. -+ */ -+int -+sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf) ++/* Get the value of an NVRAM variable. Should be locked. */ ++int ++BCMINITFN(_nvram_set)(const char *name, const char *value) +{ -+ struct sflash *sfl; -+ int ret = 0; -+ bool is4712b0; -+ uint32 page, byte, mask; ++ uint i; ++ struct nvram_tuple *t, *u, **prev; + -+ if (!len) ++ /* Hash the name */ ++ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); ++ ++ /* Find the associated tuple in the hash table */ ++ for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev); ++ ++ /* (Re)allocate tuple */ ++ if (!(u = BCMINIT(_nvram_realloc)(t, name, value))) ++ return -12; /* -ENOMEM */ ++ ++ /* Value reallocated */ ++ if (t && t == u) + return 0; + -+ if ((offset + len) > sflash.size) -+ return -22; ++ /* Move old tuple to the dead table */ ++ if (t) { ++ *prev = t->next; ++ t->next = nvram_dead; ++ nvram_dead = t; ++ } + -+ sfl = &sflash; -+ switch (sfl->type) { -+ case SFLASH_ST: -+ mask = R_REG(&cc->chipid); -+ is4712b0 = (((mask & CID_ID_MASK) == BCM4712_DEVICE_ID) && -+ ((mask & CID_REV_MASK) == (3 << CID_REV_SHIFT))); -+ /* Enable writes */ -+ sflash_cmd(cc, SFLASH_ST_WREN); -+ if (is4712b0) { -+ mask = 1 << 14; -+ W_REG(&cc->flashaddress, offset); -+ W_REG(&cc->flashdata, *buf++); -+ /* Set chip select */ -+ OR_REG(&cc->gpioout, mask); -+ /* Issue a page program with the first byte */ -+ sflash_cmd(cc, SFLASH_ST_PP); -+ ret = 1; -+ offset++; -+ len--; -+ while (len > 0) { -+ if ((offset & 255) == 0) { -+ /* Page boundary, drop cs and return */ -+ AND_REG(&cc->gpioout, ~mask); -+ if (!sflash_poll(cc, offset)) { -+ /* Flash rejected command */ -+ return -11; -+ } -+ return ret; -+ } else { -+ /* Write single byte */ -+ sflash_cmd(cc, *buf++); -+ } -+ ret++; -+ offset++; -+ len--; -+ } -+ /* All done, drop cs if needed */ -+ if ((offset & 255) != 1) { -+ /* Drop cs */ -+ AND_REG(&cc->gpioout, ~mask); -+ if (!sflash_poll(cc, offset)) { -+ /* Flash rejected command */ -+ return -12; -+ } -+ } -+ } else { -+ ret = 1; -+ W_REG(&cc->flashaddress, offset); -+ W_REG(&cc->flashdata, *buf); -+ /* Page program */ -+ sflash_cmd(cc, SFLASH_ST_PP); -+ } -+ break; -+ case SFLASH_AT: -+ mask = sfl->blocksize - 1; -+ page = (offset & ~mask) << 1; -+ byte = offset & mask; -+ /* Read main memory page into buffer 1 */ -+ if (byte || len < sfl->blocksize) { -+ W_REG(&cc->flashaddress, page); -+ sflash_cmd(cc, SFLASH_AT_BUF1_LOAD); -+ /* 250 us for AT45DB321B */ -+ SPINWAIT(sflash_poll(cc, offset), 1000); -+ ASSERT(!sflash_poll(cc, offset)); -+ } -+ /* Write into buffer 1 */ -+ for (ret = 0; ret < len && byte < sfl->blocksize; ret++) { -+ W_REG(&cc->flashaddress, byte++); -+ W_REG(&cc->flashdata, *buf++); -+ sflash_cmd(cc, SFLASH_AT_BUF1_WRITE); -+ } -+ /* Write buffer 1 into main memory page */ -+ W_REG(&cc->flashaddress, page); -+ sflash_cmd(cc, SFLASH_AT_BUF1_PROGRAM); -+ break; ++ /* Add new tuple to the hash table */ ++ u->next = BCMINIT(nvram_hash)[i]; ++ BCMINIT(nvram_hash)[i] = u; ++ ++ return 0; ++} ++ ++/* Unset the value of an NVRAM variable. Should be locked. */ ++int ++BCMINITFN(_nvram_unset)(const char *name) ++{ ++ uint i; ++ struct nvram_tuple *t, **prev; ++ ++ if (!name) ++ return 0; ++ ++ /* Hash the name */ ++ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); ++ ++ /* Find the associated tuple in the hash table */ ++ for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev); ++ ++ /* Move it to the dead table */ ++ if (t) { ++ *prev = t->next; ++ t->next = nvram_dead; ++ nvram_dead = t; + } + -+ return ret; ++ return 0; +} + -+/* Erase a region. Returns number of bytes scheduled for erasure. -+ * Caller should poll for completion. -+ */ -+int -+sflash_erase(chipcregs_t *cc, uint offset) ++/* Get all NVRAM variables. Should be locked. */ ++int ++BCMINITFN(_nvram_getall)(char *buf, int count) +{ -+ struct sflash *sfl; ++ uint i; ++ struct nvram_tuple *t; ++ int len = 0; + -+ if (offset >= sflash.size) -+ return -22; ++ bzero(buf, count); + -+ sfl = &sflash; -+ switch (sfl->type) { -+ case SFLASH_ST: -+ sflash_cmd(cc, SFLASH_ST_WREN); -+ W_REG(&cc->flashaddress, offset); -+ sflash_cmd(cc, SFLASH_ST_SE); -+ return sfl->blocksize; -+ case SFLASH_AT: -+ W_REG(&cc->flashaddress, offset << 1); -+ sflash_cmd(cc, SFLASH_AT_PAGE_ERASE); -+ return sfl->blocksize; ++ /* Write name=value\0 ... \0\0 */ ++ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { ++ for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) { ++ if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1)) ++ len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1; ++ else ++ break; ++ } + } + + return 0; +} + -+/* -+ * writes the appropriate range of flash, a NULL buf simply erases -+ * the region of flash -+ */ ++/* Regenerate NVRAM. Should be locked. */ +int -+sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf) ++BCMINITFN(_nvram_commit)(struct nvram_header *header) +{ -+ struct sflash *sfl; -+ uchar *block = NULL, *cur_ptr, *blk_ptr; -+ uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder; -+ uint blk_offset, blk_len, copied; -+ int bytes, ret = 0; -+ -+ /* Check address range */ -+ if (len <= 0) -+ return 0; ++ char *init, *config, *refresh, *ncdl; ++ char *ptr, *end; ++ int i; ++ struct nvram_tuple *t; ++ struct nvram_header tmp; ++ uint8 crc; + -+ sfl = &sflash; -+ if ((offset + len) > sfl->size) -+ return -1; ++ /* Regenerate header */ ++ header->magic = NVRAM_MAGIC; ++ header->crc_ver_init = (NVRAM_VERSION << 8); ++ if (!(init = BCMINIT(_nvram_get)("sdram_init")) || ++ !(config = BCMINIT(_nvram_get)("sdram_config")) || ++ !(refresh = BCMINIT(_nvram_get)("sdram_refresh")) || ++ !(ncdl = BCMINIT(_nvram_get)("sdram_ncdl"))) { ++ header->crc_ver_init |= SDRAM_INIT << 16; ++ header->config_refresh = SDRAM_CONFIG; ++ header->config_refresh |= SDRAM_REFRESH << 16; ++ header->config_ncdl = 0; ++ } else { ++ header->crc_ver_init |= (bcm_strtoul(init, NULL, 0) & 0xffff) << 16; ++ header->config_refresh = bcm_strtoul(config, NULL, 0) & 0xffff; ++ header->config_refresh |= (bcm_strtoul(refresh, NULL, 0) & 0xffff) << 16; ++ header->config_ncdl = bcm_strtoul(ncdl, NULL, 0); ++ } + -+ blocksize = sfl->blocksize; -+ mask = blocksize - 1; ++ /* Clear data area */ ++ ptr = (char *) header + sizeof(struct nvram_header); ++ bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header)); + -+ /* Allocate a block of mem */ -+ if (!(block = MALLOC(NULL, blocksize))) -+ return -1; ++ /* Leave space for a double NUL at the end */ ++ end = (char *) header + NVRAM_SPACE - 2; + -+ while (len) { -+ /* Align offset */ -+ cur_offset = offset & ~mask; -+ cur_length = blocksize; -+ cur_ptr = block; ++ /* Write out all tuples */ ++ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { ++ for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) { ++ if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end) ++ break; ++ ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1; ++ } ++ } + -+ remainder = blocksize - (offset & mask); -+ if (len < remainder) -+ cur_retlen = len; -+ else -+ cur_retlen = remainder; ++ /* End with a double NUL */ ++ ptr += 2; + -+ /* buf == NULL means erase only */ -+ if (buf) { -+ /* Copy existing data into holding block if necessary */ -+ if ((offset & mask) || (len < blocksize)) { -+ blk_offset = cur_offset; -+ blk_len = cur_length; -+ blk_ptr = cur_ptr; ++ /* Set new length */ ++ header->len = ROUNDUP(ptr - (char *) header, 4); + -+ /* Copy entire block */ -+ while(blk_len) { -+ copied = sflash_read(cc, blk_offset, blk_len, blk_ptr); -+ blk_offset += copied; -+ blk_len -= copied; -+ blk_ptr += copied; -+ } -+ } ++ /* Little-endian CRC8 over the last 11 bytes of the header */ ++ tmp.crc_ver_init = htol32(header->crc_ver_init); ++ tmp.config_refresh = htol32(header->config_refresh); ++ tmp.config_ncdl = htol32(header->config_ncdl); ++ crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, CRC8_INIT_VALUE); + -+ /* Copy input data into holding block */ -+ memcpy(cur_ptr + (offset & mask), buf, cur_retlen); -+ } ++ /* Continue CRC8 over data bytes */ ++ crc = hndcrc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc); + -+ /* Erase block */ -+ if ((ret = sflash_erase(cc, (uint) cur_offset)) < 0) -+ goto done; -+ while (sflash_poll(cc, (uint) cur_offset)); ++ /* Set new CRC8 */ ++ header->crc_ver_init |= crc; + -+ /* buf == NULL means erase only */ -+ if (!buf) { -+ offset += cur_retlen; -+ len -= cur_retlen; -+ continue; -+ } ++ /* Reinitialize hash table */ ++ return BCMINIT(nvram_rehash)(header); ++} + -+ /* Write holding block */ -+ while (cur_length > 0) { -+ if ((bytes = sflash_write(cc, -+ (uint) cur_offset, -+ (uint) cur_length, -+ (uchar *) cur_ptr)) < 0) { -+ ret = bytes; -+ goto done; -+ } -+ while (sflash_poll(cc, (uint) cur_offset)); -+ cur_offset += bytes; -+ cur_length -= bytes; -+ cur_ptr += bytes; -+ } ++/* Initialize hash table. Should be locked. */ ++int ++BCMINITFN(_nvram_init)(void) ++{ ++ struct nvram_header *header; ++ int ret; + -+ offset += cur_retlen; -+ len -= cur_retlen; -+ buf += cur_retlen; ++ if (!(header = (struct nvram_header *) kmalloc(NVRAM_SPACE, GFP_ATOMIC))) { ++ return -12; /* -ENOMEM */ + } + -+ ret = len; -+done: -+ if (block) -+ MFREE(NULL, block, blocksize); ++ if ((ret = BCMINIT(_nvram_read)(header)) == 0 && ++ header->magic == NVRAM_MAGIC) ++ BCMINIT(nvram_rehash)(header); ++ ++ kfree(header); + return ret; +} + -diff -Naur linux.old/arch/mips/bcm947xx/time.c linux.dev/arch/mips/bcm947xx/time.c ---- linux.old/arch/mips/bcm947xx/time.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/bcm947xx/time.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,118 @@ -+/* -+ * Copyright 2004, Broadcom Corporation -+ * All Rights Reserved. ++/* Free hash table. Should be locked. */ ++void ++BCMINITFN(_nvram_exit)(void) ++{ ++ BCMINIT(nvram_free)(); ++} +diff -urN linux.old/arch/mips/bcm947xx/nvram_linux.c linux.dev/arch/mips/bcm947xx/nvram_linux.c +--- linux.old/arch/mips/bcm947xx/nvram_linux.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/nvram_linux.c 2006-04-27 23:30:07.000000000 +0200 +@@ -0,0 +1,723 @@ ++/* ++ * NVRAM variable manipulation (Linux kernel half) ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * $Id: time.c,v 1.1 2005/03/16 13:49:59 wbx Exp $ ++ * $Id: nvram_linux.c,v 1.19 2006/04/08 07:12:42 honor Exp $ + */ ++ +#include +#include ++#include +#include -+#include -+#include ++#include +#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include +#include +#include -+#include ++#include + +#include +#include -+#include ++#include +#include ++#include +#include -+#include -+#include ++#include ++#include ++#include ++#include ++ ++/* In BSS to minimize text size and page aligned so it can be mmap()-ed */ ++static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE))); ++ ++#ifdef MODULE ++ ++#define early_nvram_get(name) nvram_get(name) ++ ++#else /* !MODULE */ + +/* Global SB handle */ +extern void *bcm947xx_sbh; +extern spinlock_t bcm947xx_sbh_lock; + ++static int cfe_env; ++extern char *cfe_env_get(char *nv_buf, const char *name); ++ +/* Convenience */ +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock ++#define KB * 1024 ++#define MB * 1024 * 1024 + -+extern int panic_timeout; -+static int watchdog = 0; -+static u8 *mcr = NULL; -+ -+void __init -+bcm947xx_time_init(void) ++/* Probe for NVRAM header */ ++static void __init ++early_nvram_init(void) +{ -+ unsigned int hz; -+ extifregs_t *eir; ++ struct nvram_header *header; ++ chipcregs_t *cc; ++ struct sflash *info = NULL; ++ int i; ++ uint32 base, off, lim; ++ u32 *src, *dst; + -+ /* -+ * Use deterministic values for initial counter interrupt -+ * so that calibrate delay avoids encountering a counter wrap. -+ */ -+ write_c0_count(0); -+ write_c0_compare(0xffff); ++ if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) { ++ base = KSEG1ADDR(SB_FLASH2); ++ switch (readl(&cc->capabilities) & CAP_FLASH_MASK) { ++ case PFLASH: ++ lim = SB_FLASH2_SZ; ++ break; + -+ if (!(hz = sb_mips_clock(sbh))) -+ hz = 100000000; ++ case SFLASH_ST: ++ case SFLASH_AT: ++ if ((info = sflash_init(cc)) == NULL) ++ return; ++ lim = info->size; ++ break; + -+ printk("CPU: BCM%04x rev %d at %d MHz\n", sb_chip(sbh), sb_chiprev(sbh), -+ (hz + 500000) / 1000000); ++ case FLASH_NONE: ++ default: ++ return; ++ } ++ } else { ++ /* extif assumed, Stop at 4 MB */ ++ base = KSEG1ADDR(SB_FLASH1); ++ lim = SB_FLASH1_SZ; ++ } + -+ /* Set MIPS counter frequency for fixed_rate_gettimeoffset() */ -+ mips_hpt_frequency = hz / 2; ++ /* XXX: hack for supporting the CFE environment stuff on WGT634U */ ++ src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000); ++ dst = (u32 *) nvram_buf; ++ if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) { ++ printk("early_nvram_init: WGT634U NVRAM found.\n"); + -+ /* Set watchdog interval in ms */ -+ watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0); -+ -+ /* Please set the watchdog to 3 sec if it is less than 3 but not equal to 0 */ -+ if (watchdog > 0) { -+ if (watchdog < 3000) -+ watchdog = 3000; ++ for (i = 0; i < 0x1ff0; i++) { ++ if (*src == 0xFFFFFFFF) ++ break; ++ *dst++ = *src++; ++ } ++ cfe_env = 1; ++ return; + } + ++ off = FLASH_MIN; ++ while (off <= lim) { ++ /* Windowed flash access */ ++ header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); ++ if (header->magic == NVRAM_MAGIC) ++ goto found; ++ off <<= 1; ++ } + -+ /* Set panic timeout in seconds */ -+ panic_timeout = watchdog / 1000; ++ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ ++ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB); ++ if (header->magic == NVRAM_MAGIC) ++ goto found; ++ ++ header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); ++ if (header->magic == NVRAM_MAGIC) ++ goto found; ++ ++ printk("early_nvram_init: NVRAM not found\n"); ++ return; + -+ /* Setup blink */ -+ if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) { -+ sbconfig_t *sb = (sbconfig_t *)((unsigned int) eir + SBCONFIGOFF); -+ unsigned long base = EXTIF_CFGIF_BASE(sb_base(readl(&sb->sbadmatch1))); -+ mcr = (u8 *) ioremap_nocache(base + UART_MCR, 1); ++found: ++ src = (u32 *) header; ++ dst = (u32 *) nvram_buf; ++ for (i = 0; i < sizeof(struct nvram_header); i += 4) ++ *dst++ = *src++; ++ for (; i < header->len && i < NVRAM_SPACE; i += 4) ++ *dst++ = ltoh32(*src++); ++} ++ ++/* Early (before mm or mtd) read-only access to NVRAM */ ++static char * __init ++early_nvram_get(const char *name) ++{ ++ char *var, *value, *end, *eq; ++ ++ if (!name) ++ return NULL; ++ ++ /* Too early? */ ++ if (sbh == NULL) ++ return NULL; ++ ++ if (!nvram_buf[0]) ++ early_nvram_init(); ++ ++ if (cfe_env) ++ return cfe_env_get(nvram_buf, name); ++ ++ /* Look for name=value and return value */ ++ var = &nvram_buf[sizeof(struct nvram_header)]; ++ end = nvram_buf + sizeof(nvram_buf) - 2; ++ end[0] = end[1] = '\0'; ++ for (; *var; var = value + strlen(value) + 1) { ++ if (!(eq = strchr(var, '='))) ++ break; ++ value = eq + 1; ++ if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0) ++ return value; + } ++ ++ return NULL; +} + -+static void -+bcm947xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ++static int __init ++early_nvram_getall(char *buf, int count) +{ -+ /* Generic MIPS timer code */ -+ timer_interrupt(irq, dev_id, regs); ++ char *var, *end; ++ int len = 0; ++ ++ /* Too early? */ ++ if (sbh == NULL) ++ return -1; + -+ /* Set the watchdog timer to reset after the specified number of ms */ -+ if (watchdog > 0) -+ sb_watchdog(sbh, WATCHDOG_CLOCK / 1000 * watchdog); ++ if (!nvram_buf[0]) ++ early_nvram_init(); + -+#ifdef CONFIG_HWSIM -+ (*((int *)0xa0000f1c))++; -+#else -+ /* Blink one of the LEDs in the external UART */ -+ if (mcr && !(jiffies % (HZ/2))) -+ writeb(readb(mcr) ^ UART_MCR_OUT2, mcr); -+#endif ++ bzero(buf, count); ++ ++ /* Write name=value\0 ... \0\0 */ ++ var = &nvram_buf[sizeof(struct nvram_header)]; ++ end = nvram_buf + sizeof(nvram_buf) - 2; ++ end[0] = end[1] = '\0'; ++ for (; *var; var += strlen(var) + 1) { ++ if ((count - len) <= (strlen(var) + 1)) ++ break; ++ len += sprintf(buf + len, "%s", var) + 1; ++ } ++ ++ return 0; +} ++#endif /* !MODULE */ + -+static struct irqaction bcm947xx_timer_irqaction = { -+ bcm947xx_timer_interrupt, -+ SA_INTERRUPT, -+ 0, -+ "timer", -+ NULL, -+ NULL -+}; ++extern char * _nvram_get(const char *name); ++extern int _nvram_set(const char *name, const char *value); ++extern int _nvram_unset(const char *name); ++extern int _nvram_getall(char *buf, int count); ++extern int _nvram_commit(struct nvram_header *header); ++extern int _nvram_init(void *sbh); ++extern void _nvram_exit(void); + -+void __init -+bcm947xx_timer_setup(struct irqaction *irq) ++/* Globals */ ++static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED; ++static struct semaphore nvram_sem; ++static unsigned long nvram_offset = 0; ++static int nvram_major = -1; ++static devfs_handle_t nvram_handle = NULL; ++static struct mtd_info *nvram_mtd = NULL; ++ ++int ++_nvram_read(char *buf) +{ -+ /* Enable the timer interrupt */ -+ setup_irq(7, &bcm947xx_timer_irqaction); ++ struct nvram_header *header = (struct nvram_header *) buf; ++ size_t len; ++ ++ if (!nvram_mtd || ++ MTD_READ(nvram_mtd, nvram_mtd->size - NVRAM_SPACE, NVRAM_SPACE, &len, buf) || ++ len != NVRAM_SPACE || ++ header->magic != NVRAM_MAGIC) { ++ /* Maybe we can recover some data from early initialization */ ++ memcpy(buf, nvram_buf, NVRAM_SPACE); ++ } ++ ++ return 0; +} -diff -Naur linux.old/arch/mips/config-shared.in linux.dev/arch/mips/config-shared.in ---- linux.old/arch/mips/config-shared.in 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/arch/mips/config-shared.in 2006-04-06 15:34:14.000000000 +0200 -@@ -208,6 +208,14 @@ - fi - define_bool CONFIG_MIPS_RTC y - fi -+dep_bool 'Support for Broadcom MIPS-based boards' CONFIG_MIPS_BRCM $CONFIG_EXPERIMENTAL -+dep_bool 'Support for Broadcom BCM947XX' CONFIG_BCM947XX $CONFIG_MIPS_BRCM -+if [ "$CONFIG_BCM947XX" = "y" ] ; then -+ bool ' Support for Broadcom BCM4710' CONFIG_BCM4710 -+ bool ' Support for Broadcom BCM4310' CONFIG_BCM4310 -+ bool ' Support for Broadcom BCM4704' CONFIG_BCM4704 -+ bool ' Support for Broadcom BCM5365' CONFIG_BCM5365 -+fi - bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI - bool 'Support for TANBAC TB0226 (Mbase)' CONFIG_TANBAC_TB0226 - bool 'Support for TANBAC TB0229 (VR4131DIMM)' CONFIG_TANBAC_TB0229 -@@ -229,6 +237,11 @@ - define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n - - # -+# Provide an option for a default kernel command line -+# -+string 'Default kernel command string' CONFIG_CMDLINE "" -+ -+# - # Select some configuration options automatically based on user selections. - # - if [ "$CONFIG_ACER_PICA_61" = "y" ]; then -@@ -554,6 +567,13 @@ - define_bool CONFIG_SWAP_IO_SPACE_L y - define_bool CONFIG_BOOT_ELF32 y - fi -+if [ "$CONFIG_BCM947XX" = "y" ] ; then -+ define_bool CONFIG_PCI y -+ define_bool CONFIG_NONCOHERENT_IO y -+ define_bool CONFIG_NEW_TIME_C y -+ define_bool CONFIG_NEW_IRQ y -+ define_bool CONFIG_HND y -+fi - if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then - define_bool CONFIG_ARC32 y - define_bool CONFIG_ARC_MEMORY y -@@ -1042,7 +1062,11 @@ - - bool 'Are you using a crosscompiler' CONFIG_CROSSCOMPILE - bool 'Enable run-time debugging' CONFIG_RUNTIME_DEBUG --bool 'Remote GDB kernel debugging' CONFIG_KGDB -+if [ "$CONFIG_BCM947XX" = "y" ] ; then -+ bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG -+else -+ bool 'Remote GDB kernel debugging' CONFIG_KGDB -+fi - dep_bool ' Console output to GDB' CONFIG_GDB_CONSOLE $CONFIG_KGDB - if [ "$CONFIG_KGDB" = "y" ]; then - define_bool CONFIG_DEBUG_INFO y -diff -Naur linux.old/arch/mips/kernel/cpu-probe.c linux.dev/arch/mips/kernel/cpu-probe.c ---- linux.old/arch/mips/kernel/cpu-probe.c 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/arch/mips/kernel/cpu-probe.c 2006-04-06 15:34:14.000000000 +0200 -@@ -162,7 +162,7 @@ - - static inline void cpu_probe_legacy(struct cpuinfo_mips *c) - { -- switch (c->processor_id & 0xff00) { -+ switch (c->processor_id & PRID_IMP_MASK) { - case PRID_IMP_R2000: - c->cputype = CPU_R2000; - c->isa_level = MIPS_CPU_ISA_I; -@@ -172,7 +172,7 @@ - c->tlbsize = 64; - break; - case PRID_IMP_R3000: -- if ((c->processor_id & 0xff) == PRID_REV_R3000A) -+ if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) - if (cpu_has_confreg()) - c->cputype = CPU_R3081E; - else -@@ -187,12 +187,12 @@ - break; - case PRID_IMP_R4000: - if (read_c0_config() & CONF_SC) { -- if ((c->processor_id & 0xff) >= PRID_REV_R4400) -+ if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_R4400) - c->cputype = CPU_R4400PC; - else - c->cputype = CPU_R4000PC; - } else { -- if ((c->processor_id & 0xff) >= PRID_REV_R4400) -+ if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_R4400) - c->cputype = CPU_R4400SC; - else - c->cputype = CPU_R4000SC; -@@ -438,7 +438,7 @@ - static inline void cpu_probe_mips(struct cpuinfo_mips *c) - { - decode_config1(c); -- switch (c->processor_id & 0xff00) { -+ switch (c->processor_id & PRID_IMP_MASK) { - case PRID_IMP_4KC: - c->cputype = CPU_4KC; - c->isa_level = MIPS_CPU_ISA_M32; -@@ -479,10 +479,10 @@ - { - decode_config1(c); - c->options |= MIPS_CPU_PREFETCH; -- switch (c->processor_id & 0xff00) { -+ switch (c->processor_id & PRID_IMP_MASK) { - case PRID_IMP_AU1_REV1: - case PRID_IMP_AU1_REV2: -- switch ((c->processor_id >> 24) & 0xff) { -+ switch ((c->processor_id >> 24) & PRID_REV_MASK) { - case 0: - c->cputype = CPU_AU1000; - break; -@@ -510,10 +510,34 @@ - } - } - -+static inline void cpu_probe_broadcom(struct cpuinfo_mips *c) -+{ -+ decode_config1(c); -+ c->options |= MIPS_CPU_PREFETCH; -+ switch (c->processor_id & PRID_IMP_MASK) { -+ case PRID_IMP_BCM4710: -+ c->cputype = CPU_BCM4710; -+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | -+ MIPS_CPU_4KTLB | MIPS_CPU_COUNTER; -+ c->scache.flags = MIPS_CACHE_NOT_PRESENT; -+ break; -+ case PRID_IMP_4KC: -+ case PRID_IMP_BCM3302: -+ c->cputype = CPU_BCM3302; -+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | -+ MIPS_CPU_4KTLB | MIPS_CPU_COUNTER; -+ c->scache.flags = MIPS_CACHE_NOT_PRESENT; -+ break; -+ default: -+ c->cputype = CPU_UNKNOWN; -+ break; -+ } -+} -+ - static inline void cpu_probe_sibyte(struct cpuinfo_mips *c) - { - decode_config1(c); -- switch (c->processor_id & 0xff00) { -+ switch (c->processor_id & PRID_IMP_MASK) { - case PRID_IMP_SB1: - c->cputype = CPU_SB1; - c->isa_level = MIPS_CPU_ISA_M64; -@@ -535,7 +559,7 @@ - static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c) - { - decode_config1(c); -- switch (c->processor_id & 0xff00) { -+ switch (c->processor_id & PRID_IMP_MASK) { - case PRID_IMP_SR71000: - c->cputype = CPU_SR71000; - c->isa_level = MIPS_CPU_ISA_M64; -@@ -560,7 +584,7 @@ - c->cputype = CPU_UNKNOWN; - - c->processor_id = read_c0_prid(); -- switch (c->processor_id & 0xff0000) { -+ switch (c->processor_id & PRID_COMP_MASK) { - - case PRID_COMP_LEGACY: - cpu_probe_legacy(c); -@@ -571,6 +595,9 @@ - case PRID_COMP_ALCHEMY: - cpu_probe_alchemy(c); - break; -+ case PRID_COMP_BROADCOM: -+ cpu_probe_broadcom(c); -+ break; - case PRID_COMP_SIBYTE: - cpu_probe_sibyte(c); - break; -diff -Naur linux.old/arch/mips/kernel/head.S linux.dev/arch/mips/kernel/head.S ---- linux.old/arch/mips/kernel/head.S 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/arch/mips/kernel/head.S 2006-04-06 15:34:14.000000000 +0200 -@@ -28,12 +28,20 @@ - #include - #include - -+#ifdef CONFIG_BCM4710 -+#undef eret -+#define eret nop; nop; eret -+#endif -+ - .text -+ j kernel_entry -+ nop -+ - /* - * Reserved space for exception handlers. - * Necessary for machines which link their kernels at KSEG0. - */ -- .fill 0x400 -+ .fill 0x3f4 - - /* The following two symbols are used for kernel profiling. */ - EXPORT(stext) -diff -Naur linux.old/arch/mips/kernel/proc.c linux.dev/arch/mips/kernel/proc.c ---- linux.old/arch/mips/kernel/proc.c 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/arch/mips/kernel/proc.c 2006-04-06 15:34:14.000000000 +0200 -@@ -78,9 +78,10 @@ - [CPU_AU1550] "Au1550", - [CPU_24K] "MIPS 24K", - [CPU_AU1200] "Au1200", -+ [CPU_BCM4710] "BCM4710", -+ [CPU_BCM3302] "BCM3302", - }; - -- - static int show_cpuinfo(struct seq_file *m, void *v) - { - unsigned int version = current_cpu_data.processor_id; -diff -Naur linux.old/arch/mips/kernel/setup.c linux.dev/arch/mips/kernel/setup.c ---- linux.old/arch/mips/kernel/setup.c 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/arch/mips/kernel/setup.c 2006-04-06 15:34:14.000000000 +0200 -@@ -493,6 +493,7 @@ - void swarm_setup(void); - void hp_setup(void); - void au1x00_setup(void); -+ void brcm_setup(void); - void frame_info_init(void); - - frame_info_init(); -@@ -691,6 +692,11 @@ - pmc_yosemite_setup(); - break; - #endif -+#if defined(CONFIG_BCM4710) || defined(CONFIG_BCM4310) -+ case MACH_GROUP_BRCM: -+ brcm_setup(); -+ break; -+#endif - default: - panic("Unsupported architecture"); - } -diff -Naur linux.old/arch/mips/kernel/traps.c linux.dev/arch/mips/kernel/traps.c ---- linux.old/arch/mips/kernel/traps.c 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/arch/mips/kernel/traps.c 2006-04-06 15:34:14.000000000 +0200 -@@ -920,6 +920,7 @@ - void __init trap_init(void) - { - extern char except_vec1_generic; -+ extern char except_vec2_generic; - extern char except_vec3_generic, except_vec3_r4000; - extern char except_vec_ejtag_debug; - extern char except_vec4; -@@ -927,6 +928,7 @@ - - /* Copy the generic exception handler code to it's final destination. */ - memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80); -+ memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); - - /* - * Setup default vectors -@@ -985,6 +987,12 @@ - set_except_vector(13, handle_tr); - set_except_vector(22, handle_mdmx); - -+ if (current_cpu_data.cputype == CPU_SB1) { -+ /* Enable timer interrupt and scd mapped interrupt */ -+ clear_c0_status(0xf000); -+ set_c0_status(0xc00); -+ } -+ - if (cpu_has_fpu && !cpu_has_nofpuex) - set_except_vector(15, handle_fpe); - -diff -Naur linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c ---- linux.old/arch/mips/mm/c-r4k.c 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/arch/mips/mm/c-r4k.c 2006-04-06 15:34:15.000000000 +0200 -@@ -1166,3 +1166,47 @@ - build_clear_page(); - build_copy_page(); - } -+ -+#ifdef CONFIG_BCM4704 -+static void __init mips32_icache_fill(unsigned long addr, uint nbytes) -+{ -+ unsigned long ic_lsize = current_cpu_data.icache.linesz; -+ int i; -+ for (i = 0; i < nbytes; i += ic_lsize) -+ fill_icache_line((addr + i)); -+} -+ -+/* -+ * This must be run from the cache on 4704A0 -+ * so there are no mips core BIU ops in progress -+ * when the PFC is enabled. -+ */ -+#define PFC_CR0 0xff400000 /* control reg 0 */ -+#define PFC_CR1 0xff400004 /* control reg 1 */ -+static void __init enable_pfc(u32 mode) -+{ -+ /* write range */ -+ *(volatile u32 *)PFC_CR1 = 0xffff0000; -+ -+ /* enable */ -+ *(volatile u32 *)PFC_CR0 = mode; -+} -+#endif -+ -+ -+void check_enable_mips_pfc(int val) -+{ -+ -+#ifdef CONFIG_BCM4704 -+ struct cpuinfo_mips *c = ¤t_cpu_data; -+ -+ /* enable prefetch cache */ -+ if (((c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) == PRID_IMP_BCM3302) -+ && (read_c0_diag() & (1 << 29))) { -+ mips32_icache_fill((unsigned long) &enable_pfc, 64); -+ enable_pfc(val); -+ } -+#endif -+} -+ -+ -diff -Naur linux.old/arch/mips/pci/Makefile linux.dev/arch/mips/pci/Makefile ---- linux.old/arch/mips/pci/Makefile 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/arch/mips/pci/Makefile 2006-04-06 15:34:14.000000000 +0200 -@@ -13,7 +13,9 @@ - obj-$(CONFIG_MIPS_MSC) += ops-msc.o - obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o - obj-$(CONFIG_SNI_RM200_PCI) += ops-sni.o -+ifndef CONFIG_BCM947XX - obj-y += pci.o -+endif - obj-$(CONFIG_PCI_AUTO) += pci_auto.o - - include $(TOPDIR)/Rules.make -diff -Naur linux.old/drivers/char/serial.c linux.dev/drivers/char/serial.c ---- linux.old/drivers/char/serial.c 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/drivers/char/serial.c 2006-04-06 15:34:14.000000000 +0200 -@@ -444,6 +444,10 @@ - return inb(info->port+1); - #endif - case SERIAL_IO_MEM: -+#ifdef CONFIG_BCM4310 -+ readb((unsigned long) info->iomem_base + -+ (UART_SCR<iomem_reg_shift)); -+#endif - return readb((unsigned long) info->iomem_base + - (offset<iomem_reg_shift)); - default: -@@ -464,6 +468,9 @@ - case SERIAL_IO_MEM: - writeb(value, (unsigned long) info->iomem_base + - (offset<iomem_reg_shift)); -+#ifdef CONFIG_BCM4704 -+ *((volatile unsigned int *) KSEG1ADDR(0x18000000)); -+#endif - break; - default: - outb(value, info->port+offset); -@@ -1728,7 +1735,7 @@ - /* Special case since 134 is really 134.5 */ - quot = (2*baud_base / 269); - else if (baud) -- quot = baud_base / baud; -+ quot = (baud_base + (baud / 2)) / baud; - } - /* If the quotient is zero refuse the change */ - if (!quot && old_termios) { -@@ -1745,12 +1752,12 @@ - /* Special case since 134 is really 134.5 */ - quot = (2*baud_base / 269); - else if (baud) -- quot = baud_base / baud; -+ quot = (baud_base + (baud / 2)) / baud; - } - } - /* As a last resort, if the quotient is zero, default to 9600 bps */ - if (!quot) -- quot = baud_base / 9600; -+ quot = (baud_base + 4800) / 9600; - /* - * Work around a bug in the Oxford Semiconductor 952 rev B - * chip which causes it to seriously miscalculate baud rates -@@ -5994,6 +6001,13 @@ - * Divisor, bytesize and parity - */ - state = rs_table + co->index; -+ /* -+ * Safe guard: state structure must have been initialized -+ */ -+ if (state->iomem_base == NULL) { -+ printk("!unable to setup serial console!\n"); -+ return -1; -+ } - if (doflow) - state->flags |= ASYNC_CONS_FLOW; - info = &async_sercons; -@@ -6007,7 +6021,7 @@ - info->io_type = state->io_type; - info->iomem_base = state->iomem_base; - info->iomem_reg_shift = state->iomem_reg_shift; -- quot = state->baud_base / baud; -+ quot = (state->baud_base + (baud / 2)) / baud; - cval = cflag & (CSIZE | CSTOPB); - #if defined(__powerpc__) || defined(__alpha__) - cval >>= 8; -diff -Naur linux.old/drivers/net/Config.in linux.dev/drivers/net/Config.in ---- linux.old/drivers/net/Config.in 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/drivers/net/Config.in 2006-04-06 15:34:14.000000000 +0200 -@@ -2,6 +2,8 @@ - # Network device configuration - # - -+tristate 'Broadcom Home Network Division' CONFIG_HND $CONFIG_PCI -+ - source drivers/net/arcnet/Config.in - - tristate 'Dummy net driver support' CONFIG_DUMMY -diff -Naur linux.old/drivers/net/Makefile linux.dev/drivers/net/Makefile ---- linux.old/drivers/net/Makefile 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/drivers/net/Makefile 2006-04-06 16:45:29.000000000 +0200 -@@ -3,6 +3,8 @@ - # Makefile for the Linux network (ethercard) device drivers. - # - -+EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include -+ - obj-y := - obj-m := - obj-n := -@@ -39,6 +41,9 @@ - obj-$(CONFIG_ISDN) += slhc.o - endif - -+subdir-$(CONFIG_HND) += hnd -+subdir-$(CONFIG_WL) += wl -+subdir-$(CONFIG_WL2) += wl2 - subdir-$(CONFIG_NET_PCMCIA) += pcmcia - subdir-$(CONFIG_NET_WIRELESS) += wireless - subdir-$(CONFIG_TULIP) += tulip -@@ -69,6 +74,10 @@ - obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o - obj-$(CONFIG_SUNGEM) += sungem.o - -+ifeq ($(CONFIG_HND),y) -+ obj-y += hnd/hnd.o -+endif -+ - obj-$(CONFIG_MACE) += mace.o - obj-$(CONFIG_BMAC) += bmac.o - obj-$(CONFIG_GMAC) += gmac.o -diff -Naur linux.old/drivers/net/hnd/Makefile linux.dev/drivers/net/hnd/Makefile ---- linux.old/drivers/net/hnd/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/hnd/Makefile 2006-04-06 16:20:00.000000000 +0200 -@@ -0,0 +1,19 @@ -+# -+# Makefile for the BCM47xx specific kernel interface routines -+# under Linux. -+# -+ -+EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER -+ -+O_TARGET := hnd.o -+ -+HND_OBJS := bcmutils.o linux_osl.o sbutils.o bcmsrom.o -+ -+export-objs := shared_ksyms.o -+obj-y := shared_ksyms.o $(HND_OBJS) -+obj-m := $(O_TARGET) -+ -+include $(TOPDIR)/Rules.make -+ -+shared_ksyms.c: shared_ksyms.sh $(HND_OBJS) -+ sh -e $< $(HND_OBJS) > $@ -diff -Naur linux.old/drivers/net/hnd/bcmsrom.c linux.dev/drivers/net/hnd/bcmsrom.c ---- linux.old/drivers/net/hnd/bcmsrom.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/hnd/bcmsrom.c 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,938 @@ -+/* -+ * Misc useful routines to access NIC SROM/OTP . -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct ether_addr { -+ uint8 octet[6]; -+} PACKED; -+ -+#define VARS_MAX 4096 /* should be reduced */ -+ -+#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */ -+#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */ -+ -+static int initvars_srom_pci(void *sbh, void *curmap, char **vars, int *count); -+static int initvars_cis_pcmcia(void *sbh, osl_t *osh, char **vars, int *count); -+static int initvars_flash_sb(void *sbh, char **vars, int *count); -+static int srom_parsecis(osl_t *osh, uint8 *cis, char **vars, int *count); -+static int sprom_cmd_pcmcia(osl_t *osh, uint8 cmd); -+static int sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data); -+static int sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data); -+static int sprom_read_pci(uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc); -+ -+static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count); -+static int initvars_flash(osl_t *osh, char **vp, int len, char *devpath); -+ -+/* -+ * Initialize local vars from the right source for this platform. -+ * Return 0 on success, nonzero on error. -+ */ -+int -+srom_var_init(void *sbh, uint bustype, void *curmap, osl_t *osh, char **vars, int *count) -+{ -+ ASSERT(bustype == BUSTYPE(bustype)); -+ if (vars == NULL || count == NULL) -+ return (0); -+ -+ switch (BUSTYPE(bustype)) { -+ case SB_BUS: -+ case JTAG_BUS: -+ return initvars_flash_sb(sbh, vars, count); -+ -+ case PCI_BUS: -+ ASSERT(curmap); /* can not be NULL */ -+ return initvars_srom_pci(sbh, curmap, vars, count); -+ -+ case PCMCIA_BUS: -+ return initvars_cis_pcmcia(sbh, osh, vars, count); -+ -+ -+ default: -+ ASSERT(0); -+ } -+ return (-1); -+} -+ -+/* support only 16-bit word read from srom */ -+int -+srom_read(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf) -+{ -+ void *srom; -+ uint i, off, nw; -+ -+ ASSERT(bustype == BUSTYPE(bustype)); -+ -+ /* check input - 16-bit access only */ -+ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2)) -+ return 1; -+ -+ off = byteoff / 2; -+ nw = nbytes / 2; -+ -+ if (BUSTYPE(bustype) == PCI_BUS) { -+ if (!curmap) -+ return 1; -+ srom = (uchar*)curmap + PCI_BAR0_SPROM_OFFSET; -+ if (sprom_read_pci(srom, off, buf, nw, FALSE)) -+ return 1; -+ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { -+ for (i = 0; i < nw; i++) { -+ if (sprom_read_pcmcia(osh, (uint16)(off + i), (uint16*)(buf + i))) -+ return 1; -+ } -+ } else { -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* support only 16-bit word write into srom */ -+int -+srom_write(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf) -+{ -+ uint16 *srom; -+ uint i, off, nw, crc_range; -+ uint16 image[SPROM_SIZE], *p; -+ uint8 crc; -+ volatile uint32 val32; -+ -+ ASSERT(bustype == BUSTYPE(bustype)); -+ -+ /* check input - 16-bit access only */ -+ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2)) -+ return 1; -+ -+ crc_range = (((BUSTYPE(bustype) == PCMCIA_BUS) || (BUSTYPE(bustype) == SDIO_BUS)) ? SPROM_SIZE : SPROM_CRC_RANGE) * 2; -+ -+ /* if changes made inside crc cover range */ -+ if (byteoff < crc_range) { -+ nw = (((byteoff + nbytes) > crc_range) ? byteoff + nbytes : crc_range) / 2; -+ /* read data including entire first 64 words from srom */ -+ if (srom_read(bustype, curmap, osh, 0, nw * 2, image)) -+ return 1; -+ /* make changes */ -+ bcopy((void*)buf, (void*)&image[byteoff / 2], nbytes); -+ /* calculate crc */ -+ htol16_buf(image, crc_range); -+ crc = ~hndcrc8((uint8 *)image, crc_range - 1, CRC8_INIT_VALUE); -+ ltoh16_buf(image, crc_range); -+ image[(crc_range / 2) - 1] = (crc << 8) | (image[(crc_range / 2) - 1] & 0xff); -+ p = image; -+ off = 0; -+ } else { -+ p = buf; -+ off = byteoff / 2; -+ nw = nbytes / 2; -+ } -+ -+ if (BUSTYPE(bustype) == PCI_BUS) { -+ srom = (uint16*)((uchar*)curmap + PCI_BAR0_SPROM_OFFSET); -+ /* enable writes to the SPROM */ -+ val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); -+ val32 |= SPROM_WRITEEN; -+ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32); -+ bcm_mdelay(WRITE_ENABLE_DELAY); -+ /* write srom */ -+ for (i = 0; i < nw; i++) { -+ W_REG(&srom[off + i], p[i]); -+ bcm_mdelay(WRITE_WORD_DELAY); -+ } -+ /* disable writes to the SPROM */ -+ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & ~SPROM_WRITEEN); -+ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { -+ /* enable writes to the SPROM */ -+ if (sprom_cmd_pcmcia(osh, SROM_WEN)) -+ return 1; -+ bcm_mdelay(WRITE_ENABLE_DELAY); -+ /* write srom */ -+ for (i = 0; i < nw; i++) { -+ sprom_write_pcmcia(osh, (uint16)(off + i), p[i]); -+ bcm_mdelay(WRITE_WORD_DELAY); -+ } -+ /* disable writes to the SPROM */ -+ if (sprom_cmd_pcmcia(osh, SROM_WDS)) -+ return 1; -+ } else { -+ return 1; -+ } -+ -+ bcm_mdelay(WRITE_ENABLE_DELAY); -+ return 0; -+} -+ -+ -+static int -+srom_parsecis(osl_t *osh, uint8 *cis, char **vars, int *count) -+{ -+ char eabuf[32]; -+ char *vp, *base; -+ uint8 tup, tlen, sromrev = 1; -+ int i, j; -+ uint varsize; -+ bool ag_init = FALSE; -+ uint32 w32; -+ -+ ASSERT(vars); -+ ASSERT(count); -+ -+ base = vp = MALLOC(osh, VARS_MAX); -+ ASSERT(vp); -+ if (!vp) -+ return -2; -+ -+ i = 0; -+ do { -+ tup = cis[i++]; -+ tlen = cis[i++]; -+ if ((i + tlen) >= CIS_SIZE) -+ break; -+ -+ switch (tup) { -+ case CISTPL_MANFID: -+ vp += sprintf(vp, "manfid=%d", (cis[i + 1] << 8) + cis[i]); -+ vp++; -+ vp += sprintf(vp, "prodid=%d", (cis[i + 3] << 8) + cis[i + 2]); -+ vp++; -+ break; -+ -+ case CISTPL_FUNCE: -+ if (cis[i] == LAN_NID) { -+ ASSERT(cis[i + 1] == 6); -+ bcm_ether_ntoa((uchar*)&cis[i + 2], eabuf); -+ vp += sprintf(vp, "il0macaddr=%s", eabuf); -+ vp++; -+ } -+ break; -+ -+ case CISTPL_CFTABLE: -+ vp += sprintf(vp, "regwindowsz=%d", (cis[i + 7] << 8) | cis[i + 6]); -+ vp++; -+ break; -+ -+ case CISTPL_BRCM_HNBU: -+ switch (cis[i]) { -+ case HNBU_SROMREV: -+ sromrev = cis[i + 1]; -+ break; -+ -+ case HNBU_CHIPID: -+ vp += sprintf(vp, "vendid=%d", (cis[i + 2] << 8) + cis[i + 1]); -+ vp++; -+ vp += sprintf(vp, "devid=%d", (cis[i + 4] << 8) + cis[i + 3]); -+ vp++; -+ if (tlen == 7) { -+ vp += sprintf(vp, "chiprev=%d", (cis[i + 6] << 8) + cis[i + 5]); -+ vp++; -+ } -+ break; -+ -+ case HNBU_BOARDREV: -+ vp += sprintf(vp, "boardrev=%d", cis[i + 1]); -+ vp++; -+ break; -+ -+ case HNBU_AA: -+ vp += sprintf(vp, "aa0=%d", cis[i + 1]); -+ vp++; -+ break; -+ -+ case HNBU_AG: -+ vp += sprintf(vp, "ag0=%d", cis[i + 1]); -+ vp++; -+ ag_init = TRUE; -+ break; -+ -+ case HNBU_CC: -+ ASSERT(sromrev > 1); -+ vp += sprintf(vp, "cc=%d", cis[i + 1]); -+ vp++; -+ break; -+ -+ case HNBU_PAPARMS: -+ if (tlen == 2) { -+ ASSERT(sromrev == 1); -+ vp += sprintf(vp, "pa0maxpwr=%d", cis[i + 1]); -+ vp++; -+ } else if (tlen >= 9) { -+ if (tlen == 10) { -+ ASSERT(sromrev == 2); -+ vp += sprintf(vp, "opo=%d", cis[i + 9]); -+ vp++; -+ } else -+ ASSERT(tlen == 9); -+ -+ for (j = 0; j < 3; j++) { -+ vp += sprintf(vp, "pa0b%d=%d", j, -+ (cis[i + (j * 2) + 2] << 8) + cis[i + (j * 2) + 1]); -+ vp++; -+ } -+ vp += sprintf(vp, "pa0itssit=%d", cis[i + 7]); -+ vp++; -+ vp += sprintf(vp, "pa0maxpwr=%d", cis[i + 8]); -+ vp++; -+ } else -+ ASSERT(tlen >= 9); -+ break; -+ -+ case HNBU_OEM: -+ ASSERT(sromrev == 1); -+ vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x", -+ cis[i + 1], cis[i + 2], cis[i + 3], cis[i + 4], -+ cis[i + 5], cis[i + 6], cis[i + 7], cis[i + 8]); -+ vp++; -+ break; -+ -+ case HNBU_BOARDFLAGS: -+ w32 = (cis[i + 2] << 8) + cis[i + 1]; -+ if (tlen == 5) -+ w32 |= (cis[i + 4] << 24) + (cis[i + 3] << 16); -+ vp += sprintf(vp, "boardflags=0x%x", w32); -+ vp++; -+ break; -+ -+ case HNBU_LEDS: -+ if (cis[i + 1] != 0xff) { -+ vp += sprintf(vp, "wl0gpio0=%d", cis[i + 1]); -+ vp++; -+ } -+ if (cis[i + 2] != 0xff) { -+ vp += sprintf(vp, "wl0gpio1=%d", cis[i + 2]); -+ vp++; -+ } -+ if (cis[i + 3] != 0xff) { -+ vp += sprintf(vp, "wl0gpio2=%d", cis[i + 3]); -+ vp++; -+ } -+ if (cis[i + 4] != 0xff) { -+ vp += sprintf(vp, "wl0gpio3=%d", cis[i + 4]); -+ vp++; -+ } -+ break; -+ -+ case HNBU_CCODE: -+ ASSERT(sromrev > 1); -+ vp += sprintf(vp, "ccode=%c%c", cis[i + 1], cis[i + 2]); -+ vp++; -+ vp += sprintf(vp, "cctl=0x%x", cis[i + 3]); -+ vp++; -+ break; -+ -+ case HNBU_CCKPO: -+ ASSERT(sromrev > 2); -+ vp += sprintf(vp, "cckpo=0x%x", (cis[i + 2] << 8) | cis[i + 1]); -+ vp++; -+ break; -+ -+ case HNBU_OFDMPO: -+ ASSERT(sromrev > 2); -+ vp += sprintf(vp, "ofdmpo=0x%x", (cis[i + 4] << 24) | -+ (cis[i + 3] << 16) | (cis[i + 2] << 8) | cis[i + 1]); -+ vp++; -+ break; -+ } -+ break; -+ -+ } -+ i += tlen; -+ } while (tup != 0xff); -+ -+ /* Set the srom version */ -+ vp += sprintf(vp, "sromrev=%d", sromrev); -+ vp++; -+ -+ /* if there is no antenna gain field, set default */ -+ if (ag_init == FALSE) { -+ ASSERT(sromrev == 1); -+ vp += sprintf(vp, "ag0=%d", 0xff); -+ vp++; -+ } -+ -+ /* final nullbyte terminator */ -+ *vp++ = '\0'; -+ varsize = (uint)(vp - base); -+ -+ ASSERT((vp - base) < VARS_MAX); -+ -+ if (varsize == VARS_MAX) { -+ *vars = base; -+ } else { -+ vp = MALLOC(osh, varsize); -+ ASSERT(vp); -+ if (vp) -+ bcopy(base, vp, varsize); -+ MFREE(osh, base, VARS_MAX); -+ *vars = vp; -+ if (!vp) { -+ *count = 0; -+ return -2; -+ } -+ } -+ *count = varsize; -+ -+ return (0); -+} -+ -+ -+/* set PCMCIA sprom command register */ -+static int -+sprom_cmd_pcmcia(osl_t *osh, uint8 cmd) -+{ -+ uint8 status = 0; -+ uint wait_cnt = 1000; -+ -+ /* write sprom command register */ -+ OSL_PCMCIA_WRITE_ATTR(osh, SROM_CS, &cmd, 1); -+ -+ /* wait status */ -+ while (wait_cnt--) { -+ OSL_PCMCIA_READ_ATTR(osh, SROM_CS, &status, 1); -+ if (status & SROM_DONE) -+ return 0; -+ } -+ -+ return 1; -+} -+ -+/* read a word from the PCMCIA srom */ -+static int -+sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data) -+{ -+ uint8 addr_l, addr_h, data_l, data_h; -+ -+ addr_l = (uint8)((addr * 2) & 0xff); -+ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); -+ -+ /* set address */ -+ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); -+ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); -+ -+ /* do read */ -+ if (sprom_cmd_pcmcia(osh, SROM_READ)) -+ return 1; -+ -+ /* read data */ -+ data_h = data_l = 0; -+ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAH, &data_h, 1); -+ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAL, &data_l, 1); -+ -+ *data = (data_h << 8) | data_l; -+ return 0; -+} -+ -+/* write a word to the PCMCIA srom */ -+static int -+sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data) -+{ -+ uint8 addr_l, addr_h, data_l, data_h; -+ -+ addr_l = (uint8)((addr * 2) & 0xff); -+ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); -+ data_l = (uint8)(data & 0xff); -+ data_h = (uint8)((data >> 8) & 0xff); -+ -+ /* set address */ -+ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); -+ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); -+ -+ /* write data */ -+ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAH, &data_h, 1); -+ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAL, &data_l, 1); -+ -+ /* do write */ -+ return sprom_cmd_pcmcia(osh, SROM_WRITE); -+} -+ -+/* -+ * Read in and validate sprom. -+ * Return 0 on success, nonzero on error. -+ */ -+static int -+sprom_read_pci(uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc) -+{ -+ int err = 0; -+ uint i; -+ -+ /* read the sprom */ -+ for (i = 0; i < nwords; i++) -+ buf[i] = R_REG(&sprom[wordoff + i]); -+ -+ if (check_crc) { -+ /* fixup the endianness so crc8 will pass */ -+ htol16_buf(buf, nwords * 2); -+ if (hndcrc8((uint8*)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) -+ err = 1; -+ /* now correct the endianness of the byte array */ -+ ltoh16_buf(buf, nwords * 2); -+ } -+ -+ return err; -+} -+ -+/* -+* Create variable table from memory. -+* Return 0 on success, nonzero on error. -+*/ -+static int -+initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count) -+{ -+ int c = (int)(end - start); -+ -+ /* do it only when there is more than just the null string */ -+ if (c > 1) { -+ char *vp = MALLOC(osh, c); -+ ASSERT(vp); -+ if (!vp) -+ return BCME_NOMEM; -+ bcopy(start, vp, c); -+ *vars = vp; -+ *count = c; -+ } -+ else { -+ *vars = NULL; -+ *count = 0; -+ } -+ -+ return 0; -+} -+ -+/* -+* Find variables with from flash. 'base' points to the beginning -+* of the table upon enter and to the end of the table upon exit when success. -+* Return 0 on success, nonzero on error. -+*/ -+static int -+initvars_flash(osl_t *osh, char **base, int size, char *devpath) -+{ -+ char *vp = *base; -+ char *flash; -+ int err; -+ char *s; -+ uint l, dl, copy_len; -+ -+ /* allocate memory and read in flash */ -+ if (!(flash = MALLOC(osh, NVRAM_SPACE))) -+ return BCME_NOMEM; -+ if ((err = BCMINIT(nvram_getall)(flash, NVRAM_SPACE))) -+ goto exit; -+ -+ /* grab vars with the prefix in name */ -+ dl = strlen(devpath); -+ for (s = flash; s && *s; s += l + 1) { -+ l = strlen(s); -+ -+ /* skip non-matching variable */ -+ if (strncmp(s, devpath, dl)) -+ continue; -+ -+ /* is there enough room to copy? */ -+ copy_len = l - dl + 1; -+ if (size < (int)copy_len) { -+ err = BCME_BUFTOOSHORT; -+ goto exit; -+ } -+ -+ /* no prefix, just the name=value */ -+ strcpy(vp, &s[dl]); -+ vp += copy_len; -+ size -= copy_len; -+ } -+ -+ /* add null string as terminator */ -+ if (size < 1) { -+ err = BCME_BUFTOOSHORT; -+ goto exit; -+ } -+ *vp++ = '\0'; -+ -+ *base = vp; -+ -+exit: MFREE(osh, flash, NVRAM_SPACE); -+ return err; -+} -+ -+/* -+ * Initialize nonvolatile variable table from flash. -+ * Return 0 on success, nonzero on error. -+ */ -+static int -+initvars_flash_sb(void *sbh, char **vars, int *count) -+{ -+ osl_t *osh = sb_osh(sbh); -+ char devpath[SB_DEVPATH_BUFSZ]; -+ char *vp, *base; -+ int err; -+ -+ ASSERT(vars); -+ ASSERT(count); -+ -+ if ((err = sb_devpath(sbh, devpath, sizeof(devpath)))) -+ return err; -+ -+ base = vp = MALLOC(osh, VARS_MAX); -+ ASSERT(vp); -+ if (!vp) -+ return BCME_NOMEM; -+ -+ if ((err = initvars_flash(osh, &vp, VARS_MAX, devpath))) -+ goto err; -+ -+ err = initvars_table(osh, base, vp, vars, count); -+ -+err: MFREE(osh, base, VARS_MAX); -+ return err; -+} -+ -+/* -+ * Initialize nonvolatile variable table from sprom. -+ * Return 0 on success, nonzero on error. -+ */ -+static int -+initvars_srom_pci(void *sbh, void *curmap, char **vars, int *count) -+{ -+ uint16 w, b[64]; -+ uint8 sromrev; -+ struct ether_addr ea; -+ char eabuf[32]; -+ uint32 w32; -+ int woff, i; -+ char *vp, *base; -+ osl_t *osh = sb_osh(sbh); -+ bool flash = FALSE; -+ char name[SB_DEVPATH_BUFSZ+16], *value; -+ char devpath[SB_DEVPATH_BUFSZ]; -+ int err; -+ -+ /* -+ * Apply CRC over SROM content regardless SROM is present or not, -+ * and use variable sromrev's existance in flash to decide -+ * if we should return an error when CRC fails or read SROM variables -+ * from flash. -+ */ -+ if (sprom_read_pci((void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b, sizeof(b)/sizeof(b[0]), TRUE)) { -+ if ((err = sb_devpath(sbh, devpath, sizeof(devpath)))) -+ return err; -+ sprintf(name, "%ssromrev", devpath); -+ if (!(value = getvar(NULL, name))) -+ return (-1); -+ sromrev = (uint8)bcm_strtoul(value, NULL, 0); -+ flash = TRUE; -+ } -+ /* srom is good */ -+ else { -+ /* top word of sprom contains version and crc8 */ -+ sromrev = b[63] & 0xff; -+ /* bcm4401 sroms misprogrammed */ -+ if (sromrev == 0x10) -+ sromrev = 1; -+ } -+ -+ /* srom version check */ -+ if (sromrev > 3) -+ return (-2); -+ -+ ASSERT(vars); -+ ASSERT(count); -+ -+ base = vp = MALLOC(osh, VARS_MAX); -+ ASSERT(vp); -+ if (!vp) -+ return -2; -+ -+ /* read variables from flash */ -+ if (flash) { -+ if ((err = initvars_flash(osh, &vp, VARS_MAX, devpath))) -+ goto err; -+ goto done; -+ } -+ -+ vp += sprintf(vp, "sromrev=%d", sromrev); -+ vp++; -+ -+ if (sromrev >= 3) { -+ /* New section takes over the 3th hardware function space */ -+ -+ /* Words 22+23 are 11a (mid) ofdm power offsets */ -+ w32 = ((uint32)b[23] << 16) | b[22]; -+ vp += sprintf(vp, "ofdmapo=%d", w32); -+ vp++; -+ -+ /* Words 24+25 are 11a (low) ofdm power offsets */ -+ w32 = ((uint32)b[25] << 16) | b[24]; -+ vp += sprintf(vp, "ofdmalpo=%d", w32); -+ vp++; -+ -+ /* Words 26+27 are 11a (high) ofdm power offsets */ -+ w32 = ((uint32)b[27] << 16) | b[26]; -+ vp += sprintf(vp, "ofdmahpo=%d", w32); -+ vp++; -+ -+ /*GPIO LED Powersave duty cycle (oncount >> 24) (offcount >> 8)*/ -+ w32 = ((uint32)b[43] << 24) | ((uint32)b[42] << 8); -+ vp += sprintf(vp, "gpiotimerval=%d", w32); -+ -+ /*GPIO LED Powersave duty cycle (oncount >> 24) (offcount >> 8)*/ -+ w32 = ((uint32)((unsigned char)(b[21] >> 8) & 0xFF) << 24) | /* oncount*/ -+ ((uint32)((unsigned char)(b[21] & 0xFF)) << 8); /* offcount */ -+ vp += sprintf(vp, "gpiotimerval=%d", w32); -+ -+ vp++; -+ } -+ -+ if (sromrev >= 2) { -+ /* New section takes over the 4th hardware function space */ -+ -+ /* Word 29 is max power 11a high/low */ -+ w = b[29]; -+ vp += sprintf(vp, "pa1himaxpwr=%d", w & 0xff); -+ vp++; -+ vp += sprintf(vp, "pa1lomaxpwr=%d", (w >> 8) & 0xff); -+ vp++; -+ -+ /* Words 30-32 set the 11alow pa settings, -+ * 33-35 are the 11ahigh ones. -+ */ -+ for (i = 0; i < 3; i++) { -+ vp += sprintf(vp, "pa1lob%d=%d", i, b[30 + i]); -+ vp++; -+ vp += sprintf(vp, "pa1hib%d=%d", i, b[33 + i]); -+ vp++; -+ } -+ w = b[59]; -+ if (w == 0) -+ vp += sprintf(vp, "ccode="); -+ else -+ vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff)); -+ vp++; -+ -+ } -+ -+ /* parameter section of sprom starts at byte offset 72 */ -+ woff = 72/2; -+ -+ /* first 6 bytes are il0macaddr */ -+ ea.octet[0] = (b[woff] >> 8) & 0xff; -+ ea.octet[1] = b[woff] & 0xff; -+ ea.octet[2] = (b[woff+1] >> 8) & 0xff; -+ ea.octet[3] = b[woff+1] & 0xff; -+ ea.octet[4] = (b[woff+2] >> 8) & 0xff; -+ ea.octet[5] = b[woff+2] & 0xff; -+ woff += 3; -+ bcm_ether_ntoa((uchar*)&ea, eabuf); -+ vp += sprintf(vp, "il0macaddr=%s", eabuf); -+ vp++; -+ -+ /* next 6 bytes are et0macaddr */ -+ ea.octet[0] = (b[woff] >> 8) & 0xff; -+ ea.octet[1] = b[woff] & 0xff; -+ ea.octet[2] = (b[woff+1] >> 8) & 0xff; -+ ea.octet[3] = b[woff+1] & 0xff; -+ ea.octet[4] = (b[woff+2] >> 8) & 0xff; -+ ea.octet[5] = b[woff+2] & 0xff; -+ woff += 3; -+ bcm_ether_ntoa((uchar*)&ea, eabuf); -+ vp += sprintf(vp, "et0macaddr=%s", eabuf); -+ vp++; -+ -+ /* next 6 bytes are et1macaddr */ -+ ea.octet[0] = (b[woff] >> 8) & 0xff; -+ ea.octet[1] = b[woff] & 0xff; -+ ea.octet[2] = (b[woff+1] >> 8) & 0xff; -+ ea.octet[3] = b[woff+1] & 0xff; -+ ea.octet[4] = (b[woff+2] >> 8) & 0xff; -+ ea.octet[5] = b[woff+2] & 0xff; -+ woff += 3; -+ bcm_ether_ntoa((uchar*)&ea, eabuf); -+ vp += sprintf(vp, "et1macaddr=%s", eabuf); -+ vp++; -+ -+ /* -+ * Enet phy settings one or two singles or a dual -+ * Bits 4-0 : MII address for enet0 (0x1f for not there) -+ * Bits 9-5 : MII address for enet1 (0x1f for not there) -+ * Bit 14 : Mdio for enet0 -+ * Bit 15 : Mdio for enet1 -+ */ -+ w = b[woff]; -+ vp += sprintf(vp, "et0phyaddr=%d", (w & 0x1f)); -+ vp++; -+ vp += sprintf(vp, "et1phyaddr=%d", ((w >> 5) & 0x1f)); -+ vp++; -+ vp += sprintf(vp, "et0mdcport=%d", ((w >> 14) & 0x1)); -+ vp++; -+ vp += sprintf(vp, "et1mdcport=%d", ((w >> 15) & 0x1)); -+ vp++; -+ -+ /* Word 46 has board rev, antennas 0/1 & Country code/control */ -+ w = b[46]; -+ vp += sprintf(vp, "boardrev=%d", w & 0xff); -+ vp++; -+ -+ if (sromrev > 1) -+ vp += sprintf(vp, "cctl=%d", (w >> 8) & 0xf); -+ else -+ vp += sprintf(vp, "cc=%d", (w >> 8) & 0xf); -+ vp++; -+ -+ vp += sprintf(vp, "aa0=%d", (w >> 12) & 0x3); -+ vp++; -+ -+ vp += sprintf(vp, "aa1=%d", (w >> 14) & 0x3); -+ vp++; -+ -+ /* Words 47-49 set the (wl) pa settings */ -+ woff = 47; -+ -+ for (i = 0; i < 3; i++) { -+ vp += sprintf(vp, "pa0b%d=%d", i, b[woff+i]); -+ vp++; -+ vp += sprintf(vp, "pa1b%d=%d", i, b[woff+i+6]); -+ vp++; -+ } -+ -+ /* -+ * Words 50-51 set the customer-configured wl led behavior. -+ * 8 bits/gpio pin. High bit: activehi=0, activelo=1; -+ * LED behavior values defined in wlioctl.h . -+ */ -+ w = b[50]; -+ if ((w != 0) && (w != 0xffff)) { -+ /* gpio0 */ -+ vp += sprintf(vp, "wl0gpio0=%d", (w & 0xff)); -+ vp++; -+ -+ /* gpio1 */ -+ vp += sprintf(vp, "wl0gpio1=%d", (w >> 8) & 0xff); -+ vp++; -+ } -+ w = b[51]; -+ if ((w != 0) && (w != 0xffff)) { -+ /* gpio2 */ -+ vp += sprintf(vp, "wl0gpio2=%d", w & 0xff); -+ vp++; -+ -+ /* gpio3 */ -+ vp += sprintf(vp, "wl0gpio3=%d", (w >> 8) & 0xff); -+ vp++; -+ } -+ -+ /* Word 52 is max power 0/1 */ -+ w = b[52]; -+ vp += sprintf(vp, "pa0maxpwr=%d", w & 0xff); -+ vp++; -+ vp += sprintf(vp, "pa1maxpwr=%d", (w >> 8) & 0xff); -+ vp++; -+ -+ /* Word 56 is idle tssi target 0/1 */ -+ w = b[56]; -+ vp += sprintf(vp, "pa0itssit=%d", w & 0xff); -+ vp++; -+ vp += sprintf(vp, "pa1itssit=%d", (w >> 8) & 0xff); -+ vp++; -+ -+ /* Word 57 is boardflags, if not programmed make it zero */ -+ w32 = (uint32)b[57]; -+ if (w32 == 0xffff) w32 = 0; -+ if (sromrev > 1) { -+ /* Word 28 is the high bits of boardflags */ -+ w32 |= (uint32)b[28] << 16; -+ } -+ vp += sprintf(vp, "boardflags=%d", w32); -+ vp++; -+ -+ /* Word 58 is antenna gain 0/1 */ -+ w = b[58]; -+ vp += sprintf(vp, "ag0=%d", w & 0xff); -+ vp++; -+ -+ vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff); -+ vp++; -+ -+ if (sromrev == 1) { -+ /* set the oem string */ -+ vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x", -+ ((b[59] >> 8) & 0xff), (b[59] & 0xff), -+ ((b[60] >> 8) & 0xff), (b[60] & 0xff), -+ ((b[61] >> 8) & 0xff), (b[61] & 0xff), -+ ((b[62] >> 8) & 0xff), (b[62] & 0xff)); -+ vp++; -+ } else if (sromrev == 2) { -+ /* Word 60 OFDM tx power offset from CCK level */ -+ /* OFDM Power Offset - opo */ -+ vp += sprintf(vp, "opo=%d", b[60] & 0xff); -+ vp++; -+ } else { -+ /* Word 60: cck power offsets */ -+ vp += sprintf(vp, "cckpo=%d", b[60]); -+ vp++; -+ -+ /* Words 61+62: 11g ofdm power offsets */ -+ w32 = ((uint32)b[62] << 16) | b[61]; -+ vp += sprintf(vp, "ofdmgpo=%d", w32); -+ vp++; -+ } -+ -+ /* final nullbyte terminator */ -+ *vp++ = '\0'; -+ -+ ASSERT((vp - base) <= VARS_MAX); -+ -+done: err = initvars_table(osh, base, vp, vars, count); -+ -+err: MFREE(osh, base, VARS_MAX); -+ return err; -+} -+ -+/* -+ * Read the cis and call parsecis to initialize the vars. -+ * Return 0 on success, nonzero on error. -+ */ -+static int -+initvars_cis_pcmcia(void *sbh, osl_t *osh, char **vars, int *count) -+{ -+ uint8 *cis = NULL; -+ int rc; -+ uint data_sz; -+ -+ data_sz = (sb_pcmciarev(sbh) == 1) ? (SPROM_SIZE * 2) : CIS_SIZE; -+ -+ if ((cis = MALLOC(osh, data_sz)) == NULL) -+ return (-2); -+ -+ if (sb_pcmciarev(sbh) == 1) { -+ if (srom_read(PCMCIA_BUS, (void *)NULL, osh, 0, data_sz, (uint16 *)cis)) { -+ MFREE(osh, cis, data_sz); -+ return (-1); -+ } -+ /* fix up endianess for 16-bit data vs 8-bit parsing */ -+ ltoh16_buf((uint16 *)cis, data_sz); -+ } else -+ OSL_PCMCIA_READ_ATTR(osh, 0, cis, data_sz); -+ -+ rc = srom_parsecis(osh, cis, vars, count); -+ -+ MFREE(osh, cis, data_sz); -+ -+ return (rc); -+} -+ -diff -Naur linux.old/drivers/net/hnd/bcmutils.c linux.dev/drivers/net/hnd/bcmutils.c ---- linux.old/drivers/net/hnd/bcmutils.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/hnd/bcmutils.c 2006-04-06 16:05:56.000000000 +0200 -@@ -0,0 +1,875 @@ -+/* -+ * Misc useful OS-independent routines. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ -+ -+#include -+#ifdef BCMDRIVER -+#include -+#include -+#include -+#else -+#include -+#include -+#endif -+#include -+#include -+#include -+ -+#ifdef BCMDRIVER -+unsigned char bcm_ctype[] = { -+ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ -+ _BCM_C,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C,_BCM_C, /* 8-15 */ -+ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ -+ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ -+ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ -+ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ -+ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ -+ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ -+ _BCM_P,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U, /* 64-71 */ -+ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ -+ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ -+ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ -+ _BCM_P,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L, /* 96-103 */ -+ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ -+ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ -+ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ -+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ -+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ -+ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 160-175 */ -+ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 176-191 */ -+ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 192-207 */ -+ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_L, /* 208-223 */ -+ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 224-239 */ -+ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L /* 240-255 */ -+}; -+ -+uchar -+bcm_toupper(uchar c) -+{ -+ if (bcm_islower(c)) -+ c -= 'a'-'A'; -+ return (c); -+} -+ -+ulong -+bcm_strtoul(char *cp, char **endp, uint base) -+{ -+ ulong result, value; -+ bool minus; -+ -+ minus = FALSE; -+ -+ while (bcm_isspace(*cp)) -+ cp++; -+ -+ if (cp[0] == '+') -+ cp++; -+ else if (cp[0] == '-') { -+ minus = TRUE; -+ cp++; -+ } -+ -+ if (base == 0) { -+ if (cp[0] == '0') { -+ if ((cp[1] == 'x') || (cp[1] == 'X')) { -+ base = 16; -+ cp = &cp[2]; -+ } else { -+ base = 8; -+ cp = &cp[1]; -+ } -+ } else -+ base = 10; -+ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { -+ cp = &cp[2]; -+ } -+ -+ result = 0; -+ -+ while (bcm_isxdigit(*cp) && -+ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { -+ result = result*base + value; -+ cp++; -+ } -+ -+ if (minus) -+ result = (ulong)(result * -1); -+ -+ if (endp) -+ *endp = (char *)cp; -+ -+ return (result); -+} -+ -+uint -+bcm_atoi(char *s) -+{ -+ uint n; -+ -+ n = 0; -+ -+ while (bcm_isdigit(*s)) -+ n = (n * 10) + *s++ - '0'; -+ return (n); -+} -+ -+/* return pointer to location of substring 'needle' in 'haystack' */ -+char* -+bcmstrstr(char *haystack, char *needle) -+{ -+ int len, nlen; -+ int i; -+ -+ if ((haystack == NULL) || (needle == NULL)) -+ return (haystack); -+ -+ nlen = strlen(needle); -+ len = strlen(haystack) - nlen + 1; -+ -+ for (i = 0; i < len; i++) -+ if (bcmp(needle, &haystack[i], nlen) == 0) -+ return (&haystack[i]); -+ return (NULL); -+} -+ -+char* -+bcmstrcat(char *dest, const char *src) -+{ -+ strcpy(&dest[strlen(dest)], src); -+ return (dest); -+} -+ -+#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) -+/* registry routine buffer preparation utility functions: -+ * parameter order is like strncpy, but returns count -+ * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) -+ */ -+ulong -+wchar2ascii( -+ char *abuf, -+ ushort *wbuf, -+ ushort wbuflen, -+ ulong abuflen -+) -+{ -+ ulong copyct = 1; -+ ushort i; -+ -+ if (abuflen == 0) -+ return 0; -+ -+ /* wbuflen is in bytes */ -+ wbuflen /= sizeof(ushort); -+ -+ for (i = 0; i < wbuflen; ++i) { -+ if (--abuflen == 0) -+ break; -+ *abuf++ = (char) *wbuf++; -+ ++copyct; -+ } -+ *abuf = '\0'; -+ -+ return copyct; -+} -+#endif -+ -+char* -+bcm_ether_ntoa(char *ea, char *buf) -+{ -+ sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x", -+ (uchar)ea[0]&0xff, (uchar)ea[1]&0xff, (uchar)ea[2]&0xff, -+ (uchar)ea[3]&0xff, (uchar)ea[4]&0xff, (uchar)ea[5]&0xff); -+ return (buf); -+} -+ -+/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ -+int -+bcm_ether_atoe(char *p, char *ea) -+{ -+ int i = 0; -+ -+ for (;;) { -+ ea[i++] = (char) bcm_strtoul(p, &p, 16); -+ if (!*p++ || i == 6) -+ break; -+ } -+ -+ return (i == 6); -+} -+ -+void -+bcm_mdelay(uint ms) -+{ -+ uint i; -+ -+ for (i = 0; i < ms; i++) { -+ OSL_DELAY(1000); -+ } -+} -+ -+/* -+ * Search the name=value vars for a specific one and return its value. -+ * Returns NULL if not found. -+ */ -+char* -+getvar(char *vars, char *name) -+{ -+ char *s; -+ int len; -+ -+ len = strlen(name); -+ -+ /* first look in vars[] */ -+ for (s = vars; s && *s; ) { -+ if ((bcmp(s, name, len) == 0) && (s[len] == '=')) -+ return (&s[len+1]); -+ -+ while (*s++) -+ ; -+ } -+ -+ /* then query nvram */ -+ return (BCMINIT(nvram_get)(name)); -+} -+ -+/* -+ * Search the vars for a specific one and return its value as -+ * an integer. Returns 0 if not found. -+ */ -+int -+getintvar(char *vars, char *name) -+{ -+ char *val; -+ -+ if ((val = getvar(vars, name)) == NULL) -+ return (0); -+ -+ return (bcm_strtoul(val, NULL, 0)); -+} -+ -+ -+/* Search for token in comma separated token-string */ -+static int -+findmatch(char *string, char *name) -+{ -+ uint len; -+ char *c; -+ -+ len = strlen(name); -+ while ((c = strchr(string, ',')) != NULL) { -+ if (len == (uint)(c - string) && !strncmp(string, name, len)) -+ return 1; -+ string = c + 1; -+ } -+ -+ return (!strcmp(string, name)); -+} -+ -+/* Return gpio pin number assigned to the named pin */ -+/* -+* Variable should be in format: -+* -+* gpio=pin_name,pin_name -+* -+* This format allows multiple features to share the gpio with mutual -+* understanding. -+* -+* 'def_pin' is returned if a specific gpio is not defined for the requested functionality -+* and if def_pin is not used by others. -+*/ -+uint -+getgpiopin(char *vars, char *pin_name, uint def_pin) -+{ -+ char name[] = "gpioXXXX"; -+ char *val; -+ uint pin; -+ -+ /* Go thru all possibilities till a match in pin name */ -+ for (pin = 0; pin < GPIO_NUMPINS; pin ++) { -+ sprintf(name, "gpio%d", pin); -+ val = getvar(vars, name); -+ if (val && findmatch(val, pin_name)) -+ return pin; -+ } -+ -+ if (def_pin != GPIO_PIN_NOTDEFINED) { -+ /* make sure the default pin is not used by someone else */ -+ sprintf(name, "gpio%d", def_pin); -+ if (getvar(vars, name)) { -+ def_pin = GPIO_PIN_NOTDEFINED; -+ } -+ } -+ -+ return def_pin; -+} -+ -+ -+static char bcm_undeferrstr[BCME_STRLEN]; -+ -+static const char *bcmerrorstrtable[] = \ -+{ "OK", /* 0 */ -+ "Undefined error", /* BCME_ERROR */ -+ "Bad Argument", /* BCME_BADARG*/ -+ "Bad Option", /* BCME_BADOPTION*/ -+ "Not up", /* BCME_NOTUP */ -+ "Not down", /* BCME_NOTDOWN */ -+ "Not AP", /* BCME_NOTAP */ -+ "Not STA", /* BCME_NOTSTA */ -+ "Bad Key Index", /* BCME_BADKEYIDX */ -+ "Radio Off", /* BCME_RADIOOFF */ -+ "Not band locked", /* BCME_NOTBANDLOCKED */ -+ "No clock", /* BCME_NOCLK */ -+ "Bad Rate valueset", /* BCME_BADRATESET */ -+ "Bad Band", /* BCME_BADBAND */ -+ "Buffer too short", /* BCME_BUFTOOSHORT */ -+ "Buffer too length", /* BCME_BUFTOOLONG */ -+ "Busy", /* BCME_BUSY */ -+ "Not Associated", /* BCME_NOTASSOCIATED */ -+ "Bad SSID len", /* BCME_BADSSIDLEN */ -+ "Out of Range Channel", /* BCME_OUTOFRANGECHAN */ -+ "Bad Channel", /* BCME_BADCHAN */ -+ "Bad Address", /* BCME_BADADDR */ -+ "Not Enough Resources", /* BCME_NORESOURCE */ -+ "Unsupported", /* BCME_UNSUPPORTED */ -+ "Bad length", /* BCME_BADLENGTH */ -+ "Not Ready", /* BCME_NOTREADY */ -+ "Not Permitted", /* BCME_EPERM */ -+ "No Memory", /* BCME_NOMEM */ -+ "Associated", /* BCME_ASSOCIATED */ -+ "Not In Range", /* BCME_RANGE */ -+ "Not Found" /* BCME_NOTFOUND */ -+ }; -+ -+/* Convert the Error codes into related Error strings */ -+const char * -+bcmerrorstr(int bcmerror) -+{ -+ int abs_bcmerror; -+ -+ abs_bcmerror = ABS(bcmerror); -+ -+ /* check if someone added a bcmerror code but forgot to add errorstring */ -+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); -+ if ( (bcmerror > 0) || (abs_bcmerror > ABS(BCME_LAST))) { -+ sprintf(bcm_undeferrstr, "undefined Error %d", bcmerror); -+ return bcm_undeferrstr; -+ } -+ -+ ASSERT((strlen((char*)bcmerrorstrtable[abs_bcmerror])) < BCME_STRLEN); -+ -+ return bcmerrorstrtable[abs_bcmerror]; -+} -+#endif /* #ifdef BCMDRIVER */ -+ -+ -+/******************************************************************************* -+ * crc8 -+ * -+ * Computes a crc8 over the input data using the polynomial: -+ * -+ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 -+ * -+ * The caller provides the initial value (either CRC8_INIT_VALUE -+ * or the previous returned value) to allow for processing of -+ * discontiguous blocks of data. When generating the CRC the -+ * caller is responsible for complementing the final return value -+ * and inserting it into the byte stream. When checking, a final -+ * return value of CRC8_GOOD_VALUE indicates a valid CRC. -+ * -+ * Reference: Dallas Semiconductor Application Note 27 -+ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", -+ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., -+ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt -+ * -+ ******************************************************************************/ -+ -+static uint8 crc8_table[256] = { -+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, -+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, -+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, -+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, -+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, -+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, -+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, -+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, -+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, -+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, -+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, -+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, -+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, -+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, -+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, -+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, -+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, -+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, -+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, -+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, -+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, -+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, -+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, -+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, -+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, -+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, -+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, -+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, -+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, -+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, -+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, -+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F -+}; -+ -+#define CRC_INNER_LOOP(n, c, x) \ -+ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] -+ -+uint8 -+hndcrc8( -+ uint8 *pdata, /* pointer to array of data to process */ -+ uint nbytes, /* number of input data bytes to process */ -+ uint8 crc /* either CRC8_INIT_VALUE or previous return value */ -+) -+{ -+ /* hard code the crc loop instead of using CRC_INNER_LOOP macro -+ * to avoid the undefined and unnecessary (uint8 >> 8) operation. */ -+ while (nbytes-- > 0) -+ crc = crc8_table[(crc ^ *pdata++) & 0xff]; -+ -+ return crc; -+} -+ -+/******************************************************************************* -+ * crc16 -+ * -+ * Computes a crc16 over the input data using the polynomial: -+ * -+ * x^16 + x^12 +x^5 + 1 -+ * -+ * The caller provides the initial value (either CRC16_INIT_VALUE -+ * or the previous returned value) to allow for processing of -+ * discontiguous blocks of data. When generating the CRC the -+ * caller is responsible for complementing the final return value -+ * and inserting it into the byte stream. When checking, a final -+ * return value of CRC16_GOOD_VALUE indicates a valid CRC. -+ * -+ * Reference: Dallas Semiconductor Application Note 27 -+ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", -+ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., -+ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt -+ * -+ ******************************************************************************/ -+ -+static uint16 crc16_table[256] = { -+ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, -+ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, -+ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, -+ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, -+ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, -+ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, -+ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, -+ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, -+ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, -+ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, -+ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, -+ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, -+ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, -+ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, -+ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, -+ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, -+ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, -+ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, -+ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, -+ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, -+ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, -+ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, -+ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, -+ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, -+ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, -+ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, -+ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, -+ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, -+ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, -+ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, -+ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, -+ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 -+}; -+ -+uint16 -+hndcrc16( -+ uint8 *pdata, /* pointer to array of data to process */ -+ uint nbytes, /* number of input data bytes to process */ -+ uint16 crc /* either CRC16_INIT_VALUE or previous return value */ -+) -+{ -+ while (nbytes-- > 0) -+ CRC_INNER_LOOP(16, crc, *pdata++); -+ return crc; -+} -+ -+static uint32 crc32_table[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 -+}; -+ -+uint32 -+hndcrc32( -+ uint8 *pdata, /* pointer to array of data to process */ -+ uint nbytes, /* number of input data bytes to process */ -+ uint32 crc /* either CRC32_INIT_VALUE or previous return value */ -+) -+{ -+ uint8 *pend; -+#ifdef __mips__ -+ uint8 tmp[4]; -+ ulong *tptr = (ulong *)tmp; -+ -+ /* in case the beginning of the buffer isn't aligned */ -+ pend = (uint8 *)((uint)(pdata + 3) & 0xfffffffc); -+ nbytes -= (pend - pdata); -+ while (pdata < pend) -+ CRC_INNER_LOOP(32, crc, *pdata++); -+ -+ /* handle bulk of data as 32-bit words */ -+ pend = pdata + (nbytes & 0xfffffffc); -+ while (pdata < pend) { -+ tptr = *((ulong *) pdata); -+ *((ulong *) pdata) += 1; -+ CRC_INNER_LOOP(32, crc, tmp[0]); -+ CRC_INNER_LOOP(32, crc, tmp[1]); -+ CRC_INNER_LOOP(32, crc, tmp[2]); -+ CRC_INNER_LOOP(32, crc, tmp[3]); -+ } -+ -+ /* 1-3 bytes at end of buffer */ -+ pend = pdata + (nbytes & 0x03); -+ while (pdata < pend) -+ CRC_INNER_LOOP(32, crc, *pdata++); -+#else -+ pend = pdata + nbytes; -+ while (pdata < pend) -+ CRC_INNER_LOOP(32, crc, *pdata++); -+#endif -+ -+ return crc; -+} -+ -+#ifdef notdef -+#define CLEN 1499 -+#define CBUFSIZ (CLEN+4) -+#define CNBUFS 5 -+ -+void testcrc32(void) -+{ -+ uint j,k,l; -+ uint8 *buf; -+ uint len[CNBUFS]; -+ uint32 crcr; -+ uint32 crc32tv[CNBUFS] = -+ {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; -+ -+ ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); -+ -+ /* step through all possible alignments */ -+ for (l=0;l<=4;l++) { -+ for (j=0; jlen; -+ elt = (bcm_tlv_t*)(elt->data + len); -+ *buflen -= (2 + len); -+ -+ /* validate next elt */ -+ if (!bcm_valid_tlv(elt, *buflen)) -+ return NULL; -+ -+ return elt; -+} -+ -+/* -+ * Traverse a string of 1-byte tag/1-byte length/variable-length value -+ * triples, returning a pointer to the substring whose first element -+ * matches tag -+ */ -+bcm_tlv_t * -+bcm_parse_tlvs(void *buf, int buflen, uint key) -+{ -+ bcm_tlv_t *elt; -+ int totlen; -+ -+ elt = (bcm_tlv_t*)buf; -+ totlen = buflen; -+ -+ /* find tagged parameter */ -+ while (totlen >= 2) { -+ int len = elt->len; -+ -+ /* validate remaining totlen */ -+ if ((elt->id == key) && (totlen >= (len + 2))) -+ return (elt); -+ -+ elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); -+ totlen -= (len + 2); -+ } -+ -+ return NULL; -+} -+ -+/* -+ * Traverse a string of 1-byte tag/1-byte length/variable-length value -+ * triples, returning a pointer to the substring whose first element -+ * matches tag. Stop parsing when we see an element whose ID is greater -+ * than the target key. -+ */ -+bcm_tlv_t * -+bcm_parse_ordered_tlvs(void *buf, int buflen, uint key) -+{ -+ bcm_tlv_t *elt; -+ int totlen; -+ -+ elt = (bcm_tlv_t*)buf; -+ totlen = buflen; -+ -+ /* find tagged parameter */ -+ while (totlen >= 2) { -+ uint id = elt->id; -+ int len = elt->len; -+ -+ /* Punt if we start seeing IDs > than target key */ -+ if (id > key) -+ return(NULL); -+ -+ /* validate remaining totlen */ -+ if ((id == key) && (totlen >= (len + 2))) -+ return (elt); -+ -+ elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); -+ totlen -= (len + 2); -+ } -+ return NULL; -+} -+/* routine to dump fields in a fileddesc structure */ -+ -+uint -+bcmdumpfields(readreg_rtn read_rtn, void *arg0, void *arg1, struct fielddesc *fielddesc_array, char *buf, uint32 bufsize) -+{ -+ uint filled_len; -+ uint len; -+ struct fielddesc *cur_ptr; -+ -+ filled_len = 0; -+ cur_ptr = fielddesc_array; -+ -+ while (bufsize > (filled_len + 64)) { -+ if (cur_ptr->nameandfmt == NULL) -+ break; -+ len = sprintf(buf, cur_ptr->nameandfmt, read_rtn(arg0, arg1, cur_ptr->offset)); -+ buf += len; -+ filled_len += len; -+ cur_ptr++; -+ } -+ return filled_len; -+} -+ -+uint -+bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) -+{ -+ uint len; -+ -+ len = strlen(name) + 1; -+ -+ if ((len + datalen) > buflen) -+ return 0; -+ -+ strcpy(buf, name); -+ -+ /* append data onto the end of the name string */ -+ memcpy(&buf[len], data, datalen); -+ len += datalen; -+ -+ return len; -+} -+ -+/* Quarter dBm units to mW -+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 -+ * Table is offset so the last entry is largest mW value that fits in -+ * a uint16. -+ */ -+ -+#define QDBM_OFFSET 153 -+#define QDBM_TABLE_LEN 40 -+ -+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. -+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 -+ */ -+#define QDBM_TABLE_LOW_BOUND 6493 -+ -+/* Largest mW value that will round down to the last table entry, -+ * QDBM_OFFSET + QDBM_TABLE_LEN-1. -+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. -+ */ -+#define QDBM_TABLE_HIGH_BOUND 64938 -+ -+static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { -+/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ -+/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, -+/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, -+/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, -+/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, -+/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 -+}; -+ -+uint16 -+bcm_qdbm_to_mw(uint8 qdbm) -+{ -+ uint factor = 1; -+ int idx = qdbm - QDBM_OFFSET; -+ -+ if (idx > QDBM_TABLE_LEN) { -+ /* clamp to max uint16 mW value */ -+ return 0xFFFF; -+ } -+ -+ /* scale the qdBm index up to the range of the table 0-40 -+ * where an offset of 40 qdBm equals a factor of 10 mW. -+ */ -+ while (idx < 0) { -+ idx += 40; -+ factor *= 10; -+ } -+ -+ /* return the mW value scaled down to the correct factor of 10, -+ * adding in factor/2 to get proper rounding. */ -+ return ((nqdBm_to_mW_map[idx] + factor/2) / factor); -+} -+ -+uint8 -+bcm_mw_to_qdbm(uint16 mw) -+{ -+ uint8 qdbm; -+ int offset; -+ uint mw_uint = mw; -+ uint boundary; -+ -+ /* handle boundary case */ -+ if (mw_uint <= 1) -+ return 0; -+ -+ offset = QDBM_OFFSET; -+ -+ /* move mw into the range of the table */ -+ while (mw_uint < QDBM_TABLE_LOW_BOUND) { -+ mw_uint *= 10; -+ offset -= 40; -+ } -+ -+ for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { -+ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - nqdBm_to_mW_map[qdbm])/2; -+ if (mw_uint < boundary) break; -+ } -+ -+ qdbm += (uint8)offset; -+ -+ return(qdbm); -+} -diff -Naur linux.old/drivers/net/hnd/linux_osl.c linux.dev/drivers/net/hnd/linux_osl.c ---- linux.old/drivers/net/hnd/linux_osl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/hnd/linux_osl.c 2006-04-06 15:34:15.000000000 +0200 -@@ -0,0 +1,708 @@ -+/* -+ * Linux OS Independent Layer -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ -+ */ -+ -+#define LINUX_OSL -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef mips -+#include -+#endif -+#include -+ -+#define PCI_CFG_RETRY 10 -+ -+#define OS_HANDLE_MAGIC 0x1234abcd -+#define BCM_MEM_FILENAME_LEN 24 -+ -+typedef struct bcm_mem_link { -+ struct bcm_mem_link *prev; -+ struct bcm_mem_link *next; -+ uint size; -+ int line; -+ char file[BCM_MEM_FILENAME_LEN]; -+} bcm_mem_link_t; -+ -+struct os_handle { -+ uint magic; -+ void *pdev; -+ uint malloced; -+ uint failed; -+ bcm_mem_link_t *dbgmem_list; -+}; -+ -+static int16 linuxbcmerrormap[] = \ -+{ 0, /* 0 */ -+ -EINVAL, /* BCME_ERROR */ -+ -EINVAL, /* BCME_BADARG*/ -+ -EINVAL, /* BCME_BADOPTION*/ -+ -EINVAL, /* BCME_NOTUP */ -+ -EINVAL, /* BCME_NOTDOWN */ -+ -EINVAL, /* BCME_NOTAP */ -+ -EINVAL, /* BCME_NOTSTA */ -+ -EINVAL, /* BCME_BADKEYIDX */ -+ -EINVAL, /* BCME_RADIOOFF */ -+ -EINVAL, /* BCME_NOTBANDLOCKED */ -+ -EINVAL, /* BCME_NOCLK */ -+ -EINVAL, /* BCME_BADRATESET */ -+ -EINVAL, /* BCME_BADBAND */ -+ -E2BIG, /* BCME_BUFTOOSHORT */ -+ -E2BIG, /* BCME_BUFTOOLONG */ -+ -EBUSY, /* BCME_BUSY */ -+ -EINVAL, /* BCME_NOTASSOCIATED */ -+ -EINVAL, /* BCME_BADSSIDLEN */ -+ -EINVAL, /* BCME_OUTOFRANGECHAN */ -+ -EINVAL, /* BCME_BADCHAN */ -+ -EFAULT, /* BCME_BADADDR */ -+ -ENOMEM, /* BCME_NORESOURCE */ -+ -EOPNOTSUPP, /* BCME_UNSUPPORTED */ -+ -EMSGSIZE, /* BCME_BADLENGTH */ -+ -EINVAL, /* BCME_NOTREADY */ -+ -EPERM, /* BCME_NOTPERMITTED */ -+ -ENOMEM, /* BCME_NOMEM */ -+ -EINVAL, /* BCME_ASSOCIATED */ -+ -ERANGE, /* BCME_RANGE */ -+ -EINVAL /* BCME_NOTFOUND */ -+}; + -+/* translate bcmerrors into linux errors*/ -+int -+osl_error(int bcmerror) ++struct nvram_tuple * ++_nvram_realloc(struct nvram_tuple *t, const char *name, const char *value) +{ -+ int abs_bcmerror; -+ int array_size = ARRAYSIZE(linuxbcmerrormap); -+ -+ abs_bcmerror = ABS(bcmerror); -+ -+ if (bcmerror > 0) -+ abs_bcmerror = 0; -+ -+ else if (abs_bcmerror >= array_size) -+ abs_bcmerror = BCME_ERROR; -+ -+ return linuxbcmerrormap[abs_bcmerror]; -+} ++ if ((nvram_offset + strlen(value) + 1) > NVRAM_SPACE) ++ return NULL; + -+osl_t * -+osl_attach(void *pdev) -+{ -+ osl_t *osh; ++ if (!t) { ++ if (!(t = kmalloc(sizeof(struct nvram_tuple) + strlen(name) + 1, GFP_ATOMIC))) ++ return NULL; + -+ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); -+ ASSERT(osh); ++ /* Copy name */ ++ t->name = (char *) &t[1]; ++ strcpy(t->name, name); + -+ /* -+ * check the cases where -+ * 1.Error code Added to bcmerror table, but forgot to add it to the OS -+ * dependent error code -+ * 2. Error code is added to the bcmerror table, but forgot to add the -+ * corresponding errorstring(dummy call to bcmerrorstr) -+ */ -+ bcmerrorstr(0); -+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); ++ t->value = NULL; ++ } + -+ osh->magic = OS_HANDLE_MAGIC; -+ osh->malloced = 0; -+ osh->failed = 0; -+ osh->dbgmem_list = NULL; -+ osh->pdev = pdev; ++ /* Copy value */ ++ if (!t->value || strcmp(t->value, value)) { ++ t->value = &nvram_buf[nvram_offset]; ++ strcpy(t->value, value); ++ nvram_offset += strlen(value) + 1; ++ } + -+ return osh; ++ return t; +} + +void -+osl_detach(osl_t *osh) -+{ -+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC)); -+ kfree(osh); -+} -+ -+void* -+osl_pktget(osl_t *osh, uint len, bool send) ++_nvram_free(struct nvram_tuple *t) +{ -+ struct sk_buff *skb; -+ -+ if ((skb = dev_alloc_skb(len)) == NULL) -+ return (NULL); -+ -+ skb_put(skb, len); -+ -+ /* ensure the cookie field is cleared */ -+ PKTSETCOOKIE(skb, NULL); -+ -+ return ((void*) skb); ++ if (!t) ++ nvram_offset = 0; ++ else ++ kfree(t); +} + -+void -+osl_pktfree(void *p) ++int ++nvram_set(const char *name, const char *value) +{ -+ struct sk_buff *skb, *nskb; -+ -+ skb = (struct sk_buff*) p; ++ unsigned long flags; ++ int ret; ++ struct nvram_header *header; + -+ /* perversion: we use skb->next to chain multi-skb packets */ -+ while (skb) { -+ nskb = skb->next; -+ skb->next = NULL; -+ if (skb->destructor) { -+ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if destructor exists */ -+ dev_kfree_skb_any(skb); -+ } else { -+ /* can free immediately (even in_irq()) if destructor does not exist */ -+ dev_kfree_skb(skb); ++ spin_lock_irqsave(&nvram_lock, flags); ++ if ((ret = _nvram_set(name, value))) { ++ /* Consolidate space and try again */ ++ if ((header = kmalloc(NVRAM_SPACE, GFP_ATOMIC))) { ++ if (_nvram_commit(header) == 0) ++ ret = _nvram_set(name, value); ++ kfree(header); + } -+ skb = nskb; + } -+} -+ -+uint32 -+osl_pci_read_config(osl_t *osh, uint offset, uint size) -+{ -+ uint val; -+ uint retry=PCI_CFG_RETRY; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ -+ /* only 4byte access supported */ -+ ASSERT(size == 4); -+ -+ do { -+ pci_read_config_dword(osh->pdev, offset, &val); -+ if (val != 0xffffffff) -+ break; -+ } while (retry--); -+ ++ spin_unlock_irqrestore(&nvram_lock, flags); + -+ return (val); ++ return ret; +} + -+void -+osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) ++char * ++real_nvram_get(const char *name) +{ -+ uint retry=PCI_CFG_RETRY; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ -+ /* only 4byte access supported */ -+ ASSERT(size == 4); -+ -+ do { -+ pci_write_config_dword(osh->pdev, offset, val); -+ if (offset!=PCI_BAR0_WIN) -+ break; -+ if (osl_pci_read_config(osh,offset,size) == val) -+ break; -+ } while (retry--); -+ -+} ++ unsigned long flags; ++ char *value; + -+/* return bus # for the pci device pointed by osh->pdev */ -+uint -+osl_pci_bus(osl_t *osh) -+{ -+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ spin_lock_irqsave(&nvram_lock, flags); ++ value = _nvram_get(name); ++ spin_unlock_irqrestore(&nvram_lock, flags); + -+ return ((struct pci_dev *)osh->pdev)->bus->number; ++ return value; +} + -+/* return slot # for the pci device pointed by osh->pdev */ -+uint -+osl_pci_slot(osl_t *osh) ++char * ++nvram_get(const char *name) +{ -+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); -+ -+ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); ++ if (nvram_major >= 0) ++ return real_nvram_get(name); ++ else ++ return early_nvram_get(name); +} + -+static void -+osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) ++int ++nvram_unset(const char *name) +{ -+} ++ unsigned long flags; ++ int ret; + -+void -+osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) -+{ -+ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); -+} ++ spin_lock_irqsave(&nvram_lock, flags); ++ ret = _nvram_unset(name); ++ spin_unlock_irqrestore(&nvram_lock, flags); + -+void -+osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) -+{ -+ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); ++ return ret; +} + -+ -+#ifdef BCMDBG_MEM -+ -+void* -+osl_debug_malloc(osl_t *osh, uint size, int line, char* file) ++static void ++erase_callback(struct erase_info *done) +{ -+ bcm_mem_link_t *p; -+ char* basename; -+ -+ ASSERT(size); -+ -+ if ((p = (bcm_mem_link_t*)osl_malloc(osh, sizeof(bcm_mem_link_t) + size)) == NULL) -+ return (NULL); -+ -+ p->size = size; -+ p->line = line; -+ -+ basename = strrchr(file, '/'); -+ /* skip the '/' */ -+ if (basename) -+ basename++; -+ -+ if (!basename) -+ basename = file; -+ -+ strncpy(p->file, basename, BCM_MEM_FILENAME_LEN); -+ p->file[BCM_MEM_FILENAME_LEN - 1] = '\0'; -+ -+ /* link this block */ -+ p->prev = NULL; -+ p->next = osh->dbgmem_list; -+ if (p->next) -+ p->next->prev = p; -+ osh->dbgmem_list = p; -+ -+ return p + 1; ++ wait_queue_head_t *wait_q = (wait_queue_head_t *) done->priv; ++ wake_up(wait_q); +} + -+void -+osl_debug_mfree(osl_t *osh, void *addr, uint size, int line, char* file) ++int ++nvram_commit(void) +{ -+ bcm_mem_link_t *p = (bcm_mem_link_t *)((int8*)addr - sizeof(bcm_mem_link_t)); -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ char *buf; ++ size_t erasesize, len, magic_len; ++ unsigned int i; ++ int ret; ++ struct nvram_header *header; ++ unsigned long flags; ++ u_int32_t offset; ++ DECLARE_WAITQUEUE(wait, current); ++ wait_queue_head_t wait_q; ++ struct erase_info erase; ++ u_int32_t magic_offset = 0; /* Offset for writing MAGIC # */ + -+ if (p->size == 0) { -+ printk("osl_debug_mfree: double free on addr 0x%x size %d at line %d file %s\n", -+ (uint)addr, size, line, file); -+ ASSERT(p->size); -+ return; ++ if (!nvram_mtd) { ++ printk("nvram_commit: NVRAM not found\n"); ++ return -ENODEV; + } + -+ if (p->size != size) { -+ printk("osl_debug_mfree: dealloc size %d does not match alloc size %d on addr 0x%x at line %d file %s\n", -+ size, p->size, (uint)addr, line, file); -+ ASSERT(p->size == size); -+ return; ++ if (in_interrupt()) { ++ printk("nvram_commit: not committing in interrupt\n"); ++ return -EINVAL; + } + -+ /* unlink this block */ -+ if (p->prev) -+ p->prev->next = p->next; -+ if (p->next) -+ p->next->prev = p->prev; -+ if (osh->dbgmem_list == p) -+ osh->dbgmem_list = p->next; -+ p->next = p->prev = NULL; -+ -+ osl_mfree(osh, p, size + sizeof(bcm_mem_link_t)); -+} -+ -+char* -+osl_debug_memdump(osl_t *osh, char *buf, uint sz) -+{ -+ bcm_mem_link_t *p; -+ char *obuf; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ obuf = buf; ++ /* Backup sector blocks to be erased */ ++ erasesize = ROUNDUP(NVRAM_SPACE, nvram_mtd->erasesize); ++ if (!(buf = kmalloc(erasesize, GFP_KERNEL))) { ++ printk("nvram_commit: out of memory\n"); ++ return -ENOMEM; ++ } + -+ buf += sprintf(buf, " Address\tSize\tFile:line\n"); -+ for (p = osh->dbgmem_list; p && ((buf - obuf) < (sz - 128)); p = p->next) -+ buf += sprintf(buf, "0x%08x\t%5d\t%s:%d\n", -+ (int)p + sizeof(bcm_mem_link_t), p->size, p->file, p->line); ++ down(&nvram_sem); + -+ return (obuf); -+} ++ if ((i = erasesize - NVRAM_SPACE) > 0) { ++ offset = nvram_mtd->size - erasesize; ++ len = 0; ++ ret = MTD_READ(nvram_mtd, offset, i, &len, buf); ++ if (ret || len != i) { ++ printk("nvram_commit: read error ret = %d, len = %d/%d\n", ret, len, i); ++ ret = -EIO; ++ goto done; ++ } ++ header = (struct nvram_header *)(buf + i); ++ magic_offset = i + ((void *)&header->magic - (void *)header); ++ } else { ++ offset = nvram_mtd->size - NVRAM_SPACE; ++ magic_offset = ((void *)&header->magic - (void *)header); ++ header = (struct nvram_header *)buf; ++ } + -+#endif /* BCMDBG_MEM */ ++ /* clear the existing magic # to mark the NVRAM as unusable ++ we can pull MAGIC bits low without erase */ ++ header->magic = NVRAM_CLEAR_MAGIC; /* All zeros magic */ + -+void* -+osl_malloc(osl_t *osh, uint size) -+{ -+ void *addr; -+ -+ /* only ASSERT if osh is defined */ -+ if (osh) -+ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ /* Unlock sector blocks (for Intel 28F320C3B flash) , 20060309 */ ++ if(nvram_mtd->unlock) ++ nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize); + -+ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { -+ if(osh) -+ osh->failed++; -+ return (NULL); ++ ret = MTD_WRITE(nvram_mtd, offset + magic_offset, sizeof(header->magic), ++ &magic_len, (char *)&header->magic); ++ if (ret || magic_len != sizeof(header->magic)) { ++ printk("nvram_commit: clear MAGIC error\n"); ++ ret = -EIO; ++ goto done; + } -+ if (osh) -+ osh->malloced += size; -+ -+ return (addr); -+} + -+void -+osl_mfree(osl_t *osh, void *addr, uint size) -+{ -+ if (osh) { -+ ASSERT(osh->magic == OS_HANDLE_MAGIC); -+ osh->malloced -= size; -+ } -+ kfree(addr); -+} ++ header->magic = NVRAM_MAGIC; /* reset MAGIC before we regenerate the NVRAM, ++ otherwise we'll have an incorrect CRC */ ++ /* Regenerate NVRAM */ ++ spin_lock_irqsave(&nvram_lock, flags); ++ ret = _nvram_commit(header); ++ spin_unlock_irqrestore(&nvram_lock, flags); ++ if (ret) ++ goto done; + -+uint -+osl_malloced(osl_t *osh) -+{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ return (osh->malloced); -+} ++ /* Erase sector blocks */ ++ init_waitqueue_head(&wait_q); ++ for (; offset < nvram_mtd->size - NVRAM_SPACE + header->len; offset += nvram_mtd->erasesize) { ++ erase.mtd = nvram_mtd; ++ erase.addr = offset; ++ erase.len = nvram_mtd->erasesize; ++ erase.callback = erase_callback; ++ erase.priv = (u_long) &wait_q; + -+uint osl_malloc_failed(osl_t *osh) -+{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ return (osh->failed); -+} ++ set_current_state(TASK_INTERRUPTIBLE); ++ add_wait_queue(&wait_q, &wait); + -+void* -+osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap) -+{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ /* Unlock sector blocks */ ++ if (nvram_mtd->unlock) ++ nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize); + -+ return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); -+} ++ if ((ret = MTD_ERASE(nvram_mtd, &erase))) { ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&wait_q, &wait); ++ printk("nvram_commit: erase error\n"); ++ goto done; ++ } + -+void -+osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) -+{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ /* Wait for erase to finish */ ++ schedule(); ++ remove_wait_queue(&wait_q, &wait); ++ } + -+ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); -+} ++ /* Write partition up to end of data area */ ++ header->magic = NVRAM_INVALID_MAGIC; /* All ones magic */ ++ offset = nvram_mtd->size - erasesize; ++ i = erasesize - NVRAM_SPACE + header->len; ++ ret = MTD_WRITE(nvram_mtd, offset, i, &len, buf); ++ if (ret || len != i) { ++ printk("nvram_commit: write error\n"); ++ ret = -EIO; ++ goto done; ++ } + -+uint -+osl_dma_map(osl_t *osh, void *va, uint size, int direction) -+{ -+ int dir; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; -+ return (pci_map_single(osh->pdev, va, size, dir)); -+} ++ /* Now mark the NVRAM in flash as "valid" by setting the correct ++ MAGIC # */ ++ header->magic = NVRAM_MAGIC; ++ ret = MTD_WRITE(nvram_mtd, offset + magic_offset, sizeof(header->magic), ++ &magic_len, (char *)&header->magic); ++ if (ret || magic_len != sizeof(header->magic)) { ++ printk("nvram_commit: write MAGIC error\n"); ++ ret = -EIO; ++ goto done; ++ } + -+void -+osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) -+{ -+ int dir; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; -+ pci_unmap_single(osh->pdev, (uint32)pa, size, dir); -+} ++ /* ++ * Reading a few bytes back here will put the device ++ * back to the correct mode on certain flashes */ ++ offset = nvram_mtd->size - erasesize; ++ ret = MTD_READ(nvram_mtd, offset, 4, &len, buf); + -+#if defined(BINOSL) -+void -+osl_assert(char *exp, char *file, int line) -+{ -+ char tempbuf[255]; ++ done: ++ up(&nvram_sem); ++ kfree(buf); + -+ sprintf(tempbuf, "assertion \"%s\" failed: file \"%s\", line %d\n", exp, file, line); -+ panic(tempbuf); ++ return ret; +} -+#endif /* BCMDBG || BINOSL */ + -+void -+osl_delay(uint usec) ++int ++nvram_getall(char *buf, int count) +{ -+ uint d; ++ unsigned long flags; ++ int ret; + -+ while (usec > 0) { -+ d = MIN(usec, 1000); -+ udelay(d); -+ usec -= d; -+ } ++ spin_lock_irqsave(&nvram_lock, flags); ++ if (nvram_major >= 0) ++ ret = _nvram_getall(buf, count); ++ else ++ ret = early_nvram_getall(buf, count); ++ spin_unlock_irqrestore(&nvram_lock, flags); ++ ++ return ret; +} + -+/* -+ * BINOSL selects the slightly slower function-call-based binary compatible osl. -+ */ -+#ifdef BINOSL + -+int -+osl_printf(const char *format, ...) -+{ -+ va_list args; -+ char buf[1024]; -+ int len; + -+ /* sprintf into a local buffer because there *is* no "vprintk()".. */ -+ va_start(args, format); -+ len = vsprintf(buf, format, args); -+ va_end(args); + -+ if (len > sizeof (buf)) { -+ printk("osl_printf: buffer overrun\n"); -+ return (0); -+ } + -+ return (printk(buf)); -+} + -+int -+osl_sprintf(char *buf, const char *format, ...) -+{ -+ va_list args; -+ int rc; + -+ va_start(args, format); -+ rc = vsprintf(buf, format, args); -+ va_end(args); -+ return (rc); -+} ++/* User mode interface below */ + -+int -+osl_strcmp(const char *s1, const char *s2) ++static ssize_t ++dev_nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ -+ return (strcmp(s1, s2)); -+} ++ char tmp[100], *name = tmp, *value; ++ ssize_t ret; ++ unsigned long off; + -+int -+osl_strncmp(const char *s1, const char *s2, uint n) -+{ -+ return (strncmp(s1, s2, n)); -+} ++ if (count > sizeof(tmp)) { ++ if (!(name = kmalloc(count, GFP_KERNEL))) ++ return -ENOMEM; ++ } + -+int -+osl_strlen(const char *s) -+{ -+ return (strlen(s)); -+} ++ if (copy_from_user(name, buf, count)) { ++ ret = -EFAULT; ++ goto done; ++ } + -+char* -+osl_strcpy(char *d, const char *s) -+{ -+ return (strcpy(d, s)); -+} ++ if (*name == '\0') { ++ /* Get all variables */ ++ ret = nvram_getall(name, count); ++ if (ret == 0) { ++ if (copy_to_user(buf, name, count)) { ++ ret = -EFAULT; ++ goto done; ++ } ++ ret = count; ++ } ++ } else { ++ if (!(value = nvram_get(name))) { ++ ret = 0; ++ goto done; ++ } + -+char* -+osl_strncpy(char *d, const char *s, uint n) -+{ -+ return (strncpy(d, s, n)); -+} ++ /* Provide the offset into mmap() space */ ++ off = (unsigned long) value - (unsigned long) nvram_buf; + -+void -+bcopy(const void *src, void *dst, int len) -+{ -+ memcpy(dst, src, len); -+} ++ if (put_user(off, (unsigned long *) buf)) { ++ ret = -EFAULT; ++ goto done; ++ } + -+int -+bcmp(const void *b1, const void *b2, int len) -+{ -+ return (memcmp(b1, b2, len)); -+} ++ ret = sizeof(unsigned long); ++ } + -+void -+bzero(void *b, int len) -+{ -+ memset(b, '\0', len); -+} ++ flush_cache_all(); ++ ++done: ++ if (name != tmp) ++ kfree(name); + -+uint32 -+osl_readl(volatile uint32 *r) -+{ -+ return (readl(r)); ++ return ret; +} + -+uint16 -+osl_readw(volatile uint16 *r) ++static ssize_t ++dev_nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ -+ return (readw(r)); -+} ++ char tmp[100], *name = tmp, *value; ++ ssize_t ret; + -+uint8 -+osl_readb(volatile uint8 *r) -+{ -+ return (readb(r)); -+} ++ if (count > sizeof(tmp)) { ++ if (!(name = kmalloc(count, GFP_KERNEL))) ++ return -ENOMEM; ++ } + -+void -+osl_writel(uint32 v, volatile uint32 *r) -+{ -+ writel(v, r); -+} ++ if (copy_from_user(name, buf, count)) { ++ ret = -EFAULT; ++ goto done; ++ } + -+void -+osl_writew(uint16 v, volatile uint16 *r) -+{ -+ writew(v, r); -+} ++ value = name; ++ name = strsep(&value, "="); ++ if (value) ++ ret = nvram_set(name, value) ? : count; ++ else ++ ret = nvram_unset(name) ? : count; + -+void -+osl_writeb(uint8 v, volatile uint8 *r) -+{ -+ writeb(v, r); -+} ++ done: ++ if (name != tmp) ++ kfree(name); + -+void * -+osl_uncached(void *va) -+{ -+#ifdef mips -+ return ((void*)KSEG1ADDR(va)); -+#else -+ return ((void*)va); -+#endif -+} ++ return ret; ++} + -+uint -+osl_getcycles(void) ++static int ++dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ -+ uint cycles; ++ if (cmd != NVRAM_MAGIC) ++ return -EINVAL; + -+#if defined(mips) -+ cycles = read_c0_count() * 2; -+#elif defined(__i386__) -+ rdtscl(cycles); -+#else -+ cycles = 0; -+#endif -+ return cycles; ++ return nvram_commit(); +} + -+void * -+osl_reg_map(uint32 pa, uint size) ++static int ++dev_nvram_mmap(struct file *file, struct vm_area_struct *vma) +{ -+ return (ioremap_nocache((unsigned long)pa, (unsigned long)size)); -+} ++ unsigned long offset = virt_to_phys(nvram_buf); + -+void -+osl_reg_unmap(void *va) -+{ -+ iounmap(va); -+} ++ if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start, ++ vma->vm_page_prot)) ++ return -EAGAIN; + -+int -+osl_busprobe(uint32 *val, uint32 addr) -+{ -+#ifdef mips -+ return get_dbe(*val, (uint32*)addr); -+#else -+ *val = readl(addr); + return 0; -+#endif +} + -+uchar* -+osl_pktdata(osl_t *osh, void *skb) ++static int ++dev_nvram_open(struct inode *inode, struct file * file) +{ -+ return (((struct sk_buff*)skb)->data); ++ MOD_INC_USE_COUNT; ++ return 0; +} + -+uint -+osl_pktlen(osl_t *osh, void *skb) ++static int ++dev_nvram_release(struct inode *inode, struct file * file) +{ -+ return (((struct sk_buff*)skb)->len); ++ MOD_DEC_USE_COUNT; ++ return 0; +} + -+uint -+osl_pktheadroom(osl_t *osh, void *skb) -+{ -+ return (uint) skb_headroom((struct sk_buff *) skb); -+} ++static struct file_operations dev_nvram_fops = { ++ owner: THIS_MODULE, ++ open: dev_nvram_open, ++ release: dev_nvram_release, ++ read: dev_nvram_read, ++ write: dev_nvram_write, ++ ioctl: dev_nvram_ioctl, ++ mmap: dev_nvram_mmap, ++}; + -+uint -+osl_pkttailroom(osl_t *osh, void *skb) ++static void ++dev_nvram_exit(void) +{ -+ return (uint) skb_tailroom((struct sk_buff *) skb); -+} ++ int order = 0; ++ struct page *page, *end; + -+void* -+osl_pktnext(osl_t *osh, void *skb) -+{ -+ return (((struct sk_buff*)skb)->next); -+} ++ if (nvram_handle) ++ devfs_unregister(nvram_handle); + -+void -+osl_pktsetnext(void *skb, void *x) -+{ -+ ((struct sk_buff*)skb)->next = (struct sk_buff*)x; -+} ++ if (nvram_major >= 0) ++ devfs_unregister_chrdev(nvram_major, "nvram"); + -+void -+osl_pktsetlen(osl_t *osh, void *skb, uint len) -+{ -+ __skb_trim((struct sk_buff*)skb, len); -+} ++ if (nvram_mtd) ++ put_mtd_device(nvram_mtd); + -+uchar* -+osl_pktpush(osl_t *osh, void *skb, int bytes) -+{ -+ return (skb_push((struct sk_buff*)skb, bytes)); -+} ++ while ((PAGE_SIZE << order) < NVRAM_SPACE) ++ order++; ++ end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1); ++ for (page = virt_to_page(nvram_buf); page <= end; page++) ++ mem_map_unreserve(page); + -+uchar* -+osl_pktpull(osl_t *osh, void *skb, int bytes) -+{ -+ return (skb_pull((struct sk_buff*)skb, bytes)); ++ _nvram_exit(); +} + -+void* -+osl_pktdup(osl_t *osh, void *skb) ++static int __init ++dev_nvram_init(void) +{ -+ return (skb_clone((struct sk_buff*)skb, GFP_ATOMIC)); -+} ++ int order = 0, ret = 0; ++ struct page *page, *end; ++ unsigned int i; + -+void* -+osl_pktcookie(void *skb) -+{ -+ return ((void*)((struct sk_buff*)skb)->csum); -+} ++ /* Allocate and reserve memory to mmap() */ ++ while ((PAGE_SIZE << order) < NVRAM_SPACE) ++ order++; ++ end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1); ++ for (page = virt_to_page(nvram_buf); page <= end; page++) ++ mem_map_reserve(page); + -+void -+osl_pktsetcookie(void *skb, void *x) -+{ -+ ((struct sk_buff*)skb)->csum = (uint)x; -+} ++#ifdef CONFIG_MTD ++ /* Find associated MTD device */ ++ for (i = 0; i < MAX_MTD_DEVICES; i++) { ++ nvram_mtd = get_mtd_device(NULL, i); ++ if (nvram_mtd) { ++ if (!strcmp(nvram_mtd->name, "nvram") && ++ nvram_mtd->size >= NVRAM_SPACE) ++ break; ++ put_mtd_device(nvram_mtd); ++ } ++ } ++ if (i >= MAX_MTD_DEVICES) ++ nvram_mtd = NULL; ++#endif + -+void* -+osl_pktlink(void *skb) -+{ -+ return (((struct sk_buff*)skb)->prev); -+} ++ /* Initialize hash table lock */ ++ spin_lock_init(&nvram_lock); + -+void -+osl_pktsetlink(void *skb, void *x) -+{ -+ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x; -+} ++ /* Initialize commit semaphore */ ++ init_MUTEX(&nvram_sem); + -+uint -+osl_pktprio(void *skb) -+{ -+ return (((struct sk_buff*)skb)->priority); -+} ++ /* Register char device */ ++ if ((nvram_major = devfs_register_chrdev(0, "nvram", &dev_nvram_fops)) < 0) { ++ ret = nvram_major; ++ goto err; ++ } + -+void -+osl_pktsetprio(void *skb, uint x) -+{ -+ ((struct sk_buff*)skb)->priority = x; -+} ++ /* Initialize hash table */ ++ _nvram_init(sbh); ++ ++ /* Create /dev/nvram handle */ ++ nvram_handle = devfs_register(NULL, "nvram", DEVFS_FL_NONE, nvram_major, 0, ++ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &dev_nvram_fops, NULL); ++ ++ /* Set the SDRAM NCDL value into NVRAM if not already done */ ++ if (getintvar(NULL, "sdram_ncdl") == 0) { ++ unsigned int ncdl; ++ char buf[] = "0x00000000"; ++ ++ if ((ncdl = sb_memc_get_ncdl(sbh))) { ++ sprintf(buf, "0x%08x", ncdl); ++ nvram_set("sdram_ncdl", buf); ++ nvram_commit(); ++ } ++ } ++ ++ return 0; + ++ err: ++ dev_nvram_exit(); ++ return ret; ++} + -+#endif /* BINOSL */ -diff -Naur linux.old/drivers/net/hnd/sbutils.c linux.dev/drivers/net/hnd/sbutils.c ---- linux.old/drivers/net/hnd/sbutils.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/hnd/sbutils.c 2006-04-06 15:34:15.000000000 +0200 -@@ -0,0 +1,2837 @@ ++module_init(dev_nvram_init); ++module_exit(dev_nvram_exit); +diff -urN linux.old/arch/mips/bcm947xx/pcibios.c linux.dev/arch/mips/bcm947xx/pcibios.c +--- linux.old/arch/mips/bcm947xx/pcibios.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/pcibios.c 2006-04-27 23:42:50.000000000 +0200 +@@ -0,0 +1,380 @@ +/* -+ * Misc utility routines for accessing chip-specific features -+ * of the SiliconBackplane-based Broadcom chips. ++ * Low-Level PCI and SB support for BCM47xx (Linux support code) + * -+ * Copyright 2005, Broadcom Corporation ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ ++ * ++ * $Id: pcibios.c,v 1.1.1.9 2006/02/27 03:42:55 honor Exp $ + */ + ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ +#include +#include -+#include +#include -+#include +#include -+#include -+#include -+#include ++#include ++#include +#include -+#include -+#include -+#include -+ -+/* debug/trace */ -+#define SB_ERROR(args) -+ -+ -+typedef uint32 (*sb_intrsoff_t)(void *intr_arg); -+typedef void (*sb_intrsrestore_t)(void *intr_arg, uint32 arg); -+typedef bool (*sb_intrsenabled_t)(void *intr_arg); -+ -+/* misc sb info needed by some of the routines */ -+typedef struct sb_info { ++#include ++#include + -+ struct sb_pub sb; /* back plane public state(must be first field of sb_info */ ++/* Global SB handle */ ++extern sb_t *bcm947xx_sbh; ++extern spinlock_t bcm947xx_sbh_lock; + -+ void *osh; /* osl os handle */ -+ void *sdh; /* bcmsdh handle */ ++/* Convenience */ ++#define sbh bcm947xx_sbh ++#define sbh_lock bcm947xx_sbh_lock + -+ void *curmap; /* current regs va */ -+ void *regs[SB_MAXCORES]; /* other regs va */ ++static int ++sbpci_read_config_byte(struct pci_dev *dev, int where, u8 *value) ++{ ++ unsigned long flags; ++ int ret; + -+ uint curidx; /* current core index */ -+ uint dev_coreid; /* the core provides driver functions */ ++ spin_lock_irqsave(&sbh_lock, flags); ++ ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), ++ PCI_FUNC(dev->devfn), where, value, sizeof(*value)); ++ spin_unlock_irqrestore(&sbh_lock, flags); ++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; ++} + -+ bool memseg; /* flag to toggle MEM_SEG register */ ++static int ++sbpci_read_config_word(struct pci_dev *dev, int where, u16 *value) ++{ ++ unsigned long flags; ++ int ret; + -+ uint gpioidx; /* gpio control core index */ -+ uint gpioid; /* gpio control coretype */ ++ spin_lock_irqsave(&sbh_lock, flags); ++ ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), ++ PCI_FUNC(dev->devfn), where, value, sizeof(*value)); ++ spin_unlock_irqrestore(&sbh_lock, flags); ++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; ++} + -+ uint numcores; /* # discovered cores */ -+ uint coreid[SB_MAXCORES]; /* id of each core */ ++static int ++sbpci_read_config_dword(struct pci_dev *dev, int where, u32 *value) ++{ ++ unsigned long flags; ++ int ret; + -+ void *intr_arg; /* interrupt callback function arg */ -+ sb_intrsoff_t intrsoff_fn; /* function turns chip interrupts off */ -+ sb_intrsrestore_t intrsrestore_fn; /* function restore chip interrupts */ -+ sb_intrsenabled_t intrsenabled_fn; /* function to check if chip interrupts are enabled */ ++ spin_lock_irqsave(&sbh_lock, flags); ++ ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), ++ PCI_FUNC(dev->devfn), where, value, sizeof(*value)); ++ spin_unlock_irqrestore(&sbh_lock, flags); ++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; ++} + -+} sb_info_t; ++static int ++sbpci_write_config_byte(struct pci_dev *dev, int where, u8 value) ++{ ++ unsigned long flags; ++ int ret; + -+/* local prototypes */ -+static sb_info_t * BCMINIT(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, -+ uint bustype, void *sdh, char **vars, int *varsz); -+static void BCMINIT(sb_scan)(sb_info_t *si); -+static uint sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val); -+static uint _sb_coreidx(sb_info_t *si); -+static uint sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit); -+static uint BCMINIT(sb_pcidev2chip)(uint pcidev); -+static uint BCMINIT(sb_chip2numcores)(uint chip); -+static bool sb_ispcie(sb_info_t *si); -+static bool sb_find_pci_capability(sb_info_t *si, uint8 req_cap_id, uchar *buf, uint32 *buflen); -+static int sb_pci_fixcfg(sb_info_t *si); ++ spin_lock_irqsave(&sbh_lock, flags); ++ ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), ++ PCI_FUNC(dev->devfn), where, &value, sizeof(value)); ++ spin_unlock_irqrestore(&sbh_lock, flags); ++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; ++} + -+/* routines to access mdio slave device registers */ -+static int sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint readdr, uint val); -+static void BCMINIT(sb_war30841)(sb_info_t *si); ++static int ++sbpci_write_config_word(struct pci_dev *dev, int where, u16 value) ++{ ++ unsigned long flags; ++ int ret; + -+/* delay needed between the mdio control/ mdiodata register data access */ -+#define PR28829_DELAY() OSL_DELAY(10) ++ spin_lock_irqsave(&sbh_lock, flags); ++ ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), ++ PCI_FUNC(dev->devfn), where, &value, sizeof(value)); ++ spin_unlock_irqrestore(&sbh_lock, flags); ++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; ++} + ++static int ++sbpci_write_config_dword(struct pci_dev *dev, int where, u32 value) ++{ ++ unsigned long flags; ++ int ret; + -+/* global variable to indicate reservation/release of gpio's*/ -+static uint32 sb_gpioreservation = 0; ++ spin_lock_irqsave(&sbh_lock, flags); ++ ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), ++ PCI_FUNC(dev->devfn), where, &value, sizeof(value)); ++ spin_unlock_irqrestore(&sbh_lock, flags); ++ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; ++} + -+#define SB_INFO(sbh) (sb_info_t*)sbh -+#define SET_SBREG(sbh, r, mask, val) W_SBREG((sbh), (r), ((R_SBREG((sbh), (r)) & ~(mask)) | (val))) -+#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && ISALIGNED((x), SB_CORE_SIZE)) -+#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE)) -+#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF) -+#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES) -+#define BADIDX (SB_MAXCORES+1) -+#define NOREV -1 ++static struct pci_ops pcibios_ops = { ++ sbpci_read_config_byte, ++ sbpci_read_config_word, ++ sbpci_read_config_dword, ++ sbpci_write_config_byte, ++ sbpci_write_config_word, ++ sbpci_write_config_dword ++}; + -+#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI)) -+#define PCIE(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCIE)) + -+/* sonicsrev */ -+#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT) -+#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT) ++void __init ++pcibios_init(void) ++{ ++ ulong flags; + -+#define R_SBREG(sbh, sbr) sb_read_sbreg((sbh), (sbr)) -+#define W_SBREG(sbh, sbr, v) sb_write_sbreg((sbh), (sbr), (v)) -+#define AND_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) & (v))) -+#define OR_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) | (v))) ++ if (!(sbh = sb_kattach())) ++ panic("sb_kattach failed"); ++ spin_lock_init(&sbh_lock); + -+/* -+ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/ -+ * after core switching to avoid invalid register accesss inside ISR. -+ */ -+#define INTR_OFF(si, intr_val) \ -+ if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ -+ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); } -+#define INTR_RESTORE(si, intr_val) \ -+ if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ -+ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); } ++ spin_lock_irqsave(&sbh_lock, flags); ++ sbpci_init(sbh); ++ spin_unlock_irqrestore(&sbh_lock, flags); + -+/* dynamic clock control defines */ -+#define LPOMINFREQ 25000 /* low power oscillator min */ -+#define LPOMAXFREQ 43000 /* low power oscillator max */ -+#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ -+#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ -+#define PCIMINFREQ 25000000 /* 25 MHz */ -+#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ ++ set_io_port_base((unsigned long) ioremap_nocache(SB_PCI_MEM, 0x04000000)); + -+#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ -+#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ ++ /* Scan the SB bus */ ++ pci_scan_bus(0, &pcibios_ops, NULL); + -+#define MIN_DUMPBUFLEN 32 /* debug */ ++} + -+/* different register spaces to access thr'u pcie indirect access*/ -+#define PCIE_CONFIGREGS 1 -+#define PCIE_PCIEREGS 2 ++char * __init ++pcibios_setup(char *str) ++{ ++ if (!strncmp(str, "ban=", 4)) { ++ sbpci_ban(simple_strtoul(str + 4, NULL, 0)); ++ return NULL; ++ } + -+/* GPIO Based LED powersave defines */ -+#define DEFAULT_GPIO_ONTIME 10 -+#define DEFAULT_GPIO_OFFTIME 90 ++ return (str); ++} + -+#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) ++static u32 pci_iobase = 0x100; ++static u32 pci_membase = SB_PCI_DMA; + -+static uint32 -+sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr) ++void __init ++pcibios_fixup_bus(struct pci_bus *b) +{ -+ uint8 tmp; -+ uint32 val, intr_val = 0; ++ struct list_head *ln; ++ struct pci_dev *d; ++ struct resource *res; ++ int pos, size; ++ u32 *base; ++ u8 irq; + ++ printk("PCI: Fixing up bus %d\n", b->number); + -+ /* -+ * compact flash only has 11 bits address, while we needs 12 bits address. -+ * MEM_SEG will be OR'd with other 11 bits address in hardware, -+ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). -+ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special -+ */ -+ if(si->memseg) { -+ INTR_OFF(si, intr_val); -+ tmp = 1; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); -+ sbr = (uint32) ((uintptr) sbr & ~(1 << 11)); /* mask out bit 11*/ ++ /* Fix up SB */ ++ if (b->number == 0) { ++ for (ln = b->devices.next; ln != &b->devices; ln = ln->next) { ++ d = pci_dev_b(ln); ++ /* Fix up interrupt lines */ ++ pci_read_config_byte(d, PCI_INTERRUPT_LINE, &irq); ++ d->irq = irq + 2; ++ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); ++ } + } + -+ val = R_REG(sbr); -+ -+ if(si->memseg) { -+ tmp = 0; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); -+ INTR_RESTORE(si, intr_val); ++ /* Fix up external PCI */ ++ else { ++ for (ln = b->devices.next; ln != &b->devices; ln = ln->next) { ++ d = pci_dev_b(ln); ++ /* Fix up resource bases */ ++ for (pos = 0; pos < 6; pos++) { ++ res = &d->resource[pos]; ++ base = (res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase; ++ if (res->end) { ++ size = res->end - res->start + 1; ++ if (*base & (size - 1)) ++ *base = (*base + size) & ~(size - 1); ++ res->start = *base; ++ res->end = res->start + size - 1; ++ *base += size; ++ pci_write_config_dword(d, ++ PCI_BASE_ADDRESS_0 + (pos << 2), res->start); ++ } ++ /* Fix up PCI bridge BAR0 only */ ++ if (b->number == 1 && PCI_SLOT(d->devfn) == 0) ++ break; ++ } ++ /* Fix up interrupt lines */ ++ if (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL)) ++ d->irq = (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL))->irq; ++ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); ++ } + } -+ -+ return (val); +} + -+static void -+sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v) ++unsigned int ++pcibios_assign_all_busses(void) +{ -+ uint8 tmp; -+ volatile uint32 dummy; -+ uint32 intr_val = 0; -+ -+ -+ /* -+ * compact flash only has 11 bits address, while we needs 12 bits address. -+ * MEM_SEG will be OR'd with other 11 bits address in hardware, -+ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). -+ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special -+ */ -+ if(si->memseg) { -+ INTR_OFF(si, intr_val); -+ tmp = 1; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); -+ sbr = (uint32) ((uintptr) sbr & ~(1 << 11)); /* mask out bit 11*/ -+ } -+ -+ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { -+#ifdef IL_BIGENDIAN -+ dummy = R_REG(sbr); -+ W_REG(((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); -+ dummy = R_REG(sbr); -+ W_REG((volatile uint16 *)sbr, (uint16)(v & 0xffff)); -+#else -+ dummy = R_REG(sbr); -+ W_REG((volatile uint16 *)sbr, (uint16)(v & 0xffff)); -+ dummy = R_REG(sbr); -+ W_REG(((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); -+#endif -+ } else -+ W_REG(sbr, v); ++ return 1; ++} + -+ if(si->memseg) { -+ tmp = 0; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); -+ INTR_RESTORE(si, intr_val); -+ } ++void ++pcibios_align_resource(void *data, struct resource *res, ++ unsigned long size, unsigned long align) ++{ +} + -+/* -+ * Allocate a sb handle. -+ * devid - pci device id (used to determine chip#) -+ * osh - opaque OS handle -+ * regs - virtual address of initial core registers -+ * bustype - pci/pcmcia/sb/sdio/etc -+ * vars - pointer to a pointer area for "environment" variables -+ * varsz - pointer to int to return the size of the vars -+ */ -+sb_t * -+BCMINITFN(sb_attach)(uint devid, osl_t *osh, void *regs, -+ uint bustype, void *sdh, char **vars, int *varsz) ++int ++pcibios_enable_resources(struct pci_dev *dev) +{ -+ sb_info_t *si; ++ u16 cmd, old_cmd; ++ int idx; ++ struct resource *r; + -+ /* alloc sb_info_t */ -+ if ((si = MALLOC(osh, sizeof (sb_info_t))) == NULL) { -+ SB_ERROR(("sb_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); -+ return (NULL); -+ } ++ /* External PCI only */ ++ if (dev->bus->number == 0) ++ return 0; + -+ if (BCMINIT(sb_doattach)(si, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { -+ MFREE(osh, si, sizeof (sb_info_t)); -+ return (NULL); ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ old_cmd = cmd; ++ for (idx = 0; idx < 6; idx++) { ++ r = &dev->resource[idx]; ++ if (r->flags & IORESOURCE_IO) ++ cmd |= PCI_COMMAND_IO; ++ if (r->flags & IORESOURCE_MEM) ++ cmd |= PCI_COMMAND_MEMORY; + } -+ return (sb_t *)si; ++ if (dev->resource[PCI_ROM_RESOURCE].start) ++ cmd |= PCI_COMMAND_MEMORY; ++ if (cmd != old_cmd) { ++ printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ } ++ return 0; +} + -+/* Using sb_kattach depends on SB_BUS support, either implicit */ -+/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */ -+#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS) -+ -+/* global kernel resource */ -+static sb_info_t ksi; -+ -+/* generic kernel variant of sb_attach() */ -+sb_t * -+BCMINITFN(sb_kattach)() ++int ++pcibios_enable_device(struct pci_dev *dev, int mask) +{ -+ uint32 *regs; ++ ulong flags; ++ uint coreidx; ++ void *regs; + -+ if (ksi.curmap == NULL) { -+ uint32 cid; ++ /* External PCI device enable */ ++ if (dev->bus->number != 0) ++ return pcibios_enable_resources(dev); + -+ regs = (uint32 *)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE); -+ cid = R_REG((uint32 *)regs); -+ if (((cid & CID_ID_MASK) == BCM4712_DEVICE_ID) && -+ ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) && -+ ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) { -+ uint32 *scc, val; ++ /* These cores come out of reset enabled */ ++ if (dev->device == SB_MIPS || ++ dev->device == SB_MIPS33 || ++ dev->device == SB_EXTIF || ++ dev->device == SB_CC) ++ return 0; + -+ scc = (uint32 *)((uchar*)regs + OFFSETOF(chipcregs_t, slow_clk_ctl)); -+ val = R_REG(scc); -+ SB_ERROR((" initial scc = 0x%x\n", val)); -+ val |= SCC_SS_XTAL; -+ W_REG(scc, val); ++ spin_lock_irqsave(&sbh_lock, flags); ++ coreidx = sb_coreidx(sbh); ++ regs = sb_setcoreidx(sbh, PCI_SLOT(dev->devfn)); ++ if (!regs) ++ return PCIBIOS_DEVICE_NOT_FOUND; ++ ++ /* ++ * The USB core requires a special bit to be set during core ++ * reset to enable host (OHCI) mode. Resetting the SB core in ++ * pcibios_enable_device() is a hack for compatibility with ++ * vanilla usb-ohci so that it does not have to know about ++ * SB. A driver that wants to use the USB core in device mode ++ * should know about SB and should reset the bit back to 0 ++ * after calling pcibios_enable_device(). ++ */ ++ if (sb_coreid(sbh) == SB_USB) { ++ sb_core_disable(sbh, sb_coreflags(sbh, 0, 0)); ++ sb_core_reset(sbh, 1 << 29, 0); ++ } ++ /* ++ * USB 2.0 special considerations: ++ * ++ * 1. Since the core supports both OHCI and EHCI functions, it must ++ * only be reset once. ++ * ++ * 2. In addition to the standard SB reset sequence, the Host Control ++ * Register must be programmed to bring the USB core and various ++ * phy components out of reset. ++ */ ++ else if (sb_coreid(sbh) == SB_USB20H) { ++ if (!sb_iscoreup(sbh)) { ++ sb_core_reset(sbh, 0, 0); ++ writel(0x7FF, (ulong)regs + 0x200); ++ udelay(1); + } ++ } else ++ sb_core_reset(sbh, 0, 0); + -+ if (BCMINIT(sb_doattach)(&ksi, BCM4710_DEVICE_ID, NULL, (void*)regs, -+ SB_BUS, NULL, NULL, NULL) == NULL) { -+ return NULL; -+ } -+ } ++ sb_setcoreidx(sbh, coreidx); ++ spin_unlock_irqrestore(&sbh_lock, flags); + -+ return (sb_t *)&ksi; ++ return 0; +} -+#endif + -+static sb_info_t * -+BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, -+ uint bustype, void *sdh, char **vars, int *varsz) ++void ++pcibios_update_resource(struct pci_dev *dev, struct resource *root, ++ struct resource *res, int resource) +{ -+ uint origidx; -+ chipcregs_t *cc; -+ sbconfig_t *sb; -+ uint32 w; -+ -+ ASSERT(GOODREGS(regs)); -+ -+ bzero((uchar*)si, sizeof (sb_info_t)); ++ unsigned long where, size; ++ u32 reg; + -+ si->sb.buscoreidx = si->gpioidx = BADIDX; ++ /* External PCI only */ ++ if (dev->bus->number == 0) ++ return; + -+ si->osh = osh; -+ si->curmap = regs; -+ si->sdh = sdh; ++ where = PCI_BASE_ADDRESS_0 + (resource * 4); ++ size = res->end - res->start; ++ pci_read_config_dword(dev, where, ®); ++ reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); ++ pci_write_config_dword(dev, where, reg); ++} + -+ /* check to see if we are a sb core mimic'ing a pci core */ -+ if (bustype == PCI_BUS) { -+ if (OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof (uint32)) == 0xffffffff) -+ bustype = SB_BUS; -+ else -+ bustype = PCI_BUS; -+ } ++static void __init ++quirk_sbpci_bridge(struct pci_dev *dev) ++{ ++ if (dev->bus->number != 1 || PCI_SLOT(dev->devfn) != 0) ++ return; + -+ si->sb.bustype = bustype; -+ if (si->sb.bustype != BUSTYPE(si->sb.bustype)) { -+ SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n", -+ si->sb.bustype, BUSTYPE(si->sb.bustype))); -+ return NULL; -+ } ++ printk("PCI: Fixing up bridge\n"); + -+ /* need to set memseg flag for CF card first before any sb registers access */ -+ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) -+ si->memseg = TRUE; ++ /* Enable PCI bridge bus mastering and memory space */ ++ pci_set_master(dev); ++ pcibios_enable_resources(dev); + -+ /* kludge to enable the clock on the 4306 which lacks a slowclock */ -+ if (BUSTYPE(si->sb.bustype) == PCI_BUS) -+ sb_clkctl_xtal(&si->sb, XTAL|PLL, ON); ++ /* Enable PCI bridge BAR1 prefetch and burst */ ++ pci_write_config_dword(dev, PCI_BAR1_CONTROL, 3); ++} + -+ if (BUSTYPE(si->sb.bustype) == PCI_BUS) { -+ w = OSL_PCI_READ_CONFIG(osh, PCI_BAR0_WIN, sizeof (uint32)); -+ if (!GOODCOREADDR(w)) -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32), SB_ENUM_BASE); -+ } ++struct pci_fixup pcibios_fixups[] = { ++ { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, quirk_sbpci_bridge }, ++ { 0 } ++}; + -+ /* initialize current core index value */ -+ si->curidx = _sb_coreidx(si); ++/* ++ * If we set up a device for bus mastering, we need to check the latency ++ * timer as certain crappy BIOSes forget to set it properly. ++ */ ++unsigned int pcibios_max_latency = 255; + -+ if (si->curidx == BADIDX) { -+ SB_ERROR(("sb_doattach: bad core index\n")); -+ return NULL; -+ } ++void pcibios_set_master(struct pci_dev *dev) ++{ ++ u8 lat; ++ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); ++ if (lat < 16) ++ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; ++ else if (lat > pcibios_max_latency) ++ lat = pcibios_max_latency; ++ else ++ return; ++ printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat); ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); ++} + -+ /* get sonics backplane revision */ -+ sb = REGS2SB(si->curmap); -+ si->sb.sonicsrev = (R_SBREG(si, &(sb)->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT; +diff -urN linux.old/arch/mips/bcm947xx/prom.c linux.dev/arch/mips/bcm947xx/prom.c +--- linux.old/arch/mips/bcm947xx/prom.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/prom.c 2006-04-27 19:24:19.000000000 +0200 +@@ -0,0 +1,41 @@ ++/* ++ * Early initialization code for BCM94710 boards ++ * ++ * Copyright 2004, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: prom.c,v 1.1 2005/03/16 13:49:59 wbx Exp $ ++ */ + -+ /* keep and reuse the initial register mapping */ -+ origidx = si->curidx; -+ if (BUSTYPE(si->sb.bustype) == SB_BUS) -+ si->regs[origidx] = regs; ++#include ++#include ++#include ++#include ++#include + -+ /* is core-0 a chipcommon core? */ -+ si->numcores = 1; -+ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, 0); -+ if (sb_coreid(&si->sb) != SB_CC) -+ cc = NULL; ++void __init ++prom_init(int argc, const char **argv) ++{ ++ unsigned long mem; + -+ /* determine chip id and rev */ -+ if (cc) { -+ /* chip common core found! */ -+ si->sb.chip = R_REG(&cc->chipid) & CID_ID_MASK; -+ si->sb.chiprev = (R_REG(&cc->chipid) & CID_REV_MASK) >> CID_REV_SHIFT; -+ si->sb.chippkg = (R_REG(&cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT; -+ } else { -+ /* The only pcmcia chip without a chipcommon core is a 4301 */ -+ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) -+ devid = BCM4301_DEVICE_ID; ++ mips_machgroup = MACH_GROUP_BRCM; ++ mips_machtype = MACH_BCM947XX; + -+ /* no chip common core -- must convert device id to chip id */ -+ if ((si->sb.chip = BCMINIT(sb_pcidev2chip)(devid)) == 0) { -+ SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid)); -+ sb_setcoreidx(&si->sb, origidx); -+ return NULL; -+ } ++ /* Figure out memory size by finding aliases */ ++ for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { ++ if (*(unsigned long *)((unsigned long)(prom_init) + mem) == ++ *(unsigned long *)(prom_init)) ++ break; + } ++ add_memory_region(0, mem, BOOT_MEM_RAM); ++} + -+ /* get chipcommon rev */ -+ si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV; ++void __init ++prom_free_prom_memory(void) ++{ ++} +diff -urN linux.old/arch/mips/bcm947xx/sbmips.c linux.dev/arch/mips/bcm947xx/sbmips.c +--- linux.old/arch/mips/bcm947xx/sbmips.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/sbmips.c 2006-05-02 04:43:13.000000000 +0200 +@@ -0,0 +1,1132 @@ ++/* ++ * BCM47XX Sonics SiliconBackplane MIPS core routines ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: hndmips.c,v 1.1.1.1 2006/02/27 03:43:16 honor Exp $ ++ */ + -+ /* determine numcores */ -+ if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6))) -+ si->numcores = (R_REG(&cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT; -+ else -+ si->numcores = BCMINIT(sb_chip2numcores)(si->sb.chip); ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ /* return to original core */ -+ sb_setcoreidx(&si->sb, origidx); ++/* sbipsflag register format, indexed by irq. */ ++static const uint32 sbips_int_mask[] = { ++ 0, /* placeholder */ ++ SBIPS_INT1_MASK, ++ SBIPS_INT2_MASK, ++ SBIPS_INT3_MASK, ++ SBIPS_INT4_MASK ++}; + -+ /* sanity checks */ -+ ASSERT(si->sb.chip); ++static const uint32 sbips_int_shift[] = { ++ 0, /* placeholder */ ++ SBIPS_INT1_SHIFT, ++ SBIPS_INT2_SHIFT, ++ SBIPS_INT3_SHIFT, ++ SBIPS_INT4_SHIFT ++}; + -+ /* scan for cores */ -+ BCMINIT(sb_scan)(si); ++/* ++ * Map SB cores sharing the MIPS hardware IRQ0 to virtual dedicated OS IRQs. ++ * Per-port BSP code is required to provide necessary translations between ++ * the shared MIPS IRQ and the virtual OS IRQs based on SB core flag. ++ * ++ * See sb_irq() for the mapping. ++ */ ++static uint shirq_map_base = 0; + -+ /* fixup necessary chip/core configurations */ -+ if (BUSTYPE(si->sb.bustype) == PCI_BUS) { -+ if (sb_pci_fixcfg(si)) { -+ SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n")); -+ return NULL; -+ } -+ } -+ -+ /* srom_var_init() depends on sb_scan() info */ -+ if (srom_var_init(si, si->sb.bustype, si->curmap, osh, vars, varsz)) { -+ SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n")); -+ return (NULL); -+ } -+ -+ if (cc == NULL) { -+ /* -+ * The chip revision number is hardwired into all -+ * of the pci function config rev fields and is -+ * independent from the individual core revision numbers. -+ * For example, the "A0" silicon of each chip is chip rev 0. -+ * For PCMCIA we get it from the CIS instead. -+ */ -+ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { -+ ASSERT(vars); -+ si->sb.chiprev = getintvar(*vars, "chiprev"); -+ } else if (BUSTYPE(si->sb.bustype) == PCI_BUS) { -+ w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_REV, sizeof (uint32)); -+ si->sb.chiprev = w & 0xff; -+ } else -+ si->sb.chiprev = 0; -+ } ++/* Returns the SB interrupt flag of the current core. */ ++static uint32 ++sb_getflag(sb_t *sbh) ++{ ++ osl_t *osh; ++ void *regs; ++ sbconfig_t *sb; + -+ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { -+ w = getintvar(*vars, "regwindowsz"); -+ si->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE; -+ } ++ osh = sb_osh(sbh); ++ regs = sb_coreregs(sbh); ++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + -+ /* gpio control core is required */ -+ if (!GOODIDX(si->gpioidx)) { -+ SB_ERROR(("sb_doattach: gpio control core not found\n")); -+ return NULL; -+ } ++ return (R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK); ++} + -+ /* get boardtype and boardrev */ -+ switch (BUSTYPE(si->sb.bustype)) { -+ case PCI_BUS: -+ /* do a pci config read to get subsystem id and subvendor id */ -+ w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_SVID, sizeof (uint32)); -+ si->sb.boardvendor = w & 0xffff; -+ si->sb.boardtype = (w >> 16) & 0xffff; -+ break; ++/* ++ * Returns the MIPS IRQ assignment of the current core. If unassigned, ++ * 0 is returned. ++ */ ++uint ++sb_irq(sb_t *sbh) ++{ ++ osl_t *osh; ++ uint idx; ++ void *regs; ++ sbconfig_t *sb; ++ uint32 flag, sbipsflag; ++ uint irq = 0; + -+ case PCMCIA_BUS: -+ case SDIO_BUS: -+ si->sb.boardvendor = getintvar(*vars, "manfid"); -+ si->sb.boardtype = getintvar(*vars, "prodid"); -+ break; ++ osh = sb_osh(sbh); ++ flag = sb_getflag(sbh); + -+ case SB_BUS: -+ case JTAG_BUS: -+ si->sb.boardvendor = VENDOR_BROADCOM; -+ if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0) -+ si->sb.boardtype = 0xffff; -+ break; -+ } ++ idx = sb_coreidx(sbh); + -+ if (si->sb.boardtype == 0) { -+ SB_ERROR(("sb_doattach: unknown board type\n")); -+ ASSERT(si->sb.boardtype); -+ } ++ if ((regs = sb_setcore(sbh, SB_MIPS, 0)) || ++ (regs = sb_setcore(sbh, SB_MIPS33, 0))) { ++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + -+ /* setup the GPIO based LED powersave register */ -+ if (si->sb.ccrev >= 16) { -+ w = getintvar(*vars, "gpiotimerval"); -+ if (!w) -+ w = DEFAULT_GPIOTIMERVAL; -+ sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w); ++ /* sbipsflag specifies which core is routed to interrupts 1 to 4 */ ++ sbipsflag = R_REG(osh, &sb->sbipsflag); ++ for (irq = 1; irq <= 4; irq++) { ++ if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag) ++ break; ++ } ++ if (irq == 5) ++ irq = 0; + } + ++ sb_setcoreidx(sbh, idx); + -+ return (si); ++ return irq; +} + -+uint -+sb_coreid(sb_t *sbh) ++/* Clears the specified MIPS IRQ. */ ++static void ++BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq) +{ -+ sb_info_t *si; ++ osl_t *osh; ++ void *regs; + sbconfig_t *sb; + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++ osh = sb_osh(sbh); ++ ++ if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) && ++ !(regs = sb_setcore(sbh, SB_MIPS33, 0))) ++ ASSERT(regs); ++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); + -+ return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT); ++ if (irq == 0) ++ W_REG(osh, &sb->sbintvec, 0); ++ else ++ OR_REG(osh, &sb->sbipsflag, sbips_int_mask[irq]); +} + -+uint -+sb_coreidx(sb_t *sbh) ++/* ++ * Assigns the specified MIPS IRQ to the specified core. Shared MIPS ++ * IRQ 0 may be assigned more than once. ++ * ++ * The old assignment to the specified core is removed first. ++ */ ++static void ++BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit) +{ -+ sb_info_t *si; ++ osl_t *osh; ++ void *regs; ++ sbconfig_t *sb; ++ uint32 flag; ++ uint oldirq; + -+ si = SB_INFO(sbh); -+ return (si->curidx); ++ osh = sb_osh(sbh); ++ ++ regs = sb_setcore(sbh, coreid, coreunit); ++ ASSERT(regs); ++ flag = sb_getflag(sbh); ++ oldirq = sb_irq(sbh); ++ if (oldirq) ++ sb_clearirq(sbh, oldirq); ++ ++ if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) && ++ !(regs = sb_setcore(sbh, SB_MIPS33, 0))) ++ ASSERT(regs); ++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); ++ ++ if (!oldirq) ++ AND_REG(osh, &sb->sbintvec, ~(1 << flag)); ++ ++ if (irq == 0) ++ OR_REG(osh, &sb->sbintvec, 1 << flag); ++ else { ++ flag <<= sbips_int_shift[irq]; ++ ASSERT(!(flag & ~sbips_int_mask[irq])); ++ flag |= R_REG(osh, &sb->sbipsflag) & ~sbips_int_mask[irq]; ++ W_REG(osh, &sb->sbipsflag, flag); ++ } +} + -+/* return current index of core */ -+static uint -+_sb_coreidx(sb_info_t *si) ++/* ++ * Initializes clocks and interrupts. SB and NVRAM access must be ++ * initialized prior to calling. ++ * ++ * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero. ++ */ ++void ++BCMINITFN(sb_mips_init)(sb_t *sbh, uint shirqmap) +{ -+ sbconfig_t *sb; -+ uint32 sbaddr = 0; ++ osl_t *osh; ++ ulong hz, ns, tmp; ++ extifregs_t *eir; ++ chipcregs_t *cc; ++ char *value; ++ uint irq; + -+ ASSERT(si); ++ osh = sb_osh(sbh); + -+ switch (BUSTYPE(si->sb.bustype)) { -+ case SB_BUS: -+ sb = REGS2SB(si->curmap); -+ sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0)); -+ break; ++ /* Figure out current SB clock speed */ ++ if ((hz = sb_clock(sbh)) == 0) ++ hz = 100000000; ++ ns = 1000000000 / hz; + -+ case PCI_BUS: -+ sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32)); -+ break; ++ /* Setup external interface timing */ ++ if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) { ++ /* Initialize extif so we can get to the LEDs and external UART */ ++ W_REG(osh, &eir->prog_config, CF_EN); + -+ case PCMCIA_BUS: { -+ uint8 tmp = 0; ++ /* Set timing for the flash */ ++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ ++ tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */ ++ tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ ++ W_REG(osh, &eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */ + -+ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1); -+ sbaddr = (uint)tmp << 12; -+ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1); -+ sbaddr |= (uint)tmp << 16; -+ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1); -+ sbaddr |= (uint)tmp << 24; -+ break; ++ /* Set programmable interface timing for external uart */ ++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ ++ tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */ ++ tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */ ++ tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ ++ W_REG(osh, &eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */ ++ } else if ((cc = sb_setcore(sbh, SB_CC, 0))) { ++ /* Set timing for the flash */ ++ tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ ++ tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */ ++ tmp |= CEIL(120, ns); /* W0 = 120nS */ ++ if ((sb_corerev(sbh) < 9) || ++ (BCMINIT(sb_chip)(sbh) == 0x5365)) ++ W_REG(osh, &cc->flash_waitcount, tmp); ++ ++ if ((sb_corerev(sbh) < 9) || ++ ((sb_chip(sbh) == BCM5350_CHIP_ID) && sb_chiprev(sbh) == 0) || ++ (BCMINIT(sb_chip)(sbh) == 0x5365)) { ++ W_REG(osh, &cc->pcmcia_memwait, tmp); ++ } ++ ++ /* Save shared IRQ mapping base */ ++ shirq_map_base = shirqmap; + } + -+#ifdef BCMJTAG -+ case JTAG_BUS: -+ sbaddr = (uint32)si->curmap; ++ /* Chip specific initialization */ ++ switch (sb_chip(sbh)) { ++ case BCM4710_CHIP_ID: ++ /* Clear interrupt map */ ++ for (irq = 0; irq <= 4; irq++) ++ sb_clearirq(sbh, irq); ++ sb_setirq(sbh, 0, SB_CODEC, 0); ++ sb_setirq(sbh, 0, SB_EXTIF, 0); ++ sb_setirq(sbh, 2, SB_ENET, 1); ++ sb_setirq(sbh, 3, SB_ILINE20, 0); ++ sb_setirq(sbh, 4, SB_PCI, 0); ++ ASSERT(eir); ++ value = nvram_get("et0phyaddr"); ++ if (value && !strcmp(value, "31")) { ++ /* Enable internal UART */ ++ W_REG(osh, &eir->corecontrol, CC_UE); ++ /* Give USB its own interrupt */ ++ sb_setirq(sbh, 1, SB_USB, 0); ++ } else { ++ /* Disable internal UART */ ++ W_REG(osh, &eir->corecontrol, 0); ++ /* Give Ethernet its own interrupt */ ++ sb_setirq(sbh, 1, SB_ENET, 0); ++ sb_setirq(sbh, 0, SB_USB, 0); ++ } ++ break; ++ case BCM5350_CHIP_ID: ++ /* Clear interrupt map */ ++ for (irq = 0; irq <= 4; irq++) ++ sb_clearirq(sbh, irq); ++ sb_setirq(sbh, 0, SB_CC, 0); ++ sb_setirq(sbh, 0, SB_MIPS33, 0); ++ sb_setirq(sbh, 1, SB_D11, 0); ++ sb_setirq(sbh, 2, SB_ENET, 0); ++ sb_setirq(sbh, 3, SB_PCI, 0); ++ sb_setirq(sbh, 4, SB_USB, 0); ++ break; ++ case BCM4785_CHIP_ID: ++ /* Reassign PCI to irq 4 */ ++ sb_setirq(sbh, 4, SB_PCI, 0); + break; -+#endif /* BCMJTAG */ -+ -+ default: -+ ASSERT(0); + } -+ -+ if (!GOODCOREADDR(sbaddr)) -+ return BADIDX; -+ -+ return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE); +} + -+uint -+sb_corevendor(sb_t *sbh) ++uint32 ++BCMINITFN(sb_cpu_clock)(sb_t *sbh) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; ++ extifregs_t *eir; ++ chipcregs_t *cc; ++ uint32 n, m; ++ uint idx; ++ uint32 pll_type, rate = 0; + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++ /* get index of the current core */ ++ idx = sb_coreidx(sbh); ++ pll_type = PLL_TYPE1; + -+ return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT); -+} ++ /* switch to extif or chipc core */ ++ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) { ++ n = R_REG(osh, &eir->clockcontrol_n); ++ m = R_REG(osh, &eir->clockcontrol_sb); ++ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { ++ pll_type = R_REG(osh, &cc->capabilities) & CAP_PLL_MASK; ++ n = R_REG(osh, &cc->clockcontrol_n); ++ if ((pll_type == PLL_TYPE2) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE6) || ++ (pll_type == PLL_TYPE7)) ++ m = R_REG(osh, &cc->clockcontrol_m3); ++ else if (pll_type == PLL_TYPE5) { ++ rate = 200000000; ++ goto out; ++ } ++ else if (pll_type == PLL_TYPE3) { ++ if (sb_chip(sbh) == BCM5365_CHIP_ID) { ++ rate = 200000000; ++ goto out; ++ } ++ /* 5350 uses m2 to control mips */ ++ else ++ m = R_REG(osh, &cc->clockcontrol_m2); ++ } else ++ m = R_REG(osh, &cc->clockcontrol_sb); ++ } else ++ goto out; + -+uint -+sb_corerev(sb_t *sbh) -+{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ uint sbidh; + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); -+ sbidh = R_SBREG(si, &(sb)->sbidhigh); ++ /* calculate rate */ ++ if (BCMINIT(sb_chip)(sbh) == 0x5365) ++ rate = 100000000; ++ else ++ rate = sb_clock_rate(pll_type, n, m); + -+ return (SBCOREREV(sbidh)); -+} ++ if (pll_type == PLL_TYPE6) ++ rate = SB2MIPS_T6(rate); + -+void * -+sb_osh(sb_t *sbh) -+{ -+ sb_info_t *si; ++out: ++ /* switch back to previous core */ ++ sb_setcoreidx(sbh, idx); + -+ si = SB_INFO(sbh); -+ return si->osh; ++ return rate; +} + -+#define SBTML_ALLOW (SBTML_PE | SBTML_FGC | SBTML_FL_MASK) ++#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) ++ ++static void ++BCMINITFN(handler)(void) ++{ ++ __asm__( ++ ".set\tmips32\n\t" ++ "ssnop\n\t" ++ "ssnop\n\t" ++ /* Disable interrupts */ ++ /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */ ++ "mfc0 $15, $12\n\t" ++ /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */ ++ "li $14, -31746\n\t" ++ "and $15, $15, $14\n\t" ++ "mtc0 $15, $12\n\t" ++ "eret\n\t" ++ "nop\n\t" ++ "nop\n\t" ++ ".set\tmips0"); ++} + -+/* set/clear sbtmstatelow core-specific flags */ -+uint32 -+sb_coreflags(sb_t *sbh, uint32 mask, uint32 val) ++/* The following MUST come right after handler() */ ++static void ++BCMINITFN(afterhandler)(void) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ uint32 w; ++} + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++/* ++ * Set the MIPS, backplane and PCI clocks as closely as possible. ++ * ++ * MIPS clocks synchronization function has been moved from PLL in chipcommon ++ * core rev. 15 to a DLL inside the MIPS core in 4785. ++ */ ++bool ++BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock) ++{ ++ extifregs_t *eir = NULL; ++ chipcregs_t *cc = NULL; ++ mipsregs_t *mipsr = NULL; ++ volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2; ++ uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg; ++ uint32 pll_type, sync_mode; ++ uint ic_size, ic_lsize; ++ uint idx, i; + -+ ASSERT((val & ~mask) == 0); -+ ASSERT((mask & ~SBTML_ALLOW) == 0); ++ /* PLL configuration: type 1 */ ++ typedef struct { ++ uint32 mipsclock; ++ uint16 n; ++ uint32 sb; ++ uint32 pci33; ++ uint32 pci25; ++ } n3m_table_t; ++ static n3m_table_t BCMINITDATA(type1_table)[] = { ++ /* 96.000 32.000 24.000 */ ++ { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, ++ /* 100.000 33.333 25.000 */ ++ { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, ++ /* 104.000 31.200 24.960 */ ++ { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, ++ /* 108.000 32.400 24.923 */ ++ { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, ++ /* 112.000 32.000 24.889 */ ++ { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, ++ /* 115.200 32.000 24.000 */ ++ { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, ++ /* 120.000 30.000 24.000 */ ++ { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, ++ /* 124.800 31.200 24.960 */ ++ { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, ++ /* 128.000 32.000 24.000 */ ++ { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, ++ /* 132.000 33.000 24.750 */ ++ { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, ++ /* 136.000 32.640 24.727 */ ++ { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, ++ /* 140.000 30.000 24.706 */ ++ { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, ++ /* 144.000 30.857 24.686 */ ++ { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, ++ /* 150.857 33.000 24.000 */ ++ { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, ++ /* 152.000 32.571 24.000 */ ++ { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, ++ /* 156.000 31.200 24.960 */ ++ { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, ++ /* 160.000 32.000 24.000 */ ++ { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, ++ /* 163.200 32.640 24.727 */ ++ { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, ++ /* 168.000 32.000 24.889 */ ++ { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, ++ /* 176.000 33.000 24.000 */ ++ { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, ++ }; ++ ++ /* PLL configuration: type 3 */ ++ typedef struct { ++ uint32 mipsclock; ++ uint16 n; ++ uint32 m2; /* that is the clockcontrol_m2 */ ++ } type3_table_t; ++ static type3_table_t type3_table[] = { ++ /* for 5350, mips clock is always double sb clock */ ++ { 150000000, 0x311, 0x4020005 }, ++ { 200000000, 0x311, 0x4020003 }, ++ }; + -+ /* mask and set */ -+ if (mask || val) { -+ w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val; -+ W_SBREG(si, &sb->sbtmstatelow, w); -+ } ++ /* PLL configuration: type 2, 4, 7 */ ++ typedef struct { ++ uint32 mipsclock; ++ uint32 sbclock; ++ uint16 n; ++ uint32 sb; ++ uint32 pci33; ++ uint32 m2; ++ uint32 m3; ++ uint32 ratio_cfg; ++ uint32 ratio_parm; ++ uint32 d11_r1; ++ uint32 d11_r2; ++ } n4m_table_t; ++ static n4m_table_t BCMINITDATA(type2_table)[] = { ++ { 120000000, 60000000, 0x0303, 0x01000200, 0x01000600, 0x01000200, 0x05000200, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 150000000, 75000000, 0x0303, 0x01000100, 0x01000600, 0x01000100, 0x05000100, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8, ++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, ++ { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8, ++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, ++ { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, ++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, ++ { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, ++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, ++ { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, ++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, ++ { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01010100, 0x05000100, 8, ++ 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, ++ { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01010100, 0x05000100, 11, ++ 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 330000000, 132000000, 0x0903, 0x01000200, 0x00020200, 0x01010100, 0x05000100, 0, ++ 0, 10 /* ratio 4/10 */, 0x02520129 }, ++ { 330000000, 146666666, 0x0903, 0x01010000, 0x00020200, 0x01010100, 0x05000100, 0, ++ 0, 9 /* ratio 4/9 */, 0x012a00a9 }, ++ { 330000000, 165000000, 0x0903, 0x01000100, 0x00020200, 0x01010100, 0x05000100, 0, ++ 0, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 360000000, 120000000, 0x0a03, 0x01000300, 0x00010201, 0x01010200, 0x05000100, 0, ++ 0, 12 /* ratio 4/12 */, 0x04920492 }, ++ { 360000000, 144000000, 0x0a03, 0x01000200, 0x00010201, 0x01010200, 0x05000100, 0, ++ 0, 10 /* ratio 4/10 */, 0x02520129 }, ++ { 360000000, 160000000, 0x0a03, 0x01010000, 0x00010201, 0x01010200, 0x05000100, 0, ++ 0, 9 /* ratio 4/9 */, 0x012a00a9 }, ++ { 360000000, 180000000, 0x0a03, 0x01000100, 0x00010201, 0x01010200, 0x05000100, 0, ++ 0, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ { 390000000, 130000000, 0x0b03, 0x01010100, 0x00020101, 0x01020100, 0x05000100, 0, ++ 0, 12 /* ratio 4/12 */, 0x04920492 }, ++ { 390000000, 156000000, 0x0b03, 0x01000200, 0x00020101, 0x01020100, 0x05000100, 0, ++ 0, 10 /* ratio 4/10 */, 0x02520129 }, ++ { 390000000, 173000000, 0x0b03, 0x01010000, 0x00020101, 0x01020100, 0x05000100, 0, ++ 0, 9 /* ratio 4/9 */, 0x012a00a9 }, ++ { 390000000, 195000000, 0x0b03, 0x01000100, 0x00020101, 0x01020100, 0x05000100, 0, ++ 0, 8 /* ratio 4/8 */, 0x00aa0055 }, ++ }; ++ static n4m_table_t BCMINITDATA(type4_table)[] = { ++ { 120000000, 60000000, 0x0009, 0x11020009, 0x01030203, 0x11020009, 0x04000009, 11, ++ 0x0aaa0555 }, ++ { 150000000, 75000000, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, ++ 0x0aaa0555 }, ++ { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8, ++ 0x012a00a9 }, ++ { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13, ++ 0x254a14a9 }, ++ { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9, ++ 0x02520129 }, ++ { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, ++ 0x0aaa0555 }, ++ { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, ++ 0x0aaa0555 }, ++ { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13, ++ 0x254a14a9 }, ++ { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, ++ 0x254a14a9 }, ++ { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, ++ 0x254a14a9 }, ++ { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9, ++ 0x02520129 }, ++ { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11, ++ 0x0aaa0555 } ++ }; ++ static n4m_table_t BCMINITDATA(type7_table)[] = { ++ { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, ++ 0x0aaa0555 }, ++ { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, ++ 0x0aaa0555 }, ++ { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, ++ 0x0aaa0555 }, ++ { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11, ++ 0x0aaa0555 }, ++ { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11, ++ 0x0aaa0555 } ++ }; + -+ /* return the new value */ -+ return (R_SBREG(si, &sb->sbtmstatelow) & SBTML_ALLOW); -+} ++ ulong start, end, dst; ++ bool ret = FALSE; + -+/* set/clear sbtmstatehigh core-specific flags */ -+uint32 -+sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val) -+{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ uint32 w; ++ volatile uint32 *dll_ctrl = (volatile uint32 *)0xff400008; ++ volatile uint32 *dll_r1 = (volatile uint32 *)0xff400010; ++ volatile uint32 *dll_r2 = (volatile uint32 *)0xff400018; + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++ /* get index of the current core */ ++ idx = sb_coreidx(sbh); ++ clockcontrol_m2 = NULL; + -+ ASSERT((val & ~mask) == 0); -+ ASSERT((mask & ~SBTMH_FL_MASK) == 0); ++ /* switch to extif or chipc core */ ++ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) { ++ pll_type = PLL_TYPE1; ++ clockcontrol_n = &eir->clockcontrol_n; ++ clockcontrol_sb = &eir->clockcontrol_sb; ++ clockcontrol_pci = &eir->clockcontrol_pci; ++ clockcontrol_m2 = &cc->clockcontrol_m2; ++ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { ++ pll_type = R_REG(osh, &cc->capabilities) & CAP_PLL_MASK; ++ if (pll_type == PLL_TYPE6) { ++ clockcontrol_n = NULL; ++ clockcontrol_sb = NULL; ++ clockcontrol_pci = NULL; ++ } else { ++ clockcontrol_n = &cc->clockcontrol_n; ++ clockcontrol_sb = &cc->clockcontrol_sb; ++ clockcontrol_pci = &cc->clockcontrol_pci; ++ clockcontrol_m2 = &cc->clockcontrol_m2; ++ } ++ } else ++ goto done; + -+ /* mask and set */ -+ if (mask || val) { -+ w = (R_SBREG(si, &sb->sbtmstatehigh) & ~mask) | val; -+ W_SBREG(si, &sb->sbtmstatehigh, w); ++ if (pll_type == PLL_TYPE6) { ++ /* Silence compilers */ ++ orig_n = orig_sb = orig_pci = 0; ++ } else { ++ /* Store the current clock register values */ ++ orig_n = R_REG(osh, clockcontrol_n); ++ orig_sb = R_REG(osh, clockcontrol_sb); ++ orig_pci = R_REG(osh, clockcontrol_pci); + } + -+ /* return the new value */ -+ return (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_FL_MASK); -+} -+ -+/* caller needs to take care of core-specific bist hazards */ -+int -+sb_corebist(sb_t *sbh, uint coreid, uint coreunit) -+{ -+ uint32 sblo; -+ uint coreidx; -+ sb_info_t *si; -+ int result = 0; ++ if (pll_type == PLL_TYPE1) { ++ /* Keep the current PCI clock if not specified */ ++ if (pciclock == 0) { ++ pciclock = sb_clock_rate(pll_type, R_REG(osh, clockcontrol_n), ++ R_REG(osh, clockcontrol_pci)); ++ pciclock = (pciclock <= 25000000) ? 25000000 : 33000000; ++ } + -+ si = SB_INFO(sbh); ++ /* Search for the closest MIPS clock less than or equal to a preferred value */ ++ for (i = 0; i < ARRAYSIZE(type1_table); i++) { ++ ASSERT(type1_table[i].mipsclock == ++ sb_clock_rate(pll_type, type1_table[i].n, ++ type1_table[i].sb)); ++ if (type1_table[i].mipsclock > mipsclock) ++ break; ++ } ++ if (i == 0) { ++ ret = FALSE; ++ goto done; ++ } else { ++ ret = TRUE; ++ i--; ++ } ++ ASSERT(type1_table[i].mipsclock <= mipsclock); + -+ coreidx = sb_findcoreidx(si, coreid, coreunit); -+ if (!GOODIDX(coreidx)) -+ result = BCME_ERROR; -+ else { -+ sblo = sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), 0, 0); -+ sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), ~0, (sblo | SBTML_FGC | SBTML_BE)); -+ -+ SPINWAIT(((sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatehigh), 0, 0) & SBTMH_BISTD) == 0), 100000); -+ -+ if (sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatehigh), 0, 0) & SBTMH_BISTF) -+ result = BCME_ERROR; ++ /* No PLL change */ ++ if ((orig_n == type1_table[i].n) && ++ (orig_sb == type1_table[i].sb) && ++ (orig_pci == type1_table[i].pci33)) ++ goto done; + -+ sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), ~0, sblo); -+ } ++ /* Set the PLL controls */ ++ W_REG(osh, clockcontrol_n, type1_table[i].n); ++ W_REG(osh, clockcontrol_sb, type1_table[i].sb); ++ if (pciclock == 25000000) ++ W_REG(osh, clockcontrol_pci, type1_table[i].pci25); ++ else ++ W_REG(osh, clockcontrol_pci, type1_table[i].pci33); + -+ return result; -+} ++ /* Reset */ ++ sb_watchdog(sbh, 1); ++ while (1); ++ } else if (pll_type == PLL_TYPE3) { ++ /* 5350 */ ++ if (sb_chip(sbh) != BCM5365_CHIP_ID) { ++ /* ++ * Search for the closest MIPS clock less than or equal to ++ * a preferred value. ++ */ ++ for (i = 0; i < ARRAYSIZE(type3_table); i++) { ++ if (type3_table[i].mipsclock > mipsclock) ++ break; ++ } ++ if (i == 0) { ++ ret = FALSE; ++ goto done; ++ } else { ++ ret = TRUE; ++ i--; ++ } ++ ASSERT(type3_table[i].mipsclock <= mipsclock); + -+bool -+sb_iscoreup(sb_t *sbh) -+{ -+ sb_info_t *si; -+ sbconfig_t *sb; ++ /* No PLL change */ ++ orig_m2 = R_REG(osh, &cc->clockcontrol_m2); ++ if ((orig_n == type3_table[i].n) && ++ (orig_m2 == type3_table[i].m2)) { ++ goto done; ++ } + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++ /* Set the PLL controls */ ++ W_REG(osh, clockcontrol_n, type3_table[i].n); ++ W_REG(osh, clockcontrol_m2, type3_table[i].m2); + -+ return ((R_SBREG(si, &(sb)->sbtmstatelow) & (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK); -+} ++ /* Reset */ ++ sb_watchdog(sbh, 1); ++ while (1); ++ } ++ } else if ((pll_type == PLL_TYPE2) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE6) || ++ (pll_type == PLL_TYPE7)) { ++ n4m_table_t *table = NULL, *te; ++ uint tabsz = 0; + -+/* -+ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, -+ * switch back to the original core, and return the new value. -+ */ -+static uint -+sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val) -+{ -+ uint origidx; -+ uint32 *r; -+ uint w; -+ uint intr_val = 0; ++ ASSERT(cc); + -+ ASSERT(GOODIDX(coreidx)); -+ ASSERT(regoff < SB_CORE_SIZE); -+ ASSERT((val & ~mask) == 0); ++ orig_mips = R_REG(osh, &cc->clockcontrol_m3); + -+ INTR_OFF(si, intr_val); ++ switch (pll_type) { ++ case PLL_TYPE6: { ++ uint32 new_mips = 0; + -+ /* save current core index */ -+ origidx = sb_coreidx(&si->sb); ++ ret = TRUE; ++ if (mipsclock <= SB2MIPS_T6(CC_T6_M1)) ++ new_mips = CC_T6_MMASK; + -+ /* switch core */ -+ r = (uint32*) ((uchar*) sb_setcoreidx(&si->sb, coreidx) + regoff); ++ if (orig_mips == new_mips) ++ goto done; + -+ /* mask and set */ -+ if (mask || val) { -+ if (regoff >= SBCONFIGOFF) { -+ w = (R_SBREG(si, r) & ~mask) | val; -+ W_SBREG(si, r, w); -+ } else { -+ w = (R_REG(r) & ~mask) | val; -+ W_REG(r, w); ++ W_REG(osh, &cc->clockcontrol_m3, new_mips); ++ goto end_fill; ++ } ++ case PLL_TYPE2: ++ table = type2_table; ++ tabsz = ARRAYSIZE(type2_table); ++ break; ++ case PLL_TYPE4: ++ table = type4_table; ++ tabsz = ARRAYSIZE(type4_table); ++ break; ++ case PLL_TYPE7: ++ table = type7_table; ++ tabsz = ARRAYSIZE(type7_table); ++ break; ++ default: ++ ASSERT("No table for plltype" == NULL); ++ break; + } -+ } + -+ /* readback */ -+ if (regoff >= SBCONFIGOFF) -+ w = R_SBREG(si, r); -+ else -+ w = R_REG(r); ++ /* Store the current clock register values */ ++ orig_m2 = R_REG(osh, &cc->clockcontrol_m2); ++ orig_ratio_parm = 0; ++ orig_ratio_cfg = 0; + -+ /* restore core index */ -+ if (origidx != coreidx) -+ sb_setcoreidx(&si->sb, origidx); ++ /* Look up current ratio */ ++ for (i = 0; i < tabsz; i++) { ++ if ((orig_n == table[i].n) && ++ (orig_sb == table[i].sb) && ++ (orig_pci == table[i].pci33) && ++ (orig_m2 == table[i].m2) && ++ (orig_mips == table[i].m3)) { ++ orig_ratio_parm = table[i].ratio_parm; ++ orig_ratio_cfg = table[i].ratio_cfg; ++ break; ++ } ++ } + -+ INTR_RESTORE(si, intr_val); -+ return (w); -+} ++ /* Search for the closest MIPS clock greater or equal to a preferred value */ ++ for (i = 0; i < tabsz; i++) { ++ ASSERT(table[i].mipsclock == ++ sb_clock_rate(pll_type, table[i].n, table[i].m3)); ++ if ((mipsclock <= table[i].mipsclock) && ++ ((sbclock == 0) || (sbclock <= table[i].sbclock))) ++ break; ++ } ++ if (i == tabsz) { ++ ret = FALSE; ++ goto done; ++ } else { ++ te = &table[i]; ++ ret = TRUE; ++ } + -+#define DWORD_ALIGN(x) (x & ~(0x03)) -+#define BYTE_POS(x) (x & 0x3) -+#define WORD_POS(x) (x & 0x1) ++ /* No PLL change */ ++ if ((orig_n == te->n) && ++ (orig_sb == te->sb) && ++ (orig_pci == te->pci33) && ++ (orig_m2 == te->m2) && ++ (orig_mips == te->m3)) ++ goto done; + -+#define BYTE_SHIFT(x) (8 * BYTE_POS(x)) -+#define WORD_SHIFT(x) (16 * WORD_POS(x)) ++ /* Set the PLL controls */ ++ W_REG(osh, clockcontrol_n, te->n); ++ W_REG(osh, clockcontrol_sb, te->sb); ++ W_REG(osh, clockcontrol_pci, te->pci33); ++ W_REG(osh, &cc->clockcontrol_m2, te->m2); ++ W_REG(osh, &cc->clockcontrol_m3, te->m3); + -+#define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF) -+#define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF) ++ /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */ ++ if ((pll_type == PLL_TYPE7) && (te->sb != te->m2) && ++ (sb_clock_rate(pll_type, te->n, te->m2) == 120000000)) ++ W_REG(osh, &cc->chipcontrol, ++ R_REG(osh, &cc->chipcontrol) | 0x100); + -+#define read_pci_cfg_byte(a) \ -+ (BYTE_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xff) ++ /* No ratio change */ ++ if (sb_chip(sbh) != BCM4785_CHIP_ID) { ++ if (orig_ratio_parm == te->ratio_parm) ++ goto end_fill; ++ } + -+#define read_pci_cfg_write(a) \ -+ (WORD_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xffff) ++ /* Preload the code into the cache */ ++ icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize); ++ if (sb_chip(sbh) == BCM4785_CHIP_ID) { ++ start = ((ulong) &&start_fill_4785) & ~(ic_lsize - 1); ++ end = ((ulong) &&end_fill_4785 + (ic_lsize - 1)) & ~(ic_lsize - 1); ++ } ++ else { ++ start = ((ulong) &&start_fill) & ~(ic_lsize - 1); ++ end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1); ++ } ++ while (start < end) { ++ cache_op(start, Fill_I); ++ start += ic_lsize; ++ } + ++ /* Copy the handler */ ++ start = (ulong) &handler; ++ end = (ulong) &afterhandler; ++ dst = KSEG1ADDR(0x180); ++ for (i = 0; i < (end - start); i += 4) ++ *((ulong *)(dst + i)) = *((ulong *)(start + i)); + -+/* return TRUE if requested capability exists in the PCI config space */ -+static bool -+sb_find_pci_capability(sb_info_t *si, uint8 req_cap_id, uchar *buf, uint32 *buflen) -+{ -+ uint8 cap_id; -+ uint8 cap_ptr; -+ uint32 bufsize; -+ uint8 byte_val; ++ /* Preload the handler into the cache one line at a time */ ++ for (i = 0; i < (end - start); i += ic_lsize) ++ cache_op(dst + i, Fill_I); + -+ if (BUSTYPE(si->sb.bustype) != PCI_BUS) -+ return FALSE; ++ /* Clear BEV bit */ ++ MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV); + -+ /* check for Header type 0*/ -+ byte_val = read_pci_cfg_byte(PCI_CFG_HDR); -+ if ((byte_val & 0x7f) != PCI_HEADER_NORMAL) -+ return FALSE; ++ /* Enable interrupts */ ++ MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE)); + -+ /* check if the capability pointer field exists */ -+ byte_val = read_pci_cfg_byte(PCI_CFG_STAT); -+ if (!(byte_val & PCI_CAPPTR_PRESENT)) -+ return FALSE; ++ /* 4785 clock freq change procedures */ ++ if (sb_chip(sbh) == BCM4785_CHIP_ID) { ++ start_fill_4785: ++ /* Switch to async */ ++ MTC0(C0_BROADCOM, 4, (1 << 22)); + -+ cap_ptr = read_pci_cfg_byte(PCI_CFG_CAPPTR); -+ /* check if the capability pointer is 0x00 */ -+ if (cap_ptr == 0x00) -+ return FALSE; ++ /* Set clock ratio in MIPS */ ++ *dll_r1 = (*dll_r1 & 0xfffffff0) | (te->d11_r1 - 1); ++ *dll_r2 = te->d11_r2; + ++ /* Enable new settings in MIPS */ ++ *dll_r1 = *dll_r1 | 0xc0000000; + -+ /* loop thr'u the capability list and see if the pcie capabilty exists */ ++ /* Set active cfg */ ++ MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) | (1 << 3) | 1); + -+ cap_id = read_pci_cfg_byte(cap_ptr); ++ /* Fake soft reset (clock cfg registers not reset) */ ++ MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2)); + -+ while (cap_id != req_cap_id) { -+ cap_ptr = read_pci_cfg_byte((cap_ptr+1)); -+ if (cap_ptr == 0x00) break; -+ cap_id = read_pci_cfg_byte(cap_ptr); -+ } -+ if (cap_id != req_cap_id) { -+ return FALSE; -+ } -+ /* found the caller requested capability */ -+ if ((buf != NULL) && (buflen != NULL)) { -+ bufsize = *buflen; -+ if (!bufsize) goto end; -+ *buflen = 0; -+ /* copy the cpability data excluding cap ID and next ptr */ -+ cap_ptr += 2; -+ if ((bufsize + cap_ptr) > SZPCR) -+ bufsize = SZPCR - cap_ptr; -+ *buflen = bufsize; -+ while (bufsize--) { -+ *buf = read_pci_cfg_byte(cap_ptr); -+ cap_ptr++; -+ buf++; -+ } -+ } -+end: -+ return TRUE; -+} ++ /* Clear active cfg */ ++ MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) & ~(1 << 3)); + -+/* return TRUE if PCIE capability exists the pci config space */ -+static bool -+sb_ispcie(sb_info_t *si) -+{ -+ return(sb_find_pci_capability(si, PCI_CAP_PCIECAP_ID, NULL, NULL)); -+} ++ /* set watchdog timer */ ++ W_REG(osh, &cc->watchdog, 20); ++ (void) R_REG(osh, &cc->chipid); + -+/* scan the sb enumerated space to identify all cores */ -+static void -+BCMINITFN(sb_scan)(sb_info_t *si) -+{ -+ uint origidx; -+ uint i; -+ bool pci; -+ bool pcie; -+ uint pciidx; -+ uint pcieidx; -+ uint pcirev; -+ uint pcierev; ++ /* wait for timer interrupt */ ++ __asm__ __volatile__( ++ ".set\tmips3\n\t" ++ "sync\n\t" ++ "wait\n\t" ++ ".set\tmips0"); ++ end_fill_4785: ++ while (1); ++ } ++ /* Generic clock freq change procedures */ ++ else { ++ /* Enable MIPS timer interrupt */ ++ if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) && ++ !(mipsr = sb_setcore(sbh, SB_MIPS33, 0))) ++ ASSERT(mipsr); ++ W_REG(osh, &mipsr->intmask, 1); + ++ start_fill: ++ /* step 1, set clock ratios */ ++ MTC0(C0_BROADCOM, 3, te->ratio_parm); ++ MTC0(C0_BROADCOM, 1, te->ratio_cfg); + ++ /* step 2: program timer intr */ ++ W_REG(osh, &mipsr->timer, 100); ++ (void) R_REG(osh, &mipsr->timer); + -+ /* numcores should already be set */ -+ ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES)); ++ /* step 3, switch to async */ ++ sync_mode = MFC0(C0_BROADCOM, 4); ++ MTC0(C0_BROADCOM, 4, 1 << 22); + -+ /* save current core index */ -+ origidx = sb_coreidx(&si->sb); ++ /* step 4, set cfg active */ ++ MTC0(C0_BROADCOM, 2, (1 << 3) | 1); + -+ si->sb.buscorerev = NOREV; -+ si->sb.buscoreidx = BADIDX; ++ /* steps 5 & 6 */ ++ __asm__ __volatile__( ++ ".set\tmips3\n\t" ++ "wait\n\t" ++ ".set\tmips0"); + -+ si->gpioidx = BADIDX; ++ /* step 7, clear cfg active */ ++ MTC0(C0_BROADCOM, 2, 0); + -+ pci = pcie = FALSE; -+ pcirev = pcierev = NOREV; -+ pciidx = pcieidx = BADIDX; ++ /* Additional Step: set back to orig sync mode */ ++ MTC0(C0_BROADCOM, 4, sync_mode); + -+ for (i = 0; i < si->numcores; i++) { -+ sb_setcoreidx(&si->sb, i); -+ si->coreid[i] = sb_coreid(&si->sb); ++ /* step 8, fake soft reset */ ++ MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2)); + -+ if (si->coreid[i] == SB_PCI) { -+ pciidx = i; -+ pcirev = sb_corerev(&si->sb); -+ pci = TRUE; -+ } else if (si->coreid[i] == SB_PCIE) { -+ pcieidx = i; -+ pcierev = sb_corerev(&si->sb); -+ pcie = TRUE; -+ } else if (si->coreid[i] == SB_PCMCIA) { -+ si->sb.buscorerev = sb_corerev(&si->sb); -+ si->sb.buscoretype = si->coreid[i]; -+ si->sb.buscoreidx = i; ++ end_fill: ++ /* set watchdog timer */ ++ W_REG(osh, &cc->watchdog, 20); ++ (void) R_REG(osh, &cc->chipid); ++ ++ /* wait for timer interrupt */ ++ __asm__ __volatile__( ++ ".set\tmips3\n\t" ++ "sync\n\t" ++ "wait\n\t" ++ ".set\tmips0"); ++ while (1); + } + } -+ if (pci && pcie) { -+ if (sb_ispcie(si)) -+ pci = FALSE; -+ else -+ pcie = FALSE; -+ } -+ if (pci) { -+ si->sb.buscoretype = SB_PCI; -+ si->sb.buscorerev = pcirev; -+ si->sb.buscoreidx = pciidx; -+ } -+ else if (pcie) { -+ si->sb.buscoretype = SB_PCIE; -+ si->sb.buscorerev = pcierev; -+ si->sb.buscoreidx = pcieidx; -+ } + -+ /* -+ * Find the gpio "controlling core" type and index. -+ * Precedence: -+ * - if there's a chip common core - use that -+ * - else if there's a pci core (rev >= 2) - use that -+ * - else there had better be an extif core (4710 only) -+ */ -+ if (GOODIDX(sb_findcoreidx(si, SB_CC, 0))) { -+ si->gpioidx = sb_findcoreidx(si, SB_CC, 0); -+ si->gpioid = SB_CC; -+ } else if (PCI(si) && (si->sb.buscorerev >= 2)) { -+ si->gpioidx = si->sb.buscoreidx; -+ si->gpioid = SB_PCI; -+ } else if (sb_findcoreidx(si, SB_EXTIF, 0)) { -+ si->gpioidx = sb_findcoreidx(si, SB_EXTIF, 0); -+ si->gpioid = SB_EXTIF; -+ } else -+ ASSERT(si->gpioidx != BADIDX); ++done: ++ /* Enable 4785 DLL */ ++ if (sb_chip(sbh) == BCM4785_CHIP_ID) { ++ uint32 tmp; + -+ /* return to original core index */ -+ sb_setcoreidx(&si->sb, origidx); -+} ++ /* set mask to 1e, enable DLL (bit 0) */ ++ *dll_ctrl |= 0x0041e021; + -+/* may be called with core in reset */ -+void -+sb_detach(sb_t *sbh) -+{ -+ sb_info_t *si; -+ uint idx; ++ /* enable aggressive hardware mode */ ++ *dll_ctrl |= 0x00000080; + -+ si = SB_INFO(sbh); ++ /* wait for lock flag to clear */ ++ while ((*dll_ctrl & 0x2) == 0); + -+ if (si == NULL) -+ return; ++ /* clear sticky flags (clear on write 1) */ ++ tmp = *dll_ctrl; ++ *dll_ctrl = tmp; + -+ if (BUSTYPE(si->sb.bustype) == SB_BUS) -+ for (idx = 0; idx < SB_MAXCORES; idx++) -+ if (si->regs[idx]) { -+ REG_UNMAP(si->regs[idx]); -+ si->regs[idx] = NULL; -+ } ++ /* set mask to 5b'10001 */ ++ *dll_ctrl = (*dll_ctrl & 0xfffc1fff) | 0x00022000; + -+ if (si != &ksi) -+ MFREE(si->osh, si, sizeof (sb_info_t)); -+} ++ /* enable sync mode */ ++ MTC0(C0_BROADCOM, 4, MFC0(C0_BROADCOM, 4) & 0xfe3fffff); ++ (void)MFC0(C0_BROADCOM, 4); ++ } + -+/* use pci dev id to determine chip id for chips not having a chipcommon core */ -+static uint -+BCMINITFN(sb_pcidev2chip)(uint pcidev) -+{ -+ if ((pcidev >= BCM4710_DEVICE_ID) && (pcidev <= BCM47XX_USB_ID)) -+ return (BCM4710_DEVICE_ID); -+ if ((pcidev >= BCM4402_DEVICE_ID) && (pcidev <= BCM4402_V90_ID)) -+ return (BCM4402_DEVICE_ID); -+ if (pcidev == BCM4401_ENET_ID) -+ return (BCM4402_DEVICE_ID); -+ if ((pcidev >= BCM4307_V90_ID) && (pcidev <= BCM4307_D11B_ID)) -+ return (BCM4307_DEVICE_ID); -+ if (pcidev == BCM4301_DEVICE_ID) -+ return (BCM4301_DEVICE_ID); ++ /* switch back to previous core */ ++ sb_setcoreidx(sbh, idx); + -+ return (0); ++ return ret; +} + -+/* convert chip number to number of i/o cores */ -+static uint -+BCMINITFN(sb_chip2numcores)(uint chip) ++void ++BCMINITFN(enable_pfc)(uint32 mode) +{ -+ if (chip == BCM4710_DEVICE_ID) -+ return (9); -+ if (chip == BCM4402_DEVICE_ID) -+ return (3); -+ if ((chip == BCM4301_DEVICE_ID) || (chip == BCM4307_DEVICE_ID)) -+ return (5); -+ if (chip == BCM4306_DEVICE_ID) /* < 4306c0 */ -+ return (6); -+ if (chip == BCM4704_DEVICE_ID) -+ return (9); -+ if (chip == BCM5365_DEVICE_ID) -+ return (7); ++ ulong start, end; ++ uint ic_size, ic_lsize; + -+ SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip)); -+ ASSERT(0); -+ return (1); -+} ++ /* If auto then choose the correct mode for this ++ * platform, currently we only ever select one mode ++ */ ++ if (mode == PFC_AUTO) ++ mode = PFC_INST; + -+/* return index of coreid or BADIDX if not found */ -+static uint -+sb_findcoreidx( sb_info_t *si, uint coreid, uint coreunit) -+{ -+ uint found; -+ uint i; ++ icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize); + -+ found = 0; ++ /* enable prefetch cache if available */ ++ if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) { ++ start = ((ulong) &&setpfc_start) & ~(ic_lsize - 1); ++ end = ((ulong) &&setpfc_end + (ic_lsize - 1)) & ~(ic_lsize - 1); + -+ for (i = 0; i < si->numcores; i++) -+ if (si->coreid[i] == coreid) { -+ if (found == coreunit) -+ return (i); -+ found++; ++ /* Preload setpfc code into the cache one line at a time */ ++ while (start < end) { ++ cache_op(start, Fill_I); ++ start += ic_lsize; + } + -+ return (BADIDX); ++ /* Now set the pfc */ ++ setpfc_start: ++ /* write range */ ++ *(volatile uint32 *)PFC_CR1 = 0xffff0000; ++ ++ /* enable */ ++ *(volatile uint32 *)PFC_CR0 = mode; ++ setpfc_end: ++ /* Compiler foder */ ++ ic_size = 0; ++ } +} + -+/* -+ * this function changes logical "focus" to the indiciated core, -+ * must be called with interrupt off. -+ * Moreover, callers should keep interrupts off during switching out of and back to d11 core -+ */ -+void* -+sb_setcoreidx(sb_t *sbh, uint coreidx) ++/* returns the ncdl value to be programmed into sdram_ncdl for calibration */ ++uint32 ++BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh) +{ -+ sb_info_t *si; -+ uint32 sbaddr; -+ uint8 tmp; -+ -+ si = SB_INFO(sbh); -+ -+ if (coreidx >= si->numcores) -+ return (NULL); -+ -+ /* -+ * If the user has provided an interrupt mask enabled function, -+ * then assert interrupts are disabled before switching the core. -+ */ -+ ASSERT((si->intrsenabled_fn == NULL) || !(*(si)->intrsenabled_fn)((si)->intr_arg)); ++ osl_t *osh; ++ sbmemcregs_t *memc; ++ uint32 ret = 0; ++ uint32 config, rd, wr, misc, dqsg, cd, sm, sd; ++ uint idx, rev; + -+ sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE); ++ osh = sb_osh(sbh); + -+ switch (BUSTYPE(si->sb.bustype)) { -+ case SB_BUS: -+ /* map new one */ -+ if (!si->regs[coreidx]) { -+ si->regs[coreidx] = (void*)REG_MAP(sbaddr, SB_CORE_SIZE); -+ ASSERT(GOODREGS(si->regs[coreidx])); -+ } -+ si->curmap = si->regs[coreidx]; -+ break; ++ idx = sb_coreidx(sbh); + -+ case PCI_BUS: -+ /* point bar0 window */ -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, 4, sbaddr); -+ break; ++ memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0); ++ if (memc == 0) ++ goto out; + -+ case PCMCIA_BUS: -+ tmp = (sbaddr >> 12) & 0x0f; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1); -+ tmp = (sbaddr >> 16) & 0xff; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1); -+ tmp = (sbaddr >> 24) & 0xff; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1); -+ break; -+#ifdef BCMJTAG -+ case JTAG_BUS: -+ /* map new one */ -+ if (!si->regs[coreidx]) { -+ si->regs[coreidx] = (void *)sbaddr; -+ ASSERT(GOODREGS(si->regs[coreidx])); -+ } -+ si->curmap = si->regs[coreidx]; -+ break; -+#endif /* BCMJTAG */ ++ rev = sb_corerev(sbh); ++ ++ config = R_REG(osh, &memc->config); ++ wr = R_REG(osh, &memc->wrncdlcor); ++ rd = R_REG(osh, &memc->rdncdlcor); ++ misc = R_REG(osh, &memc->miscdlyctl); ++ dqsg = R_REG(osh, &memc->dqsgatencdl); ++ ++ rd &= MEMC_RDNCDLCOR_RD_MASK; ++ wr &= MEMC_WRNCDLCOR_WR_MASK; ++ dqsg &= MEMC_DQSGATENCDL_G_MASK; ++ ++ if (config & MEMC_CONFIG_DDR) { ++ ret = (wr << 16) | (rd << 8) | dqsg; ++ } else { ++ if (rev > 0) ++ cd = rd; ++ else ++ cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD); ++ sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT; ++ sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT; ++ ret = (sm << 16) | (sd << 8) | cd; + } + -+ si->curidx = coreidx; ++out: ++ /* switch back to previous core */ ++ sb_setcoreidx(sbh, idx); + -+ return (si->curmap); ++ return ret; +} + -+/* -+ * this function changes logical "focus" to the indiciated core, -+ * must be called with interrupt off. -+ * Moreover, callers should keep interrupts off during switching out of and back to d11 core ++#if defined(BCMPERFSTATS) ++/* ++ * CP0 Register 25 supports 4 semi-independent 32bit performance counters. ++ * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?) ++ * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters ++ * $25 select 6 is the global perf control register. + */ -+void* -+sb_setcore(sb_t *sbh, uint coreid, uint coreunit) -+{ -+ sb_info_t *si; -+ uint idx; -+ -+ si = SB_INFO(sbh); -+ idx = sb_findcoreidx(si, coreid, coreunit); -+ if (!GOODIDX(idx)) -+ return (NULL); ++/* enable and start instruction counting */ + -+ return (sb_setcoreidx(sbh, idx)); ++void ++hndmips_perf_instrcount_enable() ++{ ++ MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */ ++ MTC0(C0_PERFORMANCE, 4, ++ 0x8044 | MFC0(C0_PERFORMANCE, 4)); /* enable instruction counting for counter 0 */ ++ MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */ +} + -+/* return chip number */ -+uint -+BCMINITFN(sb_chip)(sb_t *sbh) ++/* enable and start I$ hit and I$ miss counting */ ++void ++hndmips_perf_icachecount_enable(void) +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); -+ return (si->sb.chip); ++ MTC0(C0_PERFORMANCE, 6, 0x80000218); /* enable I$ counting */ ++ MTC0(C0_PERFORMANCE, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */ ++ MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # I$ hits */ ++ MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # I$ misses */ +} + -+/* return chip revision number */ -+uint -+BCMINITFN(sb_chiprev)(sb_t *sbh) ++/* enable and start D$ hit and I$ miss counting */ ++void ++hndmips_perf_dcachecount_enable(void) +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); -+ return (si->sb.chiprev); ++ MTC0(C0_PERFORMANCE, 6, 0x80000211); /* enable D$ counting */ ++ MTC0(C0_PERFORMANCE, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */ ++ MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # D$ hits */ ++ MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # D$ misses */ +} + -+/* return chip common revision number */ -+uint -+BCMINITFN(sb_chipcrev)(sb_t *sbh) ++void ++hndmips_perf_icache_miss_enable() +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); -+ return (si->sb.ccrev); ++ MTC0(C0_PERFORMANCE, 4, ++ 0x80140000 | MFC0(C0_PERFORMANCE, 4)); /* enable cache misses counting for counter 1 */ ++ MTC0(C0_PERFORMANCE, 1, 0); /* zero counter one */ +} + -+/* return chip package option */ -+uint -+BCMINITFN(sb_chippkg)(sb_t *sbh) -+{ -+ sb_info_t *si; + -+ si = SB_INFO(sbh); -+ return (si->sb.chippkg); ++void ++hndmips_perf_icache_hit_enable() ++{ ++ MTC0(C0_PERFORMANCE, 5, 0x8018 | MFC0(C0_PERFORMANCE, 5)); ++ /* enable cache hits counting for counter 2 */ ++ MTC0(C0_PERFORMANCE, 2, 0); /* zero counter 2 */ +} + -+/* return PCI core rev. */ -+uint -+BCMINITFN(sb_pcirev)(sb_t *sbh) ++uint32 ++hndmips_perf_read_instrcount() +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); -+ return (si->sb.buscorerev); ++ return -(long)(MFC0(C0_PERFORMANCE, 0)); +} + -+bool -+BCMINITFN(sb_war16165)(sb_t *sbh) ++uint32 ++hndmips_perf_read_cache_miss() +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); -+ -+ return (PCI(si) && (si->sb.buscorerev <= 10)); ++ return -(long)(MFC0(C0_PERFORMANCE, 1)); +} + -+static void -+BCMINITFN(sb_war30841)(sb_info_t *si) ++uint32 ++hndmips_perf_read_cache_hit() +{ -+ sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); -+ sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); -+ sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); ++ return -(long)(MFC0(C0_PERFORMANCE, 2)); +} + -+/* return PCMCIA core rev. */ -+uint -+BCMINITFN(sb_pcmciarev)(sb_t *sbh) -+{ -+ sb_info_t *si; ++#endif /* BCMINTERNAL | BCMPERFSTATS */ +diff -urN linux.old/arch/mips/bcm947xx/sbpci.c linux.dev/arch/mips/bcm947xx/sbpci.c +--- linux.old/arch/mips/bcm947xx/sbpci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/sbpci.c 2006-05-02 17:37:13.000000000 +0200 +@@ -0,0 +1,768 @@ ++/* ++ * Low-Level PCI and SB support for BCM47xx ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: hndpci.c,v 1.1.1.3 2006/04/08 06:13:39 honor Exp $ ++ */ + -+ si = SB_INFO(sbh); -+ return (si->sb.buscorerev); -+} ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+/* return board vendor id */ -+uint -+BCMINITFN(sb_boardvendor)(sb_t *sbh) -+{ -+ sb_info_t *si; ++/* debug/trace */ ++#ifdef BCMDBG_PCI ++#define PCI_MSG(args) printf args ++#else ++#define PCI_MSG(args) ++#endif /* BCMDBG_PCI */ + -+ si = SB_INFO(sbh); -+ return (si->sb.boardvendor); -+} ++/* Can free sbpci_init() memory after boot */ ++#ifndef linux ++#define __init ++#endif /* linux */ + -+/* return boardtype */ -+uint -+BCMINITFN(sb_boardtype)(sb_t *sbh) ++/* Emulated configuration space */ ++typedef struct { ++ int n; ++ uint size0; ++ uint size1; ++ uint size2; ++ uint size3; ++} sb_bar_cfg_t; ++static pci_config_regs sb_config_regs[SB_MAXCORES]; ++static sb_bar_cfg_t sb_bar_cfg[SB_MAXCORES]; ++ ++/* Links to emulated and real PCI configuration spaces */ ++#define MAXFUNCS 2 ++typedef struct { ++ pci_config_regs *emu; /* emulated PCI config */ ++ pci_config_regs *pci; /* real PCI config */ ++ sb_bar_cfg_t *bar; /* region sizes */ ++} sb_pci_cfg_t; ++static sb_pci_cfg_t sb_pci_cfg[SB_MAXCORES][MAXFUNCS]; ++ ++/* Special emulated config space for non-existing device */ ++static pci_config_regs sb_pci_null = { 0xffff, 0xffff }; ++ ++/* Banned cores */ ++static uint16 pci_ban[SB_MAXCORES] = { 0 }; ++static uint pci_banned = 0; ++ ++/* CardBus mode */ ++static bool cardbus = FALSE; ++ ++/* Disable PCI host core */ ++static bool pci_disabled = FALSE; ++ ++/* Host bridge slot #, default to 0 */ ++static uint8 pci_hbslot = 0; ++ ++/* Internal macros */ ++#define PCI_SLOTAD_MAP 16 /* SLOT mapps to AD */ ++#define PCI_HBSBCFG_REV 8 /* MIN. core rev. required to ++ * access host bridge PCI cfg space ++ * from SB ++ */ ++ ++/* ++ * Functions for accessing external PCI configuration space ++ */ ++ ++/* Assume one-hot slot wiring */ ++#define PCI_SLOT_MAX 16 /* Max. PCI Slots */ ++ ++static uint32 ++config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off) +{ -+ sb_info_t *si; -+ char *var; ++ uint coreidx; ++ sbpciregs_t *regs; ++ uint32 addr = 0; ++ osl_t *osh; + -+ si = SB_INFO(sbh); ++ /* CardBusMode supports only one device */ ++ if (cardbus && dev > 1) ++ return 0; + -+ if (BUSTYPE(si->sb.bustype) == SB_BUS && si->sb.boardtype == 0xffff) { -+ /* boardtype format is a hex string */ -+ si->sb.boardtype = getintvar(NULL, "boardtype"); ++ osh = sb_osh(sbh); + -+ /* backward compatibility for older boardtype string format */ -+ if ((si->sb.boardtype == 0) && (var = getvar(NULL, "boardtype"))) { -+ if (!strcmp(var, "bcm94710dev")) -+ si->sb.boardtype = BCM94710D_BOARD; -+ else if (!strcmp(var, "bcm94710ap")) -+ si->sb.boardtype = BCM94710AP_BOARD; -+ else if (!strcmp(var, "bu4710")) -+ si->sb.boardtype = BU4710_BOARD; -+ else if (!strcmp(var, "bcm94702mn")) -+ si->sb.boardtype = BCM94702MN_BOARD; -+ else if (!strcmp(var, "bcm94710r1")) -+ si->sb.boardtype = BCM94710R1_BOARD; -+ else if (!strcmp(var, "bcm94710r4")) -+ si->sb.boardtype = BCM94710R4_BOARD; -+ else if (!strcmp(var, "bcm94702cpci")) -+ si->sb.boardtype = BCM94702CPCI_BOARD; -+ else if (!strcmp(var, "bcm95380_rr")) -+ si->sb.boardtype = BCM95380RR_BOARD; ++ coreidx = sb_coreidx(sbh); ++ regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0); ++ ++ /* Type 0 transaction */ ++ if (bus == 1) { ++ /* Skip unwired slots */ ++ if (dev < PCI_SLOT_MAX) { ++ uint32 win; ++ ++ /* Slide the PCI window to the appropriate slot */ ++ win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK)); ++ W_REG(osh, ®s->sbtopci1, win); ++ addr = SB_PCI_CFG | ++ ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) | ++ (func << PCICFG_FUN_SHIFT) | ++ (off & ~3); + } ++ } else { ++ /* Type 1 transaction */ ++ W_REG(osh, ®s->sbtopci1, SBTOPCI_CFG1); ++ addr = SB_PCI_CFG | ++ (bus << PCICFG_BUS_SHIFT) | ++ (dev << PCICFG_SLOT_SHIFT) | ++ (func << PCICFG_FUN_SHIFT) | ++ (off & ~3); ++ } ++ ++ sb_setcoreidx(sbh, coreidx); ++ ++ return addr; ++} ++ ++/* ++ * Read host bridge PCI config registers from Silicon Backplane (>=rev8). ++ * ++ * It returns TRUE to indicate that access to the host bridge's pci config ++ * from SB is ok, and values in 'addr' and 'val' are valid. ++ * ++ * It can only read registers at multiple of 4-bytes. Callers must pick up ++ * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects ++ * the register address where value in 'val' is read. ++ */ ++static bool ++sb_pcihb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, ++ uint32 **addr, uint32 *val) ++{ ++ sbpciregs_t *regs; ++ osl_t *osh; ++ uint coreidx; ++ bool ret = FALSE; ++ ++ /* sanity check */ ++ ASSERT(bus == 1); ++ ASSERT(dev == pci_hbslot); ++ ASSERT(func == 0); ++ ++ osh = sb_osh(sbh); ++ ++ /* read pci config when core rev >= 8 */ ++ coreidx = sb_coreidx(sbh); ++ regs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0); ++ if (regs && sb_corerev(sbh) >= PCI_HBSBCFG_REV) { ++ *addr = (uint32 *)®s->pcicfg[func][off >> 2]; ++ *val = R_REG(osh, *addr); ++ ret = TRUE; + } ++ sb_setcoreidx(sbh, coreidx); + -+ return (si->sb.boardtype); ++ return ret; +} + -+/* return bus type of sbh device */ -+uint -+sb_bus(sb_t *sbh) ++int ++extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) +{ -+ sb_info_t *si; ++ uint32 addr = 0, *reg = NULL, val; ++ int ret = 0; + -+ si = SB_INFO(sbh); -+ return (si->sb.bustype); -+} ++ /* ++ * Set value to -1 when: ++ * flag 'pci_disabled' is true; ++ * value of 'addr' is zero; ++ * REG_MAP() fails; ++ * BUSPROBE() fails; ++ */ ++ if (pci_disabled) ++ val = 0xffffffff; ++ else if (bus == 1 && dev == pci_hbslot && func == 0 && ++ sb_pcihb_read_config(sbh, bus, dev, func, off, ®, &val)) ++ ; ++ else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) || ++ ((reg = (uint32 *)REG_MAP(addr, len)) == 0) || ++ (BUSPROBE(val, reg) != 0)) ++ val = 0xffffffff; + -+/* return bus core type */ -+uint -+sb_buscoretype(sb_t *sbh) -+{ -+ sb_info_t *si; ++ PCI_MSG(("%s: 0x%x <= 0x%p(0x%x), len %d, off 0x%x, buf 0x%p\n", ++ __FUNCTION__, val, reg, addr, len, off, buf)); + -+ si = SB_INFO(sbh); ++ val >>= 8 * (off & 3); ++ if (len == 4) ++ *((uint32 *) buf) = val; ++ else if (len == 2) ++ *((uint16 *) buf) = (uint16) val; ++ else if (len == 1) ++ *((uint8 *) buf) = (uint8) val; ++ else ++ ret = -1; + -+ return (si->sb.buscoretype); ++ if (reg && addr) ++ REG_UNMAP(reg); ++ ++ return ret; +} + -+/* return bus core revision */ -+uint -+sb_buscorerev(sb_t *sbh) ++int ++extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) +{ -+ sb_info_t *si; -+ si = SB_INFO(sbh); ++ osl_t *osh; ++ uint32 addr = 0, *reg = NULL, val; ++ int ret = 0; + -+ return (si->sb.buscorerev); -+} ++ osh = sb_osh(sbh); + -+/* return list of found cores */ -+uint -+sb_corelist(sb_t *sbh, uint coreid[]) -+{ -+ sb_info_t *si; ++ /* ++ * Ignore write attempt when: ++ * flag 'pci_disabled' is true; ++ * value of 'addr' is zero; ++ * REG_MAP() fails; ++ * BUSPROBE() fails; ++ */ ++ if (pci_disabled) ++ return 0; ++ else if (bus == 1 && dev == pci_hbslot && func == 0 && ++ sb_pcihb_read_config(sbh, bus, dev, func, off, ®, &val)) ++ ; ++ else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) || ++ ((reg = (uint32 *) REG_MAP(addr, len)) == 0) || ++ (BUSPROBE(val, reg) != 0)) ++ goto done; + -+ si = SB_INFO(sbh); ++ if (len == 4) ++ val = *((uint32 *) buf); ++ else if (len == 2) { ++ val &= ~(0xffff << (8 * (off & 3))); ++ val |= *((uint16 *) buf) << (8 * (off & 3)); ++ } else if (len == 1) { ++ val &= ~(0xff << (8 * (off & 3))); ++ val |= *((uint8 *) buf) << (8 * (off & 3)); ++ } else { ++ ret = -1; ++ goto done; ++ } + -+ bcopy((uchar*)si->coreid, (uchar*)coreid, (si->numcores * sizeof (uint))); -+ return (si->numcores); -+} ++ PCI_MSG(("%s: 0x%x => 0x%p\n", __FUNCTION__, val, reg)); + -+/* return current register mapping */ -+void * -+sb_coreregs(sb_t *sbh) -+{ -+ sb_info_t *si; ++ W_REG(osh, reg, val); + -+ si = SB_INFO(sbh); -+ ASSERT(GOODREGS(si->curmap)); ++done: ++ if (reg && addr) ++ REG_UNMAP(reg); + -+ return (si->curmap); ++ return ret; +} + -+ -+/* do buffered registers update */ -+void -+sb_commit(sb_t *sbh) ++/* ++ * Must access emulated PCI configuration at these locations even when ++ * the real PCI config space exists and is accessible. ++ * ++ * PCI_CFG_VID (0x00) ++ * PCI_CFG_DID (0x02) ++ * PCI_CFG_PROGIF (0x09) ++ * PCI_CFG_SUBCL (0x0a) ++ * PCI_CFG_BASECL (0x0b) ++ * PCI_CFG_HDR (0x0e) ++ * PCI_CFG_INT (0x3c) ++ * PCI_CFG_PIN (0x3d) ++ */ ++#define FORCE_EMUCFG(off, len) \ ++ ((off == PCI_CFG_VID) || (off == PCI_CFG_DID) || \ ++ (off == PCI_CFG_PROGIF) || \ ++ (off == PCI_CFG_SUBCL) || (off == PCI_CFG_BASECL) || \ ++ (off == PCI_CFG_HDR) || \ ++ (off == PCI_CFG_INT) || (off == PCI_CFG_PIN)) ++ ++/* Sync the emulation registers and the real PCI config registers. */ ++static void ++sb_pcid_read_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg, ++ uint off, uint len) +{ -+ sb_info_t *si; -+ uint origidx; -+ uint intr_val = 0; ++ osl_t *osh; ++ uint oldidx; + -+ si = SB_INFO(sbh); ++ ASSERT(cfg); ++ ASSERT(cfg->emu); ++ ASSERT(cfg->pci); + -+ origidx = si->curidx; -+ ASSERT(GOODIDX(origidx)); ++ /* decide if real PCI config register access is necessary */ ++ if (FORCE_EMUCFG(off, len)) ++ return; + -+ INTR_OFF(si, intr_val); ++ osh = sb_osh(sbh); + -+ /* switch over to chipcommon core if there is one, else use pci */ -+ if (si->sb.ccrev != NOREV) { -+ chipcregs_t *ccregs = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0); ++ /* access to the real pci config space only when the core is up */ ++ oldidx = sb_coreidx(sbh); ++ sb_setcoreidx(sbh, coreidx); ++ if (sb_iscoreup(sbh)) { ++ if (len == 4) ++ *(uint32 *)((ulong)cfg->emu + off) = ++ htol32(R_REG(osh, (uint32 *)((ulong)cfg->pci + off))); ++ else if (len == 2) ++ *(uint16 *)((ulong)cfg->emu + off) = ++ htol16(R_REG(osh, (uint16 *)((ulong)cfg->pci + off))); ++ else if (len == 1) ++ *(uint8 *)((ulong)cfg->emu + off) = ++ R_REG(osh, (uint8 *)((ulong)cfg->pci + off)); ++ } ++ sb_setcoreidx(sbh, oldidx); ++} + -+ /* do the buffer registers update */ -+ W_REG(&ccregs->broadcastaddress, SB_COMMIT); -+ W_REG(&ccregs->broadcastdata, 0x0); -+ } else if (PCI(si)) { -+ sbpciregs_t *pciregs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0); ++static void ++sb_pcid_write_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg, ++ uint off, uint len) ++{ ++ osl_t *osh; ++ uint oldidx; + -+ /* do the buffer registers update */ -+ W_REG(&pciregs->bcastaddr, SB_COMMIT); -+ W_REG(&pciregs->bcastdata, 0x0); -+ } else -+ ASSERT(0); ++ ASSERT(cfg); ++ ASSERT(cfg->emu); ++ ASSERT(cfg->pci); + -+ /* restore core index */ -+ sb_setcoreidx(sbh, origidx); -+ INTR_RESTORE(si, intr_val); -+} ++ osh = sb_osh(sbh); + -+/* reset and re-enable a core */ -+void -+sb_core_reset(sb_t *sbh, uint32 bits) -+{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ volatile uint32 dummy; ++ /* decide if real PCI config register access is necessary */ ++ if (FORCE_EMUCFG(off, len)) ++ return; + -+ si = SB_INFO(sbh); -+ ASSERT(GOODREGS(si->curmap)); -+ sb = REGS2SB(si->curmap); ++ /* access to the real pci config space only when the core is up */ ++ oldidx = sb_coreidx(sbh); ++ sb_setcoreidx(sbh, coreidx); ++ if (sb_iscoreup(sbh)) { ++ if (len == 4) ++ W_REG(osh, (uint32 *)((ulong)cfg->pci + off), ++ ltoh32(*(uint32 *)((ulong)cfg->emu + off))); ++ else if (len == 2) ++ W_REG(osh, (uint16 *)((ulong)cfg->pci + off), ++ ltoh16(*(uint16 *)((ulong)cfg->emu + off))); ++ else if (len == 1) ++ W_REG(osh, (uint8 *)((ulong)cfg->pci + off), ++ *(uint8 *)((ulong)cfg->emu + off)); ++ } ++ sb_setcoreidx(sbh, oldidx); ++} + -+ /* -+ * Must do the disable sequence first to work for arbitrary current core state. -+ */ -+ sb_core_disable(sbh, bits); ++/* ++ * Functions for accessing translated SB configuration space ++ */ ++static int ++sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) ++{ ++ pci_config_regs *cfg; + -+ /* -+ * Now do the initialization sequence. -+ */ ++ if (dev >= SB_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs)) ++ return -1; ++ cfg = sb_pci_cfg[dev][func].emu; + -+ /* set reset while enabling the clock and forcing them on throughout the core */ -+ W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | SBTML_RESET | bits)); -+ dummy = R_SBREG(si, &sb->sbtmstatelow); -+ OSL_DELAY(1); ++ ASSERT(ISALIGNED(off, len)); ++ ASSERT(ISALIGNED((uintptr)buf, len)); + -+ if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_SERR) { -+ W_SBREG(si, &sb->sbtmstatehigh, 0); -+ } -+ if ((dummy = R_SBREG(si, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) { -+ AND_SBREG(si, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO)); -+ } ++ /* use special config space if the device does not exist */ ++ if (!cfg) ++ cfg = &sb_pci_null; ++ /* sync emulation with real PCI config if necessary */ ++ else if (sb_pci_cfg[dev][func].pci) ++ sb_pcid_read_config(sbh, dev, &sb_pci_cfg[dev][func], off, len); + -+ /* clear reset and allow it to propagate throughout the core */ -+ W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | bits)); -+ dummy = R_SBREG(si, &sb->sbtmstatelow); -+ OSL_DELAY(1); ++ if (len == 4) ++ *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off))); ++ else if (len == 2) ++ *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off))); ++ else if (len == 1) ++ *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off)); ++ else ++ return -1; + -+ /* leave clock enabled */ -+ W_SBREG(si, &sb->sbtmstatelow, (SBTML_CLK | bits)); -+ dummy = R_SBREG(si, &sb->sbtmstatelow); -+ OSL_DELAY(1); ++ return 0; +} + -+void -+sb_core_tofixup(sb_t *sbh) ++static int ++sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; ++ uint coreidx; ++ void *regs; ++ pci_config_regs *cfg; ++ osl_t *osh; ++ sb_bar_cfg_t *bar; + -+ si = SB_INFO(sbh); ++ if (dev >= SB_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs)) ++ return -1; ++ cfg = sb_pci_cfg[dev][func].emu; ++ if (!cfg) ++ return -1; + -+ if ( (BUSTYPE(si->sb.bustype) != PCI_BUS) || PCIE(si) || (PCI(si) && (si->sb.buscorerev >= 5)) ) -+ return; ++ ASSERT(ISALIGNED(off, len)); ++ ASSERT(ISALIGNED((uintptr)buf, len)); + -+ ASSERT(GOODREGS(si->curmap)); -+ sb = REGS2SB(si->curmap); ++ osh = sb_osh(sbh); + -+ if (BUSTYPE(si->sb.bustype) == SB_BUS) { -+ SET_SBREG(si, &sb->sbimconfiglow, -+ SBIMCL_RTO_MASK | SBIMCL_STO_MASK, -+ (0x5 << SBIMCL_RTO_SHIFT) | 0x3); -+ } else { -+ if (sb_coreid(sbh) == SB_PCI) { -+ SET_SBREG(si, &sb->sbimconfiglow, -+ SBIMCL_RTO_MASK | SBIMCL_STO_MASK, -+ (0x3 << SBIMCL_RTO_SHIFT) | 0x2); -+ } else { -+ SET_SBREG(si, &sb->sbimconfiglow, (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0); ++ /* Emulate BAR sizing */ ++ if (off >= OFFSETOF(pci_config_regs, base[0]) && ++ off <= OFFSETOF(pci_config_regs, base[3]) && ++ len == 4 && *((uint32 *) buf) == ~0) { ++ coreidx = sb_coreidx(sbh); ++ if ((regs = sb_setcoreidx(sbh, dev))) { ++ bar = sb_pci_cfg[dev][func].bar; ++ /* Highest numbered address match register */ ++ if (off == OFFSETOF(pci_config_regs, base[0])) ++ cfg->base[0] = ~(bar->size0 - 1); ++ else if (off == OFFSETOF(pci_config_regs, base[1]) && bar->n >= 1) ++ cfg->base[1] = ~(bar->size1 - 1); ++ else if (off == OFFSETOF(pci_config_regs, base[2]) && bar->n >= 2) ++ cfg->base[2] = ~(bar->size2 - 1); ++ else if (off == OFFSETOF(pci_config_regs, base[3]) && bar->n >= 3) ++ cfg->base[3] = ~(bar->size3 - 1); + } ++ sb_setcoreidx(sbh, coreidx); + } ++ else if (len == 4) ++ *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf)); ++ else if (len == 2) ++ *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf)); ++ else if (len == 1) ++ *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf); ++ else ++ return -1; + -+ sb_commit(sbh); ++ /* sync emulation with real PCI config if necessary */ ++ if (sb_pci_cfg[dev][func].pci) ++ sb_pcid_write_config(sbh, dev, &sb_pci_cfg[dev][func], off, len); ++ ++ return 0; +} + -+/* -+ * Set the initiator timeout for the "master core". -+ * The master core is defined to be the core in control -+ * of the chip and so it issues accesses to non-memory -+ * locations (Because of dma *any* core can access memeory). -+ * -+ * The routine uses the bus to decide who is the master: -+ * SB_BUS => mips -+ * JTAG_BUS => chipc -+ * PCI_BUS => pci or pcie -+ * PCMCIA_BUS => pcmcia -+ * SDIO_BUS => pcmcia -+ * -+ * This routine exists so callers can disable initiator -+ * timeouts so accesses to very slow devices like otp -+ * won't cause an abort. The routine allows arbitrary -+ * settings of the service and request timeouts, though. -+ * -+ * Returns the timeout state before changing it or -1 -+ * on error. -+ */ ++int ++sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) ++{ ++ if (bus == 0) ++ return sb_read_config(sbh, bus, dev, func, off, buf, len); ++ else ++ return extpci_read_config(sbh, bus, dev, func, off, buf, len); ++} ++ ++int ++sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) ++{ ++ if (bus == 0) ++ return sb_write_config(sbh, bus, dev, func, off, buf, len); ++ else ++ return extpci_write_config(sbh, bus, dev, func, off, buf, len); ++} + -+#define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK) ++void ++sbpci_ban(uint16 core) ++{ ++ if (pci_banned < ARRAYSIZE(pci_ban)) ++ pci_ban[pci_banned++] = core; ++} + -+uint32 -+sb_set_initiator_to(sb_t *sbh, uint32 to) ++/* ++ * Initiliaze PCI core. Return 0 after a successful initialization. ++ * Otherwise return -1 to indicate there is no PCI core and return 1 ++ * to indicate PCI core is disabled. ++ */ ++int __init ++sbpci_init_pci(sb_t *sbh) +{ -+ sb_info_t *si; -+ uint origidx, idx; -+ uint intr_val = 0; -+ uint32 tmp, ret = 0xffffffff; ++ uint chip, chiprev, chippkg, host; ++ uint32 boardflags; ++ sbpciregs_t *pci; + sbconfig_t *sb; ++ uint32 val; ++ int ret = 0; ++ char *hbslot; ++ osl_t *osh; + -+ si = SB_INFO(sbh); ++ chip = sb_chip(sbh); ++ chiprev = sb_chiprev(sbh); ++ chippkg = sb_chippkg(sbh); + -+ if ((to & ~TO_MASK) != 0) -+ return ret; ++ osh = sb_osh(sbh); + -+ /* Figure out the master core */ -+ idx = BADIDX; -+ switch (BUSTYPE(si->sb.bustype)) { -+ case PCI_BUS: -+ idx = si->sb.buscoreidx; -+ break; -+ case JTAG_BUS: -+ idx = SB_CC_IDX; -+ break; -+ case PCMCIA_BUS: -+ case SDIO_BUS: -+ idx = sb_findcoreidx(si, SB_PCMCIA, 0); -+ break; -+ case SB_BUS: -+ if ((idx = sb_findcoreidx(si, SB_MIPS33, 0)) == BADIDX) -+ idx = sb_findcoreidx(si, SB_MIPS, 0); -+ break; -+ default: -+ ASSERT(0); ++ if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) { ++ printk("PCI: no core\n"); ++ pci_disabled = TRUE; ++ return -1; + } -+ if (idx == BADIDX) -+ return ret; + -+ INTR_OFF(si, intr_val); -+ origidx = sb_coreidx(sbh); ++ if ((chip == 0x4710) && (chiprev == 0)) ++ pci_disabled = TRUE; ++ ++ sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF); + -+ sb = REGS2SB(sb_setcoreidx(sbh, idx)); ++ boardflags = (uint32) getintvar(NULL, "boardflags"); + -+ tmp = R_SBREG(si, &sb->sbimconfiglow); -+ ret = tmp & TO_MASK; -+ W_SBREG(si, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to); ++ /* ++ * The 200-pin BCM4712 package does not bond out PCI. Even when ++ * PCI is bonded out, some boards may leave the pins ++ * floating. ++ */ ++ if (((chip == BCM4712_CHIP_ID) && ++ ((chippkg == BCM4712SMALL_PKG_ID) || ++ (chippkg == BCM4712MID_PKG_ID))) || ++ (boardflags & BFL_NOPCI)) ++ pci_disabled = TRUE; + -+ sb_commit(sbh); -+ sb_setcoreidx(sbh, origidx); -+ INTR_RESTORE(si, intr_val); -+ return ret; -+} ++ /* Enable the core */ ++ sb_core_reset(sbh, 0, 0); + -+void -+sb_core_disable(sb_t *sbh, uint32 bits) -+{ -+ sb_info_t *si; -+ volatile uint32 dummy; -+ uint32 rej; -+ sbconfig_t *sb; ++ /* ++ * If the PCI core should not be touched (disabled, not bonded ++ * out, or pins floating), do not even attempt to access core ++ * registers. Otherwise, try to determine if it is in host ++ * mode. ++ */ ++ if (pci_disabled) ++ host = 0; ++ else ++ host = !BUSPROBE(val, &pci->control); + -+ si = SB_INFO(sbh); ++ if (!host) { ++ ret = 1; + -+ ASSERT(GOODREGS(si->curmap)); -+ sb = REGS2SB(si->curmap); ++ /* Disable PCI interrupts in client mode */ ++ W_REG(osh, &sb->sbintvec, 0); + -+ /* if core is already in reset, just return */ -+ if (R_SBREG(si, &sb->sbtmstatelow) & SBTML_RESET) -+ return; ++ /* Disable the PCI bridge in client mode */ ++ sbpci_ban(SB_PCI); ++ sb_core_disable(sbh, 0); + -+ /* reject value changed between sonics 2.2 and 2.3 */ -+ if (si->sb.sonicsrev == SONICS_2_2) -+ rej = (1 << SBTML_REJ_SHIFT); -+ else -+ rej = (2 << SBTML_REJ_SHIFT); ++ printk("PCI: Disabled\n"); ++ } else { ++ printk("PCI: Initializing host\n"); + -+ /* if clocks are not enabled, put into reset and return */ -+ if ((R_SBREG(si, &sb->sbtmstatelow) & SBTML_CLK) == 0) -+ goto disable; ++ /* Disable PCI SBReqeustTimeout for BCM4785 */ ++ if (chip == BCM4785_CHIP_ID) { ++ AND_REG(osh, &sb->sbimconfiglow, ~0x00000070); ++ sb_commit(sbh); ++ } + -+ /* set target reject and spin until busy is clear (preserve core-specific bits) */ -+ OR_SBREG(si, &sb->sbtmstatelow, rej); -+ dummy = R_SBREG(si, &sb->sbtmstatelow); -+ OSL_DELAY(1); -+ SPINWAIT((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000); ++ /* Reset the external PCI bus and enable the clock */ ++ W_REG(osh, &pci->control, 0x5); /* enable the tristate drivers */ ++ W_REG(osh, &pci->control, 0xd); /* enable the PCI clock */ ++ OSL_DELAY(150); /* delay > 100 us */ ++ W_REG(osh, &pci->control, 0xf); /* deassert PCI reset */ ++ /* Use internal arbiter and park REQ/GRNT at external master 0 */ ++ W_REG(osh, &pci->arbcontrol, PCI_INT_ARB); ++ OSL_DELAY(1); /* delay 1 us */ ++ if (sb_corerev(sbh) >= 8) { ++ val = getintvar(NULL, "parkid"); ++ ASSERT(val <= PCI_PARKID_LAST); ++ OR_REG(osh, &pci->arbcontrol, val << PCI_PARKID_SHIFT); ++ OSL_DELAY(1); ++ } + -+ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) { -+ OR_SBREG(si, &sb->sbimstate, SBIM_RJ); -+ dummy = R_SBREG(si, &sb->sbimstate); -+ OSL_DELAY(1); -+ SPINWAIT((R_SBREG(si, &sb->sbimstate) & SBIM_BY), 100000); -+ } ++ /* Enable CardBusMode */ ++ cardbus = getintvar(NULL, "cardbus") == 1; ++ if (cardbus) { ++ printk("PCI: Enabling CardBus\n"); ++ /* GPIO 1 resets the CardBus device on bcm94710ap */ ++ sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY); ++ sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY); ++ W_REG(osh, &pci->sprom[0], R_REG(osh, &pci->sprom[0]) | 0x400); ++ } + -+ /* set reset and reject while enabling the clocks */ -+ W_SBREG(si, &sb->sbtmstatelow, (bits | SBTML_FGC | SBTML_CLK | rej | SBTML_RESET)); -+ dummy = R_SBREG(si, &sb->sbtmstatelow); -+ OSL_DELAY(10); ++ /* 64 MB I/O access window */ ++ W_REG(osh, &pci->sbtopci0, SBTOPCI_IO); ++ /* 64 MB configuration access window */ ++ W_REG(osh, &pci->sbtopci1, SBTOPCI_CFG0); ++ /* 1 GB memory access window */ ++ W_REG(osh, &pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA); + -+ /* don't forget to clear the initiator reject bit */ -+ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) -+ AND_SBREG(si, &sb->sbimstate, ~SBIM_RJ); ++ /* Host bridge slot # nvram overwrite */ ++ if ((hbslot = nvram_get("pcihbslot"))) { ++ pci_hbslot = bcm_strtoul(hbslot, NULL, 0); ++ ASSERT(pci_hbslot < PCI_MAX_DEVICES); ++ } + -+disable: -+ /* leave reset and reject asserted */ -+ W_SBREG(si, &sb->sbtmstatelow, (bits | rej | SBTML_RESET)); -+ OSL_DELAY(1); ++ /* Enable PCI bridge BAR0 prefetch and burst */ ++ val = 6; ++ sbpci_write_config(sbh, 1, pci_hbslot, 0, PCI_CFG_CMD, &val, sizeof(val)); ++ ++ /* Enable PCI interrupts */ ++ W_REG(osh, &pci->intmask, PCI_INTA); ++ } ++ ++ return ret; +} + -+/* set chip watchdog reset timer to fire in 'ticks' backplane cycles */ -+void -+sb_watchdog(sb_t *sbh, uint ticks) ++/* ++ * Get the PCI region address and size information. ++ */ ++static void __init ++sbpci_init_regions(sb_t *sbh, uint func, pci_config_regs *cfg, sb_bar_cfg_t *bar) +{ -+ sb_info_t *si = SB_INFO(sbh); ++ osl_t *osh; ++ uint16 coreid; ++ void *regs; ++ sbconfig_t *sb; ++ uint32 base; + -+ /* instant NMI */ -+ switch (si->gpioid) { -+ case SB_CC: -+ sb_corereg(si, 0, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); ++ osh = sb_osh(sbh); ++ coreid = sb_coreid(sbh); ++ regs = sb_coreregs(sbh); ++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); ++ ++ switch (coreid) { ++ case SB_USB20H: ++ base = htol32(sb_base(R_REG(osh, &sb->sbadmatch0))); ++ ++ cfg->base[0] = func == 0 ? base : base + 0x800; /* OHCI/EHCI */ ++ cfg->base[1] = 0; ++ cfg->base[2] = 0; ++ cfg->base[3] = 0; ++ cfg->base[4] = 0; ++ cfg->base[5] = 0; ++ bar->n = 1; ++ bar->size0 = func == 0 ? 0x200 : 0x100; /* OHCI/EHCI */ ++ bar->size1 = 0; ++ bar->size2 = 0; ++ bar->size3 = 0; + break; -+ case SB_EXTIF: -+ sb_corereg(si, si->gpioidx, OFFSETOF(extifregs_t, watchdog), ~0, ticks); ++ default: ++ cfg->base[0] = htol32(sb_base(R_REG(osh, &sb->sbadmatch0))); ++ cfg->base[1] = htol32(sb_base(R_REG(osh, &sb->sbadmatch1))); ++ cfg->base[2] = htol32(sb_base(R_REG(osh, &sb->sbadmatch2))); ++ cfg->base[3] = htol32(sb_base(R_REG(osh, &sb->sbadmatch3))); ++ cfg->base[4] = 0; ++ cfg->base[5] = 0; ++ bar->n = (R_REG(osh, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT; ++ bar->size0 = sb_size(R_REG(osh, &sb->sbadmatch0)); ++ bar->size1 = sb_size(R_REG(osh, &sb->sbadmatch1)); ++ bar->size2 = sb_size(R_REG(osh, &sb->sbadmatch2)); ++ bar->size3 = sb_size(R_REG(osh, &sb->sbadmatch3)); + break; + } +} + -+/* initialize the pcmcia core */ -+void -+sb_pcmcia_init(sb_t *sbh) ++/* ++ * Construct PCI config spaces for SB cores so that they ++ * can be accessed as if they were PCI devices. ++ */ ++static void __init ++sbpci_init_cores(sb_t *sbh) +{ -+ sb_info_t *si; -+ uint8 cor; ++ uint chiprev, coreidx, i; ++ sbconfig_t *sb; ++ pci_config_regs *cfg, *pci; ++ sb_bar_cfg_t *bar; ++ void *regs; ++ osl_t *osh; ++ uint16 vendor, device; ++ uint16 coreid; ++ uint8 class, subclass, progif; ++ uint dev; ++ uint8 header; ++ uint func; + -+ si = SB_INFO(sbh); ++ chiprev = sb_chiprev(sbh); ++ coreidx = sb_coreidx(sbh); + -+ /* enable d11 mac interrupts */ -+ if (si->sb.chip == BCM4301_DEVICE_ID) { -+ /* Have to use FCR2 in 4301 */ -+ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_FCR2 + PCMCIA_COR, &cor, 1); -+ cor |= COR_IRQEN | COR_FUNEN; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_FCR2 + PCMCIA_COR, &cor, 1); -+ } else { -+ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1); -+ cor |= COR_IRQEN | COR_FUNEN; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1); ++ osh = sb_osh(sbh); ++ ++ /* Scan the SB bus */ ++ bzero(sb_config_regs, sizeof(sb_config_regs)); ++ bzero(sb_bar_cfg, sizeof(sb_bar_cfg)); ++ bzero(sb_pci_cfg, sizeof(sb_pci_cfg)); ++ memset(&sb_pci_null, -1, sizeof(sb_pci_null)); ++ cfg = sb_config_regs; ++ bar = sb_bar_cfg; ++ for (dev = 0; dev < SB_MAXCORES; dev ++) { ++ /* Check if the core exists */ ++ if (!(regs = sb_setcoreidx(sbh, dev))) ++ continue; ++ sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); ++ ++ /* Check if this core is banned */ ++ coreid = sb_coreid(sbh); ++ for (i = 0; i < pci_banned; i++) ++ if (coreid == pci_ban[i]) ++ break; ++ if (i < pci_banned) ++ continue; ++ ++ for (func = 0; func < MAXFUNCS; ++func) { ++ /* Make sure we won't go beyond the limit */ ++ if (cfg >= &sb_config_regs[SB_MAXCORES]) { ++ printk("PCI: too many emulated devices\n"); ++ goto done; ++ } ++ ++ /* Convert core id to pci id */ ++ if (sb_corepciid(sbh, func, &vendor, &device, &class, &subclass, ++ &progif, &header)) ++ continue; ++ ++ /* ++ * Differentiate real PCI config from emulated. ++ * non zero 'pci' indicate there is a real PCI config space ++ * for this device. ++ */ ++ switch (device) { ++ case BCM47XX_GIGETH_ID: ++ pci = (pci_config_regs *)((uint32)regs + 0x800); ++ break; ++ case BCM47XX_SATAXOR_ID: ++ pci = (pci_config_regs *)((uint32)regs + 0x400); ++ break; ++ case BCM47XX_ATA100_ID: ++ pci = (pci_config_regs *)((uint32)regs + 0x800); ++ break; ++ default: ++ pci = NULL; ++ break; ++ } ++ /* Supported translations */ ++ cfg->vendor = htol16(vendor); ++ cfg->device = htol16(device); ++ cfg->rev_id = chiprev; ++ cfg->prog_if = progif; ++ cfg->sub_class = subclass; ++ cfg->base_class = class; ++ cfg->header_type = header; ++ sbpci_init_regions(sbh, func, cfg, bar); ++ /* Save core interrupt flag */ ++ cfg->int_pin = R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK; ++ /* Save core interrupt assignment */ ++ cfg->int_line = sb_irq(sbh); ++ /* Indicate there is no SROM */ ++ *((uint32 *) &cfg->sprom_control) = 0xffffffff; ++ ++ /* Point to the PCI config spaces */ ++ sb_pci_cfg[dev][func].emu = cfg; ++ sb_pci_cfg[dev][func].pci = pci; ++ sb_pci_cfg[dev][func].bar = bar; ++ cfg ++; ++ bar ++; ++ } + } + ++done: ++ sb_setcoreidx(sbh, coreidx); +} + -+ +/* -+ * Configure the pci core for pci client (NIC) action -+ * coremask is the bitvec of cores by index to be enabled. ++ * Initialize PCI core and construct PCI config spaces for SB cores. ++ * Must propagate sbpci_init_pci() return value to the caller to let ++ * them know the PCI core initialization status. + */ -+void -+sb_pci_setup(sb_t *sbh, uint coremask) ++int __init ++sbpci_init(sb_t *sbh) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ sbpciregs_t *pciregs; -+ uint32 sbflag; -+ uint32 w; -+ uint idx; -+ int reg_val; ++ int status = sbpci_init_pci(sbh); ++ sbpci_init_cores(sbh); ++ return status; ++} + -+ si = SB_INFO(sbh); +diff -urN linux.old/arch/mips/bcm947xx/sbutils.c linux.dev/arch/mips/bcm947xx/sbutils.c +--- linux.old/arch/mips/bcm947xx/sbutils.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/sbutils.c 2006-05-02 04:33:16.000000000 +0200 +@@ -0,0 +1,3081 @@ ++/* ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * $Id: sbutils.c,v 1.10 2006/04/08 07:12:42 honor Exp $ ++ */ + -+ /* if not pci bus, we're done */ -+ if (BUSTYPE(si->sb.bustype) != PCI_BUS) -+ return; ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef __mips__ ++#include ++#endif /* __mips__ */ + -+ ASSERT(PCI(si) || PCIE(si)); -+ ASSERT(si->sb.buscoreidx != BADIDX); ++/* debug/trace */ ++#define SB_ERROR(args) + -+ /* get current core index */ -+ idx = si->curidx; ++typedef uint32 (*sb_intrsoff_t)(void *intr_arg); ++typedef void (*sb_intrsrestore_t)(void *intr_arg, uint32 arg); ++typedef bool (*sb_intrsenabled_t)(void *intr_arg); + -+ /* we interrupt on this backplane flag number */ -+ ASSERT(GOODREGS(si->curmap)); -+ sb = REGS2SB(si->curmap); -+ sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK; ++/* misc sb info needed by some of the routines */ ++typedef struct sb_info { + -+ /* switch over to pci core */ -+ pciregs = (sbpciregs_t*) sb_setcoreidx(sbh, si->sb.buscoreidx); -+ sb = REGS2SB(pciregs); ++ struct sb_pub sb; /* back plane public state (must be first field) */ + -+ /* -+ * Enable sb->pci interrupts. Assume -+ * PCI rev 2.3 support was added in pci core rev 6 and things changed.. -+ */ -+ if (PCIE(si) || (PCI(si) && ((si->sb.buscorerev) >= 6))) { -+ /* pci config write to set this core bit in PCIIntMask */ -+ w = OSL_PCI_READ_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32)); -+ w |= (coremask << PCI_SBIM_SHIFT); -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32), w); -+ } else { -+ /* set sbintvec bit for our flag number */ -+ OR_SBREG(si, &sb->sbintvec, (1 << sbflag)); -+ } ++ void *osh; /* osl os handle */ ++ void *sdh; /* bcmsdh handle */ + -+ if (PCI(si)) { -+ OR_REG(&pciregs->sbtopci2, (SBTOPCI_PREF|SBTOPCI_BURST)); -+ if (si->sb.buscorerev >= 11) -+ OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI); -+ if (si->sb.buscorerev < 5) { -+ SET_SBREG(si, &sb->sbimconfiglow, SBIMCL_RTO_MASK | SBIMCL_STO_MASK, -+ (0x3 << SBIMCL_RTO_SHIFT) | 0x2); -+ sb_commit(sbh); -+ } -+ } ++ void *curmap; /* current regs va */ ++ void *regs[SB_MAXCORES]; /* other regs va */ + -+ if (PCIE(si) && (si->sb.buscorerev == 0)) { -+ reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS, PCIE_TLP_WORKAROUNDSREG); -+ reg_val |= 0x8; -+ sb_pcie_writereg((void *)sbh, (void *)PCIE_PCIEREGS, PCIE_TLP_WORKAROUNDSREG, reg_val); ++ uint curidx; /* current core index */ ++ uint dev_coreid; /* the core provides driver functions */ + -+ reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS, PCIE_DLLP_LCREG); -+ reg_val &= ~(0x40); -+ sb_pcie_writereg(sbh, (void *)PCIE_PCIEREGS, PCIE_DLLP_LCREG, reg_val); ++ bool memseg; /* flag to toggle MEM_SEG register */ + -+ BCMINIT(sb_war30841)(si); -+ } ++ uint gpioidx; /* gpio control core index */ ++ uint gpioid; /* gpio control coretype */ + -+ /* switch back to previous core */ -+ sb_setcoreidx(sbh, idx); -+} ++ uint numcores; /* # discovered cores */ ++ uint coreid[SB_MAXCORES]; /* id of each core */ + -+uint32 -+sb_base(uint32 admatch) -+{ -+ uint32 base; -+ uint type; ++ void *intr_arg; /* interrupt callback function arg */ ++ sb_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ ++ sb_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ ++ sb_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ + -+ type = admatch & SBAM_TYPE_MASK; -+ ASSERT(type < 3); ++} sb_info_t; + -+ base = 0; ++/* local prototypes */ ++static sb_info_t * sb_doattach(sb_info_t *si, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz); ++static void sb_scan(sb_info_t *si); ++static uint sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val); ++static uint _sb_coreidx(sb_info_t *si); ++static uint sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit); ++static uint sb_pcidev2chip(uint pcidev); ++static uint sb_chip2numcores(uint chip); ++static bool sb_ispcie(sb_info_t *si); ++static bool sb_find_pci_capability(sb_info_t *si, uint8 req_cap_id, uchar *buf, uint32 *buflen); ++static int sb_pci_fixcfg(sb_info_t *si); + -+ if (type == 0) { -+ base = admatch & SBAM_BASE0_MASK; -+ } else if (type == 1) { -+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ -+ base = admatch & SBAM_BASE1_MASK; -+ } else if (type == 2) { -+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ -+ base = admatch & SBAM_BASE2_MASK; -+ } ++/* routines to access mdio slave device registers */ ++static int sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint readdr, uint val); ++static void sb_war30841(sb_info_t *si); + -+ return (base); -+} ++/* delay needed between the mdio control/ mdiodata register data access */ ++#define PR28829_DELAY() OSL_DELAY(10) + -+uint32 -+sb_size(uint32 admatch) -+{ -+ uint32 size; -+ uint type; ++/* size that can take bitfielddump */ ++#define BITFIELD_DUMP_SIZE 32 + -+ type = admatch & SBAM_TYPE_MASK; -+ ASSERT(type < 3); ++/* global variable to indicate reservation/release of gpio's */ ++static uint32 sb_gpioreservation = 0; + -+ size = 0; ++#define SB_INFO(sbh) (sb_info_t*)sbh ++#define SET_SBREG(si, r, mask, val) \ ++ W_SBREG((si), (r), ((R_SBREG((si), (r)) & ~(mask)) | (val))) ++#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && \ ++ ISALIGNED((x), SB_CORE_SIZE)) ++#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE)) ++#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF) ++#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES) ++#define BADIDX (SB_MAXCORES+1) ++#define NOREV -1 /* Invalid rev */ + -+ if (type == 0) { -+ size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1); -+ } else if (type == 1) { -+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ -+ size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1); -+ } else if (type == 2) { -+ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ -+ size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1); -+ } ++#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI)) ++#define PCIE(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCIE)) + -+ return (size); -+} ++/* sonicsrev */ ++#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT) ++#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT) + -+/* return the core-type instantiation # of the current core */ -+uint -+sb_coreunit(sb_t *sbh) -+{ -+ sb_info_t *si; -+ uint idx; -+ uint coreid; -+ uint coreunit; -+ uint i; ++#define R_SBREG(si, sbr) sb_read_sbreg((si), (sbr)) ++#define W_SBREG(si, sbr, v) sb_write_sbreg((si), (sbr), (v)) ++#define AND_SBREG(si, sbr, v) W_SBREG((si), (sbr), (R_SBREG((si), (sbr)) & (v))) ++#define OR_SBREG(si, sbr, v) W_SBREG((si), (sbr), (R_SBREG((si), (sbr)) | (v))) + -+ si = SB_INFO(sbh); -+ coreunit = 0; ++/* ++ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/ ++ * after core switching to avoid invalid register accesss inside ISR. ++ */ ++#define INTR_OFF(si, intr_val) \ ++ if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); } ++#define INTR_RESTORE(si, intr_val) \ ++ if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); } + -+ idx = si->curidx; ++/* dynamic clock control defines */ ++#define LPOMINFREQ 25000 /* low power oscillator min */ ++#define LPOMAXFREQ 43000 /* low power oscillator max */ ++#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ ++#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ ++#define PCIMINFREQ 25000000 /* 25 MHz */ ++#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ + -+ ASSERT(GOODREGS(si->curmap)); -+ coreid = sb_coreid(sbh); ++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ ++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ + -+ /* count the cores of our type */ -+ for (i = 0; i < idx; i++) -+ if (si->coreid[i] == coreid) -+ coreunit++; ++/* different register spaces to access thr'u pcie indirect access */ ++#define PCIE_CONFIGREGS 1 /* Access to config space */ ++#define PCIE_PCIEREGS 2 /* Access to pcie registers */ + -+ return (coreunit); -+} ++/* GPIO Based LED powersave defines */ ++#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ ++#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ + -+static INLINE uint32 -+factor6(uint32 x) -+{ -+ switch (x) { -+ case CC_F6_2: return 2; -+ case CC_F6_3: return 3; -+ case CC_F6_4: return 4; -+ case CC_F6_5: return 5; -+ case CC_F6_6: return 6; -+ case CC_F6_7: return 7; -+ default: return 0; -+ } -+} ++#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) + -+/* calculate the speed the SB would run at given a set of clockcontrol values */ -+uint32 -+sb_clock_rate(uint32 pll_type, uint32 n, uint32 m) ++static uint32 ++sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr) +{ -+ uint32 n1, n2, clock, m1, m2, m3, mc; ++ uint8 tmp; ++ uint32 val, intr_val = 0; + -+ n1 = n & CN_N1_MASK; -+ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; + -+ if (pll_type == PLL_TYPE6) { -+ if (m & CC_T6_MMASK) -+ return CC_T6_M1; -+ else -+ return CC_T6_M0; -+ } else if ((pll_type == PLL_TYPE1) || -+ (pll_type == PLL_TYPE3) || -+ (pll_type == PLL_TYPE4) || -+ (pll_type == PLL_TYPE7)) { -+ n1 = factor6(n1); -+ n2 += CC_F5_BIAS; -+ } else if (pll_type == PLL_TYPE2) { -+ n1 += CC_T2_BIAS; -+ n2 += CC_T2_BIAS; -+ ASSERT((n1 >= 2) && (n1 <= 7)); -+ ASSERT((n2 >= 5) && (n2 <= 23)); -+ } else if (pll_type == PLL_TYPE5) { -+ return (100000000); -+ } else -+ ASSERT(0); -+ /* PLL types 3 and 7 use BASE2 (25Mhz) */ -+ if ((pll_type == PLL_TYPE3) || -+ (pll_type == PLL_TYPE7)) { -+ clock = CC_CLOCK_BASE2 * n1 * n2; ++ /* ++ * compact flash only has 11 bits address, while we needs 12 bits address. ++ * MEM_SEG will be OR'd with other 11 bits address in hardware, ++ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). ++ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special ++ */ ++ if (si->memseg) { ++ INTR_OFF(si, intr_val); ++ tmp = 1; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); ++ sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ + } -+ else -+ clock = CC_CLOCK_BASE1 * n1 * n2; -+ -+ if (clock == 0) -+ return 0; -+ -+ m1 = m & CC_M1_MASK; -+ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; -+ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; -+ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; -+ -+ if ((pll_type == PLL_TYPE1) || -+ (pll_type == PLL_TYPE3) || -+ (pll_type == PLL_TYPE4) || -+ (pll_type == PLL_TYPE7)) { -+ m1 = factor6(m1); -+ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) -+ m2 += CC_F5_BIAS; -+ else -+ m2 = factor6(m2); -+ m3 = factor6(m3); -+ -+ switch (mc) { -+ case CC_MC_BYPASS: return (clock); -+ case CC_MC_M1: return (clock / m1); -+ case CC_MC_M1M2: return (clock / (m1 * m2)); -+ case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); -+ case CC_MC_M1M3: return (clock / (m1 * m3)); -+ default: return (0); -+ } -+ } else { -+ ASSERT(pll_type == PLL_TYPE2); -+ -+ m1 += CC_T2_BIAS; -+ m2 += CC_T2M2_BIAS; -+ m3 += CC_T2_BIAS; -+ ASSERT((m1 >= 2) && (m1 <= 7)); -+ ASSERT((m2 >= 3) && (m2 <= 10)); -+ ASSERT((m3 >= 2) && (m3 <= 7)); + -+ if ((mc & CC_T2MC_M1BYP) == 0) -+ clock /= m1; -+ if ((mc & CC_T2MC_M2BYP) == 0) -+ clock /= m2; -+ if ((mc & CC_T2MC_M3BYP) == 0) -+ clock /= m3; ++ val = R_REG(si->osh, sbr); + -+ return(clock); ++ if (si->memseg) { ++ tmp = 0; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); ++ INTR_RESTORE(si, intr_val); + } ++ ++ return (val); +} + -+/* returns the current speed the SB is running at */ -+uint32 -+sb_clock(sb_t *sbh) ++static void ++sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v) +{ -+ sb_info_t *si; -+ extifregs_t *eir; -+ chipcregs_t *cc; -+ uint32 n, m; -+ uint idx; -+ uint32 pll_type, rate; -+ uint intr_val = 0; ++ uint8 tmp; ++ volatile uint32 dummy; ++ uint32 intr_val = 0; + -+ si = SB_INFO(sbh); -+ idx = si->curidx; -+ pll_type = PLL_TYPE1; + -+ INTR_OFF(si, intr_val); ++ /* ++ * compact flash only has 11 bits address, while we needs 12 bits address. ++ * MEM_SEG will be OR'd with other 11 bits address in hardware, ++ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). ++ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special ++ */ ++ if (si->memseg) { ++ INTR_OFF(si, intr_val); ++ tmp = 1; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); ++ sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ ++ } + -+ /* switch to extif or chipc core */ -+ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) { -+ n = R_REG(&eir->clockcontrol_n); -+ m = R_REG(&eir->clockcontrol_sb); -+ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { -+ pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK; -+ n = R_REG(&cc->clockcontrol_n); -+ if (pll_type == PLL_TYPE6) -+ m = R_REG(&cc->clockcontrol_mips); -+ else if (pll_type == PLL_TYPE3) -+ { -+ // Added by Chen-I for 5365 -+ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) -+ m = R_REG(&cc->clockcontrol_sb); -+ else -+ m = R_REG(&cc->clockcontrol_m2); -+ } -+ else -+ m = R_REG(&cc->clockcontrol_sb); -+ } else { ++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { ++#ifdef IL_BIGENDIAN ++ dummy = R_REG(si->osh, sbr); ++ W_REG(si->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); ++ dummy = R_REG(si->osh, sbr); ++ W_REG(si->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff)); ++#else ++ dummy = R_REG(si->osh, sbr); ++ W_REG(si->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff)); ++ dummy = R_REG(si->osh, sbr); ++ W_REG(si->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); ++#endif /* IL_BIGENDIAN */ ++ } else ++ W_REG(si->osh, sbr, v); ++ ++ if (si->memseg) { ++ tmp = 0; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); + INTR_RESTORE(si, intr_val); -+ return 0; + } ++} + -+ // Added by Chen-I for 5365 -+ if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) -+ { -+ rate = 100000000; ++/* ++ * Allocate a sb handle. ++ * devid - pci device id (used to determine chip#) ++ * osh - opaque OS handle ++ * regs - virtual address of initial core registers ++ * bustype - pci/pcmcia/sb/sdio/etc ++ * vars - pointer to a pointer area for "environment" variables ++ * varsz - pointer to int to return the size of the vars ++ */ ++sb_t * ++BCMINITFN(sb_attach)(uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) ++{ ++ sb_info_t *si; ++ ++ /* alloc sb_info_t */ ++ if ((si = MALLOC(osh, sizeof (sb_info_t))) == NULL) { ++ SB_ERROR(("sb_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); ++ return (NULL); + } -+ else -+ { -+ /* calculate rate */ -+ rate = sb_clock_rate(pll_type, n, m); -+ if (pll_type == PLL_TYPE3) -+ rate = rate / 2; ++ ++ if (sb_doattach(si, devid, osh, regs, bustype, sdh, vars, (uint*)varsz) == NULL) { ++ MFREE(osh, si, sizeof(sb_info_t)); ++ return (NULL); + } + -+ /* switch back to previous core */ -+ sb_setcoreidx(sbh, idx); ++ return (sb_t *)si; ++} + -+ INTR_RESTORE(si, intr_val); ++/* Using sb_kattach depends on SB_BUS support, either implicit */ ++/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */ ++#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS) + -+ return rate; -+} ++/* global kernel resource */ ++static sb_info_t ksi; ++static bool ksi_attached = FALSE; + -+/* change logical "focus" to the gpio core for optimized access */ -+void* -+sb_gpiosetcore(sb_t *sbh) ++/* generic kernel variant of sb_attach() */ ++sb_t * ++BCMINITFN(sb_kattach)(void) +{ -+ sb_info_t *si; ++ osl_t *osh = NULL; ++ uint32 *regs; + -+ si = SB_INFO(sbh); ++ if (!ksi_attached) { ++ uint32 cid; + -+ return (sb_setcoreidx(sbh, si->gpioidx)); ++ regs = (uint32 *)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE); ++ cid = R_REG(osh, (uint32 *)regs); ++ if (((cid & CID_ID_MASK) == BCM4712_CHIP_ID) && ++ ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) && ++ ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) { ++ uint32 *scc, val; ++ ++ scc = (uint32 *)((uchar*)regs + OFFSETOF(chipcregs_t, slow_clk_ctl)); ++ val = R_REG(osh, scc); ++ SB_ERROR((" initial scc = 0x%x\n", val)); ++ val |= SCC_SS_XTAL; ++ W_REG(osh, scc, val); ++ } ++ ++ if (sb_doattach(&ksi, BCM4710_DEVICE_ID, osh, (void*)regs, ++ SB_BUS, NULL, NULL, NULL) == NULL) { ++ return NULL; ++ } ++ else ++ ksi_attached = TRUE; ++ } ++ ++ return (sb_t *)&ksi; +} ++#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */ + -+/* mask&set gpiocontrol bits */ -+uint32 -+sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) ++static sb_info_t * ++BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) +{ -+ sb_info_t *si; -+ uint regoff; ++ uint origidx; ++ chipcregs_t *cc; ++ sbconfig_t *sb; ++ uint32 w; + -+ si = SB_INFO(sbh); -+ regoff = 0; ++ ASSERT(GOODREGS(regs)); + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ bzero((uchar*)si, sizeof(sb_info_t)); + -+ /* gpios could be shared on router platforms */ -+ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { -+ mask = priority ? (sb_gpioreservation & mask) : -+ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); -+ val &= mask; ++ si->sb.buscoreidx = si->gpioidx = BADIDX; ++ ++ si->curmap = regs; ++ si->sdh = sdh; ++ si->osh = osh; ++ ++ /* check to see if we are a sb core mimic'ing a pci core */ ++ if (bustype == PCI_BUS) { ++ if (OSL_PCI_READ_CONFIG(si->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff) { ++ SB_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SB " ++ "devid:0x%x\n", __FUNCTION__, devid)); ++ bustype = SB_BUS; ++ } + } + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpiocontrol); -+ break; ++ si->sb.bustype = bustype; ++ if (si->sb.bustype != BUSTYPE(si->sb.bustype)) { ++ SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n", ++ si->sb.bustype, BUSTYPE(si->sb.bustype))); ++ return NULL; ++ } + -+ case SB_PCI: -+ regoff = OFFSETOF(sbpciregs_t, gpiocontrol); -+ break; ++ /* need to set memseg flag for CF card first before any sb registers access */ ++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) ++ si->memseg = TRUE; + -+ case SB_EXTIF: -+ return (0); ++ /* kludge to enable the clock on the 4306 which lacks a slowclock */ ++ if (BUSTYPE(si->sb.bustype) == PCI_BUS) ++ sb_clkctl_xtal(&si->sb, XTAL|PLL, ON); ++ ++ if (BUSTYPE(si->sb.bustype) == PCI_BUS) { ++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32)); ++ if (!GOODCOREADDR(w)) ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32), SB_ENUM_BASE); + } + -+ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); -+} ++ /* initialize current core index value */ ++ si->curidx = _sb_coreidx(si); + -+/* mask&set gpio output enable bits */ -+uint32 -+sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) -+{ -+ sb_info_t *si; -+ uint regoff; ++ if (si->curidx == BADIDX) { ++ SB_ERROR(("sb_doattach: bad core index\n")); ++ return NULL; ++ } + -+ si = SB_INFO(sbh); -+ regoff = 0; ++ /* get sonics backplane revision */ ++ sb = REGS2SB(si->curmap); ++ si->sb.sonicsrev = (R_SBREG(si, &sb->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT; + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ /* keep and reuse the initial register mapping */ ++ origidx = si->curidx; ++ if (BUSTYPE(si->sb.bustype) == SB_BUS) ++ si->regs[origidx] = regs; + -+ /* gpios could be shared on router platforms */ -+ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { -+ mask = priority ? (sb_gpioreservation & mask) : -+ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); -+ val &= mask; ++ /* is core-0 a chipcommon core? */ ++ si->numcores = 1; ++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, 0); ++ if (sb_coreid(&si->sb) != SB_CC) ++ cc = NULL; ++ ++ /* determine chip id and rev */ ++ if (cc) { ++ /* chip common core found! */ ++ si->sb.chip = R_REG(si->osh, &cc->chipid) & CID_ID_MASK; ++ si->sb.chiprev = (R_REG(si->osh, &cc->chipid) & CID_REV_MASK) >> CID_REV_SHIFT; ++ si->sb.chippkg = (R_REG(si->osh, &cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ } else { ++ /* no chip common core -- must convert device id to chip id */ ++ if ((si->sb.chip = sb_pcidev2chip(devid)) == 0) { ++ SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid)); ++ sb_setcoreidx(&si->sb, origidx); ++ return NULL; ++ } + } + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpioouten); -+ break; ++ /* get chipcommon rev */ ++ si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV; + -+ case SB_PCI: -+ regoff = OFFSETOF(sbpciregs_t, gpioouten); -+ break; ++ /* determine numcores */ ++ if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6))) ++ si->numcores = (R_REG(si->osh, &cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT; ++ else ++ si->numcores = sb_chip2numcores(si->sb.chip); + -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpio[0].outen); -+ break; ++ /* return to original core */ ++ sb_setcoreidx(&si->sb, origidx); ++ ++ /* sanity checks */ ++ ASSERT(si->sb.chip); ++ ++ /* scan for cores */ ++ sb_scan(si); ++ ++ /* fixup necessary chip/core configurations */ ++ if (BUSTYPE(si->sb.bustype) == PCI_BUS) { ++ if (sb_pci_fixcfg(si)) { ++ SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n")); ++ return NULL; ++ } ++ } ++ ++ /* srom_var_init() depends on sb_scan() info */ ++ if (srom_var_init(si, si->sb.bustype, si->curmap, si->osh, vars, varsz)) { ++ SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n")); ++ return (NULL); ++ } ++ ++ if (cc == NULL) { ++ /* ++ * The chip revision number is hardwired into all ++ * of the pci function config rev fields and is ++ * independent from the individual core revision numbers. ++ * For example, the "A0" silicon of each chip is chip rev 0. ++ * For PCMCIA we get it from the CIS instead. ++ */ ++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { ++ ASSERT(vars); ++ si->sb.chiprev = getintvar(*vars, "chiprev"); ++ } else if (BUSTYPE(si->sb.bustype) == PCI_BUS) { ++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_REV, sizeof(uint32)); ++ si->sb.chiprev = w & 0xff; ++ } else ++ si->sb.chiprev = 0; + } + -+ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); -+} -+ -+/* mask&set gpio output bits */ -+uint32 -+sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) -+{ -+ sb_info_t *si; -+ uint regoff; -+ -+ si = SB_INFO(sbh); -+ regoff = 0; -+ -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { ++ w = getintvar(*vars, "regwindowsz"); ++ si->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE; ++ } + -+ /* gpios could be shared on router platforms */ -+ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { -+ mask = priority ? (sb_gpioreservation & mask) : -+ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); -+ val &= mask; ++ /* gpio control core is required */ ++ if (!GOODIDX(si->gpioidx)) { ++ SB_ERROR(("sb_doattach: gpio control core not found\n")); ++ return NULL; + } + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpioout); ++ /* get boardtype and boardrev */ ++ switch (BUSTYPE(si->sb.bustype)) { ++ case PCI_BUS: ++ /* do a pci config read to get subsystem id and subvendor id */ ++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_SVID, sizeof(uint32)); ++ si->sb.boardvendor = w & 0xffff; ++ si->sb.boardtype = (w >> 16) & 0xffff; + break; + -+ case SB_PCI: -+ regoff = OFFSETOF(sbpciregs_t, gpioout); ++ case PCMCIA_BUS: ++ case SDIO_BUS: ++ si->sb.boardvendor = getintvar(*vars, "manfid"); ++ si->sb.boardtype = getintvar(*vars, "prodid"); + break; + -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpio[0].out); ++ case SB_BUS: ++ case JTAG_BUS: ++ si->sb.boardvendor = VENDOR_BROADCOM; ++ if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0) ++ si->sb.boardtype = 0xffff; + break; + } + -+ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); -+} -+ -+/* reserve one gpio */ -+uint32 -+sb_gpioreserve(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) -+{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); -+ -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ if (si->sb.boardtype == 0) { ++ SB_ERROR(("sb_doattach: unknown board type\n")); ++ ASSERT(si->sb.boardtype); ++ } + -+ /* only cores on SB_BUS share GPIO's and only applcation users need to reserve/release GPIO */ -+ if ( (BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { -+ ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority)); -+ return -1; ++ /* setup the GPIO based LED powersave register */ ++ if (si->sb.ccrev >= 16) { ++ if ((vars == NULL) || ((w = getintvar(*vars, "leddc")) == 0)) ++ w = DEFAULT_GPIOTIMERVAL; ++ sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w); + } -+ /* make sure only one bit is set */ -+ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { -+ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); -+ return -1; ++ if ((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev <= 1)) { ++ /* set proper clk setup delays before forcing HT */ ++ sb_clkctl_init((void *)si); ++ sb_corereg((void*)si, SB_CC_IDX, OFFSETOF(chipcregs_t, system_clk_ctl), ++ SYCC_HR, SYCC_HR); + } + -+ /* already reserved */ -+ if (sb_gpioreservation & gpio_bitmask) -+ return -1; -+ /* set reservation */ -+ sb_gpioreservation |= gpio_bitmask; + -+ return sb_gpioreservation; ++ return (si); +} + -+/* release one gpio */ -+/* -+ * releasing the gpio doesn't change the current value on the GPIO last write value -+ * persists till some one overwrites it -+*/ -+ -+uint32 -+sb_gpiorelease(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) ++uint ++sb_coreid(sb_t *sbh) +{ + sb_info_t *si; ++ sbconfig_t *sb; + + si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ -+ -+ /* only cores on SB_BUS share GPIO's and only applcation users need to reserve/release GPIO */ -+ if ( (BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { -+ ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority)); -+ return -1; -+ } -+ /* make sure only one bit is set */ -+ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { -+ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); -+ return -1; -+ } -+ -+ /* already released */ -+ if (!(sb_gpioreservation & gpio_bitmask)) -+ return -1; -+ -+ /* clear reservation */ -+ sb_gpioreservation &= ~gpio_bitmask; -+ -+ return sb_gpioreservation; ++ return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT); +} + -+/* return the current gpioin register value */ -+uint32 -+sb_gpioin(sb_t *sbh) ++uint ++sb_coreidx(sb_t *sbh) +{ + sb_info_t *si; -+ uint regoff; + + si = SB_INFO(sbh); -+ regoff = 0; -+ -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpioin); -+ break; -+ -+ case SB_PCI: -+ regoff = OFFSETOF(sbpciregs_t, gpioin); -+ break; -+ -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpioin); -+ break; -+ } -+ -+ return (sb_corereg(si, si->gpioidx, regoff, 0, 0)); ++ return (si->curidx); +} + -+/* mask&set gpio interrupt polarity bits */ -+uint32 -+sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) ++/* return current index of core */ ++static uint ++_sb_coreidx(sb_info_t *si) +{ -+ sb_info_t *si; -+ uint regoff; -+ -+ si = SB_INFO(sbh); -+ regoff = 0; -+ -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ -+ -+ /* gpios could be shared on router platforms */ -+ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { -+ mask = priority ? (sb_gpioreservation & mask) : -+ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); -+ val &= mask; -+ } ++ sbconfig_t *sb; ++ uint32 sbaddr = 0; + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpiointpolarity); -+ break; ++ ASSERT(si); + -+ case SB_PCI: -+ /* pci gpio implementation does not support interrupt polarity */ -+ ASSERT(0); ++ switch (BUSTYPE(si->sb.bustype)) { ++ case SB_BUS: ++ sb = REGS2SB(si->curmap); ++ sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0)); + break; + -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpiointpolarity); ++ case PCI_BUS: ++ sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32)); + break; -+ } + -+ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); -+} -+ -+/* mask&set gpio interrupt mask bits */ -+uint32 -+sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) -+{ -+ sb_info_t *si; -+ uint regoff; -+ -+ si = SB_INFO(sbh); -+ regoff = 0; -+ -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ case PCMCIA_BUS: { ++ uint8 tmp = 0; + -+ /* gpios could be shared on router platforms */ -+ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { -+ mask = priority ? (sb_gpioreservation & mask) : -+ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); -+ val &= mask; ++ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1); ++ sbaddr = (uint)tmp << 12; ++ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1); ++ sbaddr |= (uint)tmp << 16; ++ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1); ++ sbaddr |= (uint)tmp << 24; ++ break; + } + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpiointmask); ++#ifdef BCMJTAG ++ case JTAG_BUS: ++ sbaddr = (uint32)si->curmap; + break; ++#endif /* BCMJTAG */ + -+ case SB_PCI: -+ /* pci gpio implementation does not support interrupt mask */ ++ default: + ASSERT(0); -+ break; -+ -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpiointmask); -+ break; + } + -+ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); ++ if (!GOODCOREADDR(sbaddr)) ++ return BADIDX; ++ ++ return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE); +} + -+/* assign the gpio to an led */ -+uint32 -+sb_gpioled(sb_t *sbh, uint32 mask, uint32 val) ++uint ++sb_corevendor(sb_t *sbh) +{ + sb_info_t *si; ++ sbconfig_t *sb; + + si = SB_INFO(sbh); -+ if (si->sb.ccrev < 16) -+ return -1; ++ sb = REGS2SB(si->curmap); + -+ /* gpio led powersave reg */ -+ return(sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); ++ return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT); +} + -+/* mask&set gpio timer val */ -+uint32 -+sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 gpiotimerval) ++uint ++sb_corerev(sb_t *sbh) +{ + sb_info_t *si; -+ si = SB_INFO(sbh); ++ sbconfig_t *sb; ++ uint sbidh; + -+ if (si->sb.ccrev < 16) -+ return -1; ++ si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); ++ sbidh = R_SBREG(si, &sb->sbidhigh); + -+ return(sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); ++ return (SBCOREREV(sbidh)); +} + ++void * ++sb_osh(sb_t *sbh) ++{ ++ sb_info_t *si; + -+/* return the slow clock source - LPO, XTAL, or PCI */ -+static uint -+sb_slowclk_src(sb_info_t *si) -+{ -+ chipcregs_t *cc; -+ -+ -+ ASSERT(sb_coreid(&si->sb) == SB_CC); -+ -+ if (si->sb.ccrev < 6) { -+ if ((BUSTYPE(si->sb.bustype) == PCI_BUS) -+ && (OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32)) & PCI_CFG_GPIO_SCS)) -+ return (SCC_SS_PCI); -+ else -+ return (SCC_SS_XTAL); -+ } else if (si->sb.ccrev < 10) { -+ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); -+ return (R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK); -+ } else /* Insta-clock */ -+ return (SCC_SS_XTAL); ++ si = SB_INFO(sbh); ++ return si->osh; +} + -+/* return the ILP (slowclock) min or max frequency */ -+static uint -+sb_slowclk_freq(sb_info_t *si, bool max) ++void ++sb_setosh(sb_t *sbh, osl_t *osh) +{ -+ chipcregs_t *cc; -+ uint32 slowclk; -+ uint div; ++ sb_info_t *si; + ++ si = SB_INFO(sbh); ++ if (si->osh != NULL) { ++ SB_ERROR(("osh is already set....\n")); ++ ASSERT(!si->osh); ++ } ++ si->osh = osh; ++} + -+ ASSERT(sb_coreid(&si->sb) == SB_CC); ++/* set/clear sbtmstatelow core-specific flags */ ++uint32 ++sb_coreflags(sb_t *sbh, uint32 mask, uint32 val) ++{ ++ sb_info_t *si; ++ sbconfig_t *sb; ++ uint32 w; + -+ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); ++ si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); + -+ /* shouldn't be here unless we've established the chip has dynamic clk control */ -+ ASSERT(R_REG(&cc->capabilities) & CAP_PWR_CTL); ++ ASSERT((val & ~mask) == 0); + -+ slowclk = sb_slowclk_src(si); -+ if (si->sb.ccrev < 6) { -+ if (slowclk == SCC_SS_PCI) -+ return (max? (PCIMAXFREQ/64) : (PCIMINFREQ/64)); -+ else -+ return (max? (XTALMAXFREQ/32) : (XTALMINFREQ/32)); -+ } else if (si->sb.ccrev < 10) { -+ div = 4 * (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); -+ if (slowclk == SCC_SS_LPO) -+ return (max? LPOMAXFREQ : LPOMINFREQ); -+ else if (slowclk == SCC_SS_XTAL) -+ return (max? (XTALMAXFREQ/div) : (XTALMINFREQ/div)); -+ else if (slowclk == SCC_SS_PCI) -+ return (max? (PCIMAXFREQ/div) : (PCIMINFREQ/div)); -+ else -+ ASSERT(0); -+ } else { -+ /* Chipc rev 10 is InstaClock */ -+ div = R_REG(&cc->system_clk_ctl) >> SYCC_CD_SHIFT; -+ div = 4 * (div + 1); -+ return (max ? XTALMAXFREQ : (XTALMINFREQ/div)); ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val; ++ W_SBREG(si, &sb->sbtmstatelow, w); + } -+ return (0); ++ ++ /* return the new value */ ++ return (R_SBREG(si, &sb->sbtmstatelow)); +} + -+static void -+sb_clkctl_setdelay(sb_info_t *si, void *chipcregs) ++/* set/clear sbtmstatehigh core-specific flags */ ++uint32 ++sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val) +{ -+ chipcregs_t * cc; -+ uint slowmaxfreq, pll_delay, slowclk; -+ uint pll_on_delay, fref_sel_delay; -+ -+ pll_delay = PLL_DELAY; ++ sb_info_t *si; ++ sbconfig_t *sb; ++ uint32 w; + -+ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay -+ * since the xtal will also be powered down by dynamic clk control logic. -+ */ -+ slowclk = sb_slowclk_src(si); -+ if (slowclk != SCC_SS_XTAL) -+ pll_delay += XTAL_ON_DELAY; ++ si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); + -+ /* Starting with 4318 it is ILP that is used for the delays */ -+ slowmaxfreq = sb_slowclk_freq(si, (si->sb.ccrev >= 10) ? FALSE : TRUE); ++ ASSERT((val & ~mask) == 0); ++ ASSERT((mask & ~SBTMH_FL_MASK) == 0); + -+ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; -+ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_SBREG(si, &sb->sbtmstatehigh) & ~mask) | val; ++ W_SBREG(si, &sb->sbtmstatehigh, w); ++ } + -+ cc = (chipcregs_t *)chipcregs; -+ W_REG(&cc->pll_on_delay, pll_on_delay); -+ W_REG(&cc->fref_sel_delay, fref_sel_delay); ++ /* return the new value */ ++ return (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_FL_MASK); +} + ++/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ +int -+sb_pwrctl_slowclk(void *sbh, bool set, uint *div) ++sb_corebist(sb_t *sbh) +{ ++ uint32 sblo; + sb_info_t *si; -+ uint origidx; -+ chipcregs_t *cc; -+ uint intr_val = 0; -+ uint err = 0; -+ ++ sbconfig_t *sb; ++ int result = 0; ++ + si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); + -+ /* chipcommon cores prior to rev6 don't support slowclkcontrol */ -+ if (si->sb.ccrev < 6) -+ return 1; ++ sblo = R_SBREG(si, &sb->sbtmstatelow); ++ W_SBREG(si, &sb->sbtmstatelow, (sblo | SBTML_FGC | SBTML_BE)); + -+ /* chipcommon cores rev10 are a whole new ball game */ -+ if (si->sb.ccrev >= 10) -+ return 1; ++ SPINWAIT(((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTD) == 0), 100000); + -+ if (set && ((*div % 4) || (*div < 4))) -+ return 2; -+ -+ INTR_OFF(si, intr_val); -+ origidx = si->curidx; -+ cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0); -+ ASSERT(cc != NULL); -+ -+ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) { -+ err = 3; -+ goto done; -+ } ++ if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTF) ++ result = BCME_ERROR; + -+ if (set) { -+ SET_REG(&cc->slow_clk_ctl, SCC_CD_MASK, ((*div / 4 - 1) << SCC_CD_SHIFT)); -+ sb_clkctl_setdelay(sbh, (void *)cc); -+ } else -+ *div = 4 * (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); ++ W_SBREG(si, &sb->sbtmstatelow, sblo); + -+done: -+ sb_setcoreidx(sbh, origidx); -+ INTR_RESTORE(si, intr_val); -+ return err; ++ return result; +} + -+/* initialize power control delay registers */ -+void sb_clkctl_init(sb_t *sbh) ++bool ++sb_iscoreup(sb_t *sbh) +{ + sb_info_t *si; -+ uint origidx; -+ chipcregs_t *cc; ++ sbconfig_t *sb; + + si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); + -+ origidx = si->curidx; ++ return ((R_SBREG(si, &sb->sbtmstatelow) & ++ (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK); ++} + -+ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) -+ return; ++/* ++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, ++ * switch back to the original core, and return the new value. ++ * ++ * When using the silicon backplane, no fidleing with interrupts or core switches are needed. ++ * ++ * Also, when using pci/pcie, we can optimize away the core switching for pci registers ++ * and (on newer pci cores) chipcommon registers. ++ */ ++static uint ++sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ uint origidx = 0; ++ uint32 *r = NULL; ++ uint w; ++ uint intr_val = 0; ++ bool fast = FALSE; + -+ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) -+ goto done; ++ ASSERT(GOODIDX(coreidx)); ++ ASSERT(regoff < SB_CORE_SIZE); ++ ASSERT((val & ~mask) == 0); + -+ /* 4317pc does not work with SlowClock less than 5 MHz */ -+ if ((BUSTYPE(si->sb.bustype) == PCMCIA_BUS) && (si->sb.ccrev >= 6) && (si->sb.ccrev < 10)) -+ SET_REG(&cc->slow_clk_ctl, SCC_CD_MASK, (ILP_DIV_5MHZ << SCC_CD_SHIFT)); ++#ifdef notyet ++ if (si->sb.bustype == SB_BUS) { ++ /* If internal bus, we can always get at everything */ ++ fast = TRUE; ++ r = (uint32 *)((uchar *)si->regs[coreidx] + regoff); ++ } else if (si->sb.bustype == PCI_BUS) { ++ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ ++ ++ if ((si->coreid[coreidx] == SB_CC) && ++ ((si->sb.buscoretype == SB_PCIE) || ++ (si->sb.buscorerev >= 13))) { ++ /* Chipc registers are mapped at 12KB */ ++ ++ fast = TRUE; ++ r = (uint32 *)((char *)si->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); ++ } else if (si->sb.buscoreidx == coreidx) { ++ /* pci registers are at either in the last 2KB of an 8KB window ++ * or, in pcie and pci rev 13 at 8KB ++ */ ++ fast = TRUE; ++ if ((si->sb.buscoretype == SB_PCIE) || ++ (si->sb.buscorerev >= 13)) ++ r = (uint32 *)((char *)si->curmap + ++ PCI_16KB0_PCIREGS_OFFSET + regoff); ++ else ++ r = (uint32 *)((char *)si->curmap + ++ ((regoff >= SBCONFIGOFF) ? ++ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + ++ regoff); ++ } ++ } ++#endif /* notyet */ + -+ /* set all Instaclk chip ILP to 1 MHz */ -+ else if (si->sb.ccrev >= 10) -+ SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK, (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); -+ -+ sb_clkctl_setdelay(si, (void *)cc); ++ if (!fast) { ++ INTR_OFF(si, intr_val); + -+done: -+ sb_setcoreidx(sbh, origidx); -+} -+void sb_pwrctl_init(sb_t *sbh) -+{ -+sb_clkctl_init(sbh); -+} -+/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */ -+uint16 -+sb_clkctl_fast_pwrup_delay(sb_t *sbh) -+{ -+ sb_info_t *si; -+ uint origidx; -+ chipcregs_t *cc; -+ uint slowminfreq; -+ uint16 fpdelay; -+ uint intr_val = 0; ++ /* save current core index */ ++ origidx = sb_coreidx(&si->sb); + -+ si = SB_INFO(sbh); -+ fpdelay = 0; -+ origidx = si->curidx; ++ /* switch core */ ++ r = (uint32*) ((uchar*) sb_setcoreidx(&si->sb, coreidx) + regoff); ++ } ++ ASSERT(r); + -+ INTR_OFF(si, intr_val); ++ /* mask and set */ ++ if (mask || val) { ++ if (regoff >= SBCONFIGOFF) { ++ w = (R_SBREG(si, r) & ~mask) | val; ++ W_SBREG(si, r, w); ++ } else { ++ w = (R_REG(si->osh, r) & ~mask) | val; ++ W_REG(si->osh, r, w); ++ } ++ } + -+ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) -+ goto done; ++ /* readback */ ++ if (regoff >= SBCONFIGOFF) ++ w = R_SBREG(si, r); ++ else ++ w = R_REG(si->osh, r); + -+ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) -+ goto done; ++ if (!fast) { ++ /* restore core index */ ++ if (origidx != coreidx) ++ sb_setcoreidx(&si->sb, origidx); + -+ slowminfreq = sb_slowclk_freq(si, FALSE); -+ fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) + (slowminfreq - 1)) / slowminfreq; ++ INTR_RESTORE(si, intr_val); ++ } + -+done: -+ sb_setcoreidx(sbh, origidx); -+ INTR_RESTORE(si, intr_val); -+ return (fpdelay); -+} -+uint16 sb_pwrctl_fast_pwrup_delay(sb_t *sbh) -+{ -+return sb_clkctl_fast_pwrup_delay(sbh); ++ return (w); +} -+/* turn primary xtal and/or pll off/on */ -+int -+sb_clkctl_xtal(sb_t *sbh, uint what, bool on) -+{ -+ sb_info_t *si; -+ uint32 in, out, outen; + -+ si = SB_INFO(sbh); ++#define DWORD_ALIGN(x) (x & ~(0x03)) ++#define BYTE_POS(x) (x & 0x3) ++#define WORD_POS(x) (x & 0x1) + -+ switch (BUSTYPE(si->sb.bustype)) { ++#define BYTE_SHIFT(x) (8 * BYTE_POS(x)) ++#define WORD_SHIFT(x) (16 * WORD_POS(x)) + ++#define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF) ++#define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF) + -+ case PCMCIA_BUS: -+ return (0); ++#define read_pci_cfg_byte(a) \ ++ (BYTE_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xff) + ++#define read_pci_cfg_write(a) \ ++ (WORD_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xffff) + -+ case PCI_BUS: + -+ /* pcie core doesn't have any mapping to control the xtal pu */ -+ if (PCIE(si)) -+ return -1; ++/* return TRUE if requested capability exists in the PCI config space */ ++static bool ++sb_find_pci_capability(sb_info_t *si, uint8 req_cap_id, uchar *buf, uint32 *buflen) ++{ ++ uint8 cap_id; ++ uint8 cap_ptr; ++ uint32 bufsize; ++ uint8 byte_val; ++ ++ if (BUSTYPE(si->sb.bustype) != PCI_BUS) ++ return FALSE; + -+ in = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_IN, sizeof (uint32)); -+ out = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32)); -+ outen = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof (uint32)); ++ /* check for Header type 0 */ ++ byte_val = read_pci_cfg_byte(PCI_CFG_HDR); ++ if ((byte_val & 0x7f) != PCI_HEADER_NORMAL) ++ return FALSE; + -+ /* -+ * Avoid glitching the clock if GPRS is already using it. -+ * We can't actually read the state of the PLLPD so we infer it -+ * by the value of XTAL_PU which *is* readable via gpioin. -+ */ -+ if (on && (in & PCI_CFG_GPIO_XTAL)) -+ return (0); ++ /* check if the capability pointer field exists */ ++ byte_val = read_pci_cfg_byte(PCI_CFG_STAT); ++ if (!(byte_val & PCI_CAPPTR_PRESENT)) ++ return FALSE; ++ ++ cap_ptr = read_pci_cfg_byte(PCI_CFG_CAPPTR); ++ /* check if the capability pointer is 0x00 */ ++ if (cap_ptr == 0x00) ++ return FALSE; + -+ if (what & XTAL) -+ outen |= PCI_CFG_GPIO_XTAL; -+ if (what & PLL) -+ outen |= PCI_CFG_GPIO_PLL; + -+ if (on) { -+ /* turn primary xtal on */ -+ if (what & XTAL) { -+ out |= PCI_CFG_GPIO_XTAL; -+ if (what & PLL) -+ out |= PCI_CFG_GPIO_PLL; -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32), out); -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof (uint32), outen); -+ OSL_DELAY(XTAL_ON_DELAY); -+ } ++ /* loop thr'u the capability list and see if the pcie capabilty exists */ + -+ /* turn pll on */ -+ if (what & PLL) { -+ out &= ~PCI_CFG_GPIO_PLL; -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32), out); -+ OSL_DELAY(2000); -+ } -+ } else { -+ if (what & XTAL) -+ out &= ~PCI_CFG_GPIO_XTAL; -+ if (what & PLL) -+ out |= PCI_CFG_GPIO_PLL; -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, sizeof (uint32), out); -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof (uint32), outen); -+ } ++ cap_id = read_pci_cfg_byte(cap_ptr); + -+ default: -+ return (-1); ++ while (cap_id != req_cap_id) { ++ cap_ptr = read_pci_cfg_byte((cap_ptr+1)); ++ if (cap_ptr == 0x00) break; ++ cap_id = read_pci_cfg_byte(cap_ptr); + } -+ -+ return (0); ++ if (cap_id != req_cap_id) { ++ return FALSE; ++ } ++ /* found the caller requested capability */ ++ if ((buf != NULL) && (buflen != NULL)) { ++ bufsize = *buflen; ++ if (!bufsize) goto end; ++ *buflen = 0; ++ /* copy the cpability data excluding cap ID and next ptr */ ++ cap_ptr += 2; ++ if ((bufsize + cap_ptr) > SZPCR) ++ bufsize = SZPCR - cap_ptr; ++ *buflen = bufsize; ++ while (bufsize--) { ++ *buf = read_pci_cfg_byte(cap_ptr); ++ cap_ptr++; ++ buf++; ++ } ++ } ++end: ++ return TRUE; +} + -+int sb_pwrctl_xtal(sb_t *sbh, uint what, bool on) ++/* return TRUE if PCIE capability exists the pci config space */ ++static inline bool ++sb_ispcie(sb_info_t *si) +{ -+return sb_clkctl_xtal(sbh,what,on); ++ return (sb_find_pci_capability(si, PCI_CAP_PCIECAP_ID, NULL, NULL)); +} + -+/* set dynamic clk control mode (forceslow, forcefast, dynamic) */ -+/* returns true if ignore pll off is set and false if it is not */ -+bool -+sb_clkctl_clk(sb_t *sbh, uint mode) ++/* scan the sb enumerated space to identify all cores */ ++static void ++BCMINITFN(sb_scan)(sb_info_t *si) +{ -+ sb_info_t *si; + uint origidx; -+ chipcregs_t *cc; -+ uint32 scc; -+ bool forcefastclk=FALSE; -+ uint intr_val = 0; -+ -+ si = SB_INFO(sbh); -+ -+ /* chipcommon cores prior to rev6 don't support dynamic clock control */ -+ if (si->sb.ccrev < 6) -+ return (FALSE); -+ -+ /* chipcommon cores rev10 are a whole new ball game */ -+ if (si->sb.ccrev >= 10) -+ return (FALSE); ++ uint i; ++ bool pci; ++ bool pcie; ++ uint pciidx; ++ uint pcieidx; ++ uint pcirev; ++ uint pcierev; + -+ INTR_OFF(si, intr_val); + -+ origidx = si->curidx; ++ /* numcores should already be set */ ++ ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES)); + -+ cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0); -+ ASSERT(cc != NULL); ++ /* save current core index */ ++ origidx = sb_coreidx(&si->sb); + -+ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) -+ goto done; ++ si->sb.buscorerev = NOREV; ++ si->sb.buscoreidx = BADIDX; + -+ switch (mode) { -+ case CLK_FAST: /* force fast (pll) clock */ -+ /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */ -+ sb_clkctl_xtal(&si->sb, XTAL, ON); ++ si->gpioidx = BADIDX; + -+ SET_REG(&cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); -+ break; ++ pci = pcie = FALSE; ++ pcirev = pcierev = NOREV; ++ pciidx = pcieidx = BADIDX; + -+ case CLK_DYNAMIC: /* enable dynamic clock control */ -+ scc = R_REG(&cc->slow_clk_ctl); -+ scc &= ~(SCC_FS | SCC_IP | SCC_XC); -+ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) -+ scc |= SCC_XC; -+ W_REG(&cc->slow_clk_ctl, scc); -+ -+ /* for dynamic control, we have to release our xtal_pu "force on" */ -+ if (scc & SCC_XC) -+ sb_clkctl_xtal(&si->sb, XTAL, OFF); -+ break; ++ for (i = 0; i < si->numcores; i++) { ++ sb_setcoreidx(&si->sb, i); ++ si->coreid[i] = sb_coreid(&si->sb); + -+ default: -+ ASSERT(0); ++ if (si->coreid[i] == SB_PCI) { ++ pciidx = i; ++ pcirev = sb_corerev(&si->sb); ++ pci = TRUE; ++ } else if (si->coreid[i] == SB_PCIE) { ++ pcieidx = i; ++ pcierev = sb_corerev(&si->sb); ++ pcie = TRUE; ++ } else if (si->coreid[i] == SB_PCMCIA) { ++ si->sb.buscorerev = sb_corerev(&si->sb); ++ si->sb.buscoretype = si->coreid[i]; ++ si->sb.buscoreidx = i; ++ } ++ } ++ if (pci && pcie) { ++ if (sb_ispcie(si)) ++ pci = FALSE; ++ else ++ pcie = FALSE; ++ } ++ if (pci) { ++ si->sb.buscoretype = SB_PCI; ++ si->sb.buscorerev = pcirev; ++ si->sb.buscoreidx = pciidx; ++ } else if (pcie) { ++ si->sb.buscoretype = SB_PCIE; ++ si->sb.buscorerev = pcierev; ++ si->sb.buscoreidx = pcieidx; + } + -+ /* Is the h/w forcing the use of the fast clk */ -+ forcefastclk = (bool)((R_REG(&cc->slow_clk_ctl) & SCC_IP) == SCC_IP); ++ /* ++ * Find the gpio "controlling core" type and index. ++ * Precedence: ++ * - if there's a chip common core - use that ++ * - else if there's a pci core (rev >= 2) - use that ++ * - else there had better be an extif core (4710 only) ++ */ ++ if (GOODIDX(sb_findcoreidx(si, SB_CC, 0))) { ++ si->gpioidx = sb_findcoreidx(si, SB_CC, 0); ++ si->gpioid = SB_CC; ++ } else if (PCI(si) && (si->sb.buscorerev >= 2)) { ++ si->gpioidx = si->sb.buscoreidx; ++ si->gpioid = SB_PCI; ++ } else if (sb_findcoreidx(si, SB_EXTIF, 0)) { ++ si->gpioidx = sb_findcoreidx(si, SB_EXTIF, 0); ++ si->gpioid = SB_EXTIF; ++ } else ++ ASSERT(si->gpioidx != BADIDX); + -+done: -+ sb_setcoreidx(sbh, origidx); -+ INTR_RESTORE(si, intr_val); -+ return (forcefastclk); ++ /* return to original core index */ ++ sb_setcoreidx(&si->sb, origidx); +} + -+bool sb_pwrctl_clk(sb_t *sbh, uint mode) -+{ -+return sb_clkctl_clk(sbh, mode); -+} -+/* register driver interrupt disabling and restoring callback functions */ ++/* may be called with core in reset */ +void -+sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, void *intrsrestore_fn, void *intrsenabled_fn, void *intr_arg) ++sb_detach(sb_t *sbh) +{ + sb_info_t *si; ++ uint idx; + + si = SB_INFO(sbh); -+ si->intr_arg = intr_arg; -+ si->intrsoff_fn = (sb_intrsoff_t)intrsoff_fn; -+ si->intrsrestore_fn = (sb_intrsrestore_t)intrsrestore_fn; -+ si->intrsenabled_fn = (sb_intrsenabled_t)intrsenabled_fn; -+ /* save current core id. when this function called, the current core -+ * must be the core which provides driver functions(il, et, wl, etc.) -+ */ -+ si->dev_coreid = si->coreid[si->curidx]; -+} -+ -+ -+void -+sb_corepciid(sb_t *sbh, uint16 *pcivendor, uint16 *pcidevice, -+ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif) -+{ -+ uint vendor, core, unit; -+ uint chip, chippkg; -+ char varname[8]; -+ uint8 class, subclass, progif; -+ -+ vendor = sb_corevendor(sbh); -+ core = sb_coreid(sbh); -+ unit = sb_coreunit(sbh); -+ -+ chip = BCMINIT(sb_chip)(sbh); -+ chippkg = BCMINIT(sb_chippkg)(sbh); + -+ progif = 0; -+ -+ /* Known vendor translations */ -+ switch (vendor) { -+ case SB_VEND_BCM: -+ vendor = VENDOR_BROADCOM; -+ break; -+ } ++ if (si == NULL) ++ return; + -+ /* Determine class based on known core codes */ -+ switch (core) { -+ case SB_ILINE20: -+ class = PCI_CLASS_NET; -+ subclass = PCI_NET_ETHER; -+ core = BCM47XX_ILINE_ID; -+ break; -+ case SB_ENET: -+ class = PCI_CLASS_NET; -+ subclass = PCI_NET_ETHER; -+ core = BCM47XX_ENET_ID; -+ break; -+ case SB_SDRAM: -+ case SB_MEMC: -+ class = PCI_CLASS_MEMORY; -+ subclass = PCI_MEMORY_RAM; -+ break; -+ case SB_PCI: -+ case SB_PCIE: -+ class = PCI_CLASS_BRIDGE; -+ subclass = PCI_BRIDGE_PCI; -+ break; -+ case SB_MIPS: -+ case SB_MIPS33: -+ class = PCI_CLASS_CPU; -+ subclass = PCI_CPU_MIPS; -+ break; -+ case SB_CODEC: -+ class = PCI_CLASS_COMM; -+ subclass = PCI_COMM_MODEM; -+ core = BCM47XX_V90_ID; -+ break; -+ case SB_USB: -+ class = PCI_CLASS_SERIAL; -+ subclass = PCI_SERIAL_USB; -+ progif = 0x10; /* OHCI */ -+ core = BCM47XX_USB_ID; -+ break; -+ case SB_USB11H: -+ class = PCI_CLASS_SERIAL; -+ subclass = PCI_SERIAL_USB; -+ progif = 0x10; /* OHCI */ -+ core = BCM47XX_USBH_ID; -+ break; -+ case SB_USB11D: -+ class = PCI_CLASS_SERIAL; -+ subclass = PCI_SERIAL_USB; -+ core = BCM47XX_USBD_ID; -+ break; -+ case SB_IPSEC: -+ class = PCI_CLASS_CRYPT; -+ subclass = PCI_CRYPT_NETWORK; -+ core = BCM47XX_IPSEC_ID; -+ break; -+ case SB_ROBO: -+ class = PCI_CLASS_NET; -+ subclass = PCI_NET_OTHER; -+ core = BCM47XX_ROBO_ID; -+ break; -+ case SB_EXTIF: -+ case SB_CC: -+ class = PCI_CLASS_MEMORY; -+ subclass = PCI_MEMORY_FLASH; -+ break; -+ case SB_D11: -+ class = PCI_CLASS_NET; -+ subclass = PCI_NET_OTHER; -+ /* Let an nvram variable override this */ -+ sprintf(varname, "wl%did", unit); -+ if ((core = getintvar(NULL, varname)) == 0) { -+ if (chip == BCM4712_DEVICE_ID) { -+ if (chippkg == BCM4712SMALL_PKG_ID) -+ core = BCM4306_D11G_ID; -+ else -+ core = BCM4306_D11DUAL_ID; ++ if (BUSTYPE(si->sb.bustype) == SB_BUS) ++ for (idx = 0; idx < SB_MAXCORES; idx++) ++ if (si->regs[idx]) { ++ REG_UNMAP(si->regs[idx]); ++ si->regs[idx] = NULL; + } -+ } -+ break; ++#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS) ++ if (si != &ksi) ++#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */ ++ MFREE(si->osh, si, sizeof(sb_info_t)); + -+ default: -+ class = subclass = progif = 0xff; -+ break; -+ } ++} + -+ *pcivendor = (uint16)vendor; -+ *pcidevice = (uint16)core; -+ *pciclass = class; -+ *pcisubclass = subclass; -+ *pciprogif = progif; ++/* use pci dev id to determine chip id for chips not having a chipcommon core */ ++static uint ++BCMINITFN(sb_pcidev2chip)(uint pcidev) ++{ ++ if ((pcidev >= BCM4710_DEVICE_ID) && (pcidev <= BCM47XX_USB_ID)) ++ return (BCM4710_CHIP_ID); ++ if ((pcidev >= BCM4402_ENET_ID) && (pcidev <= BCM4402_V90_ID)) ++ return (BCM4402_CHIP_ID); ++ if (pcidev == BCM4401_ENET_ID) ++ return (BCM4402_CHIP_ID); ++ ++ return (0); +} + ++/* convert chip number to number of i/o cores */ ++static uint ++BCMINITFN(sb_chip2numcores)(uint chip) ++{ ++ if (chip == BCM4710_CHIP_ID) ++ return (9); ++ if (chip == BCM4402_CHIP_ID) ++ return (3); ++ if (chip == BCM4306_CHIP_ID) /* < 4306c0 */ ++ return (6); ++ if (chip == BCM4704_CHIP_ID) ++ return (9); ++ if (chip == BCM5365_CHIP_ID) ++ return (7); ++ ++ SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip)); ++ ASSERT(0); ++ return (1); ++} ++ ++/* return index of coreid or BADIDX if not found */ ++static uint ++sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit) ++{ ++ uint found; ++ uint i; ++ ++ found = 0; + ++ for (i = 0; i < si->numcores; i++) ++ if (si->coreid[i] == coreid) { ++ if (found == coreunit) ++ return (i); ++ found++; ++ } + ++ return (BADIDX); ++} + -+/* use the mdio interface to write to mdio slaves */ -+static int -+sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint regaddr, uint val) ++/* ++ * this function changes logical "focus" to the indiciated core, ++ * must be called with interrupt off. ++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core ++ */ ++void* ++sb_setcoreidx(sb_t *sbh, uint coreidx) +{ -+ uint mdiodata; -+ uint i = 0; -+ sbpcieregs_t *pcieregs; ++ sb_info_t *si; ++ uint32 sbaddr; ++ uint8 tmp; + -+ pcieregs = (sbpcieregs_t*) sb_setcoreidx(&si->sb, si->sb.buscoreidx); -+ ASSERT (pcieregs); ++ si = SB_INFO(sbh); ++ ++ if (coreidx >= si->numcores) ++ return (NULL); + -+ /* enable mdio access to SERDES */ -+ W_REG((&pcieregs->mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); ++ /* ++ * If the user has provided an interrupt mask enabled function, ++ * then assert interrupts are disabled before switching the core. ++ */ ++ ASSERT((si->intrsenabled_fn == NULL) || !(*(si)->intrsenabled_fn)((si)->intr_arg)); + -+ mdiodata = MDIODATA_START | MDIODATA_WRITE | -+ (physmedia << MDIODATA_DEVADDR_SHF) | -+ (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA | val; ++ sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE); + -+ W_REG((&pcieregs->mdiodata), mdiodata); ++ switch (BUSTYPE(si->sb.bustype)) { ++ case SB_BUS: ++ /* map new one */ ++ if (!si->regs[coreidx]) { ++ si->regs[coreidx] = (void*)REG_MAP(sbaddr, SB_CORE_SIZE); ++ ASSERT(GOODREGS(si->regs[coreidx])); ++ } ++ si->curmap = si->regs[coreidx]; ++ break; + -+ PR28829_DELAY(); ++ case PCI_BUS: ++ /* point bar0 window */ ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, 4, sbaddr); ++ break; + -+ /* retry till the transaction is complete */ -+ while ( i < 10 ) { -+ if (R_REG(&(pcieregs->mdiocontrol)) & MDIOCTL_ACCESS_DONE) { -+ /* Disable mdio access to SERDES */ -+ W_REG((&pcieregs->mdiocontrol), 0); -+ return 0; ++ case PCMCIA_BUS: ++ tmp = (sbaddr >> 12) & 0x0f; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1); ++ tmp = (sbaddr >> 16) & 0xff; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1); ++ tmp = (sbaddr >> 24) & 0xff; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1); ++ break; ++#ifdef BCMJTAG ++ case JTAG_BUS: ++ /* map new one */ ++ if (!si->regs[coreidx]) { ++ si->regs[coreidx] = (void *)sbaddr; ++ ASSERT(GOODREGS(si->regs[coreidx])); + } -+ OSL_DELAY(1000); -+ i++; ++ si->curmap = si->regs[coreidx]; ++ break; ++#endif /* BCMJTAG */ + } + -+ SB_ERROR(("sb_pcie_mdiowrite: timed out\n")); -+ /* Disable mdio access to SERDES */ -+ W_REG((&pcieregs->mdiocontrol), 0); -+ ASSERT(0); -+ return 1; ++ si->curidx = coreidx; + ++ return (si->curmap); +} + -+/* indirect way to read pcie config regs*/ -+uint -+sb_pcie_readreg(void *sb, void* arg1, uint offset) ++/* ++ * this function changes logical "focus" to the indiciated core, ++ * must be called with interrupt off. ++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core ++ */ ++void* ++sb_setcore(sb_t *sbh, uint coreid, uint coreunit) ++{ ++ sb_info_t *si; ++ uint idx; ++ ++ si = SB_INFO(sbh); ++ idx = sb_findcoreidx(si, coreid, coreunit); ++ if (!GOODIDX(idx)) ++ return (NULL); ++ ++ return (sb_setcoreidx(sbh, idx)); ++} ++ ++/* return chip number */ ++uint ++sb_chip(sb_t *sbh) +{ + sb_info_t *si; -+ sb_t *sbh; -+ uint retval = 0xFFFFFFFF; -+ sbpcieregs_t *pcieregs; -+ uint addrtype; + -+ sbh = (sb_t *)sb; + si = SB_INFO(sbh); -+ ASSERT (PCIE(si)); ++ return (si->sb.chip); ++} + -+ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); -+ ASSERT (pcieregs); ++/* return chip revision number */ ++uint ++sb_chiprev(sb_t *sbh) ++{ ++ sb_info_t *si; + -+ addrtype = (uint)((uintptr)arg1); -+ switch(addrtype) { -+ case PCIE_CONFIGREGS: -+ W_REG((&pcieregs->configaddr),offset); -+ retval = R_REG(&(pcieregs->configdata)); -+ break; -+ case PCIE_PCIEREGS: -+ W_REG(&(pcieregs->pcieaddr),offset); -+ retval = R_REG(&(pcieregs->pciedata)); -+ break; -+ default: -+ ASSERT(0); -+ break; -+ } -+ return retval; ++ si = SB_INFO(sbh); ++ return (si->sb.chiprev); +} + -+/* indirect way to write pcie config/mdio/pciecore regs*/ -+uint -+sb_pcie_writereg(sb_t *sbh, void *arg1, uint offset, uint val) ++/* return chip common revision number */ ++uint ++sb_chipcrev(sb_t *sbh) +{ + sb_info_t *si; -+ sbpcieregs_t *pcieregs; -+ uint addrtype; + + si = SB_INFO(sbh); -+ ASSERT (PCIE(si)); ++ return (si->sb.ccrev); ++} + -+ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); -+ ASSERT (pcieregs); ++/* return chip package option */ ++uint ++sb_chippkg(sb_t *sbh) ++{ ++ sb_info_t *si; + -+ addrtype = (uint)((uintptr)arg1); ++ si = SB_INFO(sbh); ++ return (si->sb.chippkg); ++} + -+ switch(addrtype) { -+ case PCIE_CONFIGREGS: -+ W_REG((&pcieregs->configaddr),offset); -+ W_REG((&pcieregs->configdata),val); -+ break; -+ case PCIE_PCIEREGS: -+ W_REG((&pcieregs->pcieaddr),offset); -+ W_REG((&pcieregs->pciedata),val); -+ break; -+ default: -+ ASSERT(0); -+ break; -+ } -+ return 0; ++/* return PCI core rev. */ ++uint ++sb_pcirev(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->sb.buscorerev); +} + ++bool ++BCMINITFN(sb_war16165)(sb_t *sbh) ++{ ++ sb_info_t *si; + -+/* Build device path. Support SB, PCI, and JTAG for now. */ -+int -+sb_devpath(sb_t *sbh, char *path, int size) ++ si = SB_INFO(sbh); ++ ++ return (PCI(si) && (si->sb.buscorerev <= 10)); ++} ++ ++static void ++BCMINITFN(sb_war30841)(sb_info_t *si) +{ -+ ASSERT(path); -+ ASSERT(size >= SB_DEVPATH_BUFSZ); -+ -+ switch (BUSTYPE((SB_INFO(sbh))->sb.bustype)) { -+ case SB_BUS: -+ case JTAG_BUS: -+ sprintf(path, "sb/%u/", sb_coreidx(sbh)); -+ break; -+ case PCI_BUS: -+ ASSERT((SB_INFO(sbh))->osh); -+ sprintf(path, "pci/%u/%u/", OSL_PCI_BUS((SB_INFO(sbh))->osh), -+ OSL_PCI_SLOT((SB_INFO(sbh))->osh)); -+ break; -+ case PCMCIA_BUS: -+ SB_ERROR(("sb_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n")); -+ SB_ERROR(("sb_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n")); -+ sprintf(path, "pc/%u/%u/", 1, 1); -+ break; -+ case SDIO_BUS: -+ SB_ERROR(("sb_devpath: device 0 assumed\n")); -+ sprintf(path, "sd/%u/", sb_coreidx(sbh)); -+ break; -+ default: -+ ASSERT(0); -+ break; -+ } ++ sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); ++ sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); ++ sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); ++} + -+ return 0; ++/* return PCMCIA core rev. */ ++uint ++BCMINITFN(sb_pcmciarev)(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->sb.buscorerev); +} + -+/* Fix chip's configuration. The current core may be changed upon return */ -+static int -+sb_pci_fixcfg(sb_info_t *si) ++/* return board vendor id */ ++uint ++sb_boardvendor(sb_t *sbh) +{ -+ uint origidx, pciidx; -+ sbpciregs_t *pciregs; -+ sbpcieregs_t *pcieregs; -+ uint16 val16, *reg16; -+ char name[SB_DEVPATH_BUFSZ+16], *value; -+ char devpath[SB_DEVPATH_BUFSZ]; ++ sb_info_t *si; + -+ ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS); ++ si = SB_INFO(sbh); ++ return (si->sb.boardvendor); ++} ++ ++/* return boardtype */ ++uint ++sb_boardtype(sb_t *sbh) ++{ ++ sb_info_t *si; ++ char *var; + -+ /* Fix PCI(e) SROM shadow area */ -+ /* save the current index */ -+ origidx = sb_coreidx(&si->sb); ++ si = SB_INFO(sbh); + -+ /* check 'pi' is correct and fix it if not */ -+ if (si->sb.buscoretype == SB_PCIE) { -+ pcieregs = (sbpcieregs_t *)sb_setcore(&si->sb, SB_PCIE, 0); -+ ASSERT(pcieregs); -+ reg16 = &pcieregs->sprom[SRSH_PI_OFFSET]; -+ } -+ else if (si->sb.buscoretype == SB_PCI) { -+ pciregs = (sbpciregs_t *)sb_setcore(&si->sb, SB_PCI, 0); -+ ASSERT(pciregs); -+ reg16 = &pciregs->sprom[SRSH_PI_OFFSET]; -+ } -+ else { -+ ASSERT(0); -+ return -1; -+ } -+ pciidx = sb_coreidx(&si->sb); -+ val16 = R_REG(reg16); -+ if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) { -+ val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK); -+ W_REG(reg16, val16); -+ } ++ if (BUSTYPE(si->sb.bustype) == SB_BUS && si->sb.boardtype == 0xffff) { ++ /* boardtype format is a hex string */ ++ si->sb.boardtype = getintvar(NULL, "boardtype"); + -+ /* restore the original index */ -+ sb_setcoreidx(&si->sb, origidx); -+ -+ /* Fix bar0window */ -+ /* !do it last, it changes the current core! */ -+ if (sb_devpath(&si->sb, devpath, sizeof(devpath))) -+ return -1; -+ sprintf(name, "%sb0w", devpath); -+ if ((value = getvar(NULL, name))) { -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32), -+ bcm_strtoul(value, NULL, 16)); -+ /* update curidx since the current core is changed */ -+ si->curidx = _sb_coreidx(si); -+ if (si->curidx == BADIDX) { -+ SB_ERROR(("sb_pci_fixcfg: bad core index\n")); -+ return -1; ++ /* backward compatibility for older boardtype string format */ ++ if ((si->sb.boardtype == 0) && (var = getvar(NULL, "boardtype"))) { ++ if (!strcmp(var, "bcm94710dev")) ++ si->sb.boardtype = BCM94710D_BOARD; ++ else if (!strcmp(var, "bcm94710ap")) ++ si->sb.boardtype = BCM94710AP_BOARD; ++ else if (!strcmp(var, "bu4710")) ++ si->sb.boardtype = BU4710_BOARD; ++ else if (!strcmp(var, "bcm94702mn")) ++ si->sb.boardtype = BCM94702MN_BOARD; ++ else if (!strcmp(var, "bcm94710r1")) ++ si->sb.boardtype = BCM94710R1_BOARD; ++ else if (!strcmp(var, "bcm94710r4")) ++ si->sb.boardtype = BCM94710R4_BOARD; ++ else if (!strcmp(var, "bcm94702cpci")) ++ si->sb.boardtype = BCM94702CPCI_BOARD; ++ else if (!strcmp(var, "bcm95380_rr")) ++ si->sb.boardtype = BCM95380RR_BOARD; + } + } + -+ return 0; ++ return (si->sb.boardtype); +} + -diff -Naur linux.old/drivers/net/hnd/shared_ksyms.sh linux.dev/drivers/net/hnd/shared_ksyms.sh ---- linux.old/drivers/net/hnd/shared_ksyms.sh 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/hnd/shared_ksyms.sh 2006-04-06 15:34:15.000000000 +0200 -@@ -0,0 +1,21 @@ -+#!/bin/sh -+# -+# Copyright 2004, Broadcom Corporation -+# All Rights Reserved. -+# -+# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+# -+# $Id: shared_ksyms.sh,v 1.1 2005/03/16 13:50:00 wbx Exp $ -+# -+ -+cat < -+#include -+EOF -+ -+for file in $* ; do -+ ${NM} $file | sed -ne 's/[0-9A-Fa-f]* [DT] \([^ ]*\)/extern void \1; EXPORT_SYMBOL(\1);/p' -+done -diff -Naur linux.old/drivers/net/wireless/Config.in linux.dev/drivers/net/wireless/Config.in ---- linux.old/drivers/net/wireless/Config.in 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/drivers/net/wireless/Config.in 2006-04-06 17:04:48.000000000 +0200 -@@ -13,6 +13,8 @@ - fi - - if [ "$CONFIG_PCI" = "y" ]; then -+ dep_tristate ' Proprietary Broadcom BCM43xx 802.11 Wireless support (old)' CONFIG_WL -+ dep_tristate ' Proprietary Broadcom BCM43xx 802.11 Wireless support (new)' CONFIG_WL2 - dep_tristate ' Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)' CONFIG_PLX_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL - dep_tristate ' Hermes in TMD7160/NCP130 based PCI adaptor support (Pheecom WL-PCI etc.) (EXPERIMENTAL)' CONFIG_TMD_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL - dep_tristate ' Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)' CONFIG_PCI_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL -diff -Naur linux.old/drivers/net/wl/Makefile linux.dev/drivers/net/wl/Makefile ---- linux.old/drivers/net/wl/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl/Makefile 2006-04-06 16:56:38.000000000 +0200 -@@ -0,0 +1,27 @@ -+# -+# Makefile for the Broadcom wl driver -+# -+# Copyright 2004, Broadcom Corporation -+# All Rights Reserved. -+# -+# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+# -+# $Id: Makefile,v 1.2 2005/03/29 03:32:18 mbm Exp $ ++/* return bus type of sbh device */ ++uint ++sb_bus(sb_t *sbh) ++{ ++ sb_info_t *si; + -+EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER ++ si = SB_INFO(sbh); ++ return (si->sb.bustype); ++} + -+O_TARGET := wl.o ++/* return bus core type */ ++uint ++sb_buscoretype(sb_t *sbh) ++{ ++ sb_info_t *si; + -+obj-y := apsta_aeskeywrap.o apsta_aes.o apsta_bcmwpa.o apsta_d11ucode.o -+obj-y += apsta_hmac.o apsta_md5.o apsta_passhash.o apsta_prf.o apsta_rc4.o -+obj-y += apsta_rijndael-alg-fst.o apsta_sha1.o apsta_tkhash.o apsta_wlc_led.o -+obj-y += apsta_wlc_phy.o apsta_wlc_rate.o apsta_wlc_security.o -+obj-y += apsta_wlc_sup.o apsta_wlc_wet.o apsta_wl_linux.o apsta_wlc.o -+obj-y += compat.o hnddma.o ++ si = SB_INFO(sbh); + -+obj-m := $(O_TARGET) ++ return (si->sb.buscoretype); ++} + -+include $(TOPDIR)/Rules.make -diff -Naur linux.old/drivers/net/wl/compat.c linux.dev/drivers/net/wl/compat.c ---- linux.old/drivers/net/wl/compat.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl/compat.c 2006-04-06 17:12:19.000000000 +0200 -@@ -0,0 +1,237 @@ -+/* -+ * Misc useful OS-independent routines. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ ++/* return bus core revision */ ++uint ++sb_buscorerev(sb_t *sbh) ++{ ++ sb_info_t *si; ++ si = SB_INFO(sbh); + -+#include -+#ifdef BCMDRIVER -+#include -+#include -+#include -+#else -+#include -+#include -+#endif -+#include "pktq.h" -+#include -+#include -+#include ++ return (si->sb.buscorerev); ++} + -+#ifdef BCMDRIVER -+/* copy a pkt buffer chain into a buffer */ ++/* return list of found cores */ +uint -+pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++sb_corelist(sb_t *sbh, uint coreid[]) +{ -+ uint n, ret = 0; ++ sb_info_t *si; + -+ if (len < 0) -+ len = 4096; /* "infinite" */ ++ si = SB_INFO(sbh); + -+ /* skip 'offset' bytes */ -+ for (; p && offset; p = PKTNEXT(osh, p)) { -+ if (offset < (uint)PKTLEN(osh, p)) -+ break; -+ offset -= PKTLEN(osh, p); -+ } ++ bcopy((uchar*)si->coreid, (uchar*)coreid, (si->numcores * sizeof(uint))); ++ return (si->numcores); ++} + -+ if (!p) -+ return 0; ++/* return current register mapping */ ++void * ++sb_coreregs(sb_t *sbh) ++{ ++ sb_info_t *si; + -+ /* copy the data */ -+ for (; p && len; p = PKTNEXT(osh, p)) { -+ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); -+ bcopy(PKTDATA(osh, p) + offset, buf, n); -+ buf += n; -+ len -= n; -+ ret += n; -+ offset = 0; -+ } ++ si = SB_INFO(sbh); ++ ASSERT(GOODREGS(si->curmap)); + -+ return ret; ++ return (si->curmap); +} + -+/* return total length of buffer chain */ -+uint -+pkttotlen(osl_t *osh, void *p) ++ ++/* do buffered registers update */ ++void ++sb_commit(sb_t *sbh) +{ -+ uint total; ++ sb_info_t *si; ++ uint origidx; ++ uint intr_val = 0; + -+ total = 0; -+ for (; p; p = PKTNEXT(osh, p)) -+ total += PKTLEN(osh, p); -+ return (total); -+} ++ si = SB_INFO(sbh); + -+void -+pktq_init(struct pktq *q, uint maxlen, const uint8 prio_map[]) -+{ -+ q->head = q->tail = NULL; -+ q->maxlen = maxlen; -+ q->len = 0; -+ if (prio_map) { -+ q->priority = TRUE; -+ bcopy(prio_map, q->prio_map, sizeof(q->prio_map)); -+ } -+ else -+ q->priority = FALSE; -+} ++ origidx = si->curidx; ++ ASSERT(GOODIDX(origidx)); ++ ++ INTR_OFF(si, intr_val); ++ ++ /* switch over to chipcommon core if there is one, else use pci */ ++ if (si->sb.ccrev != NOREV) { ++ chipcregs_t *ccregs = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0); ++ ++ /* do the buffer registers update */ ++ W_REG(si->osh, &ccregs->broadcastaddress, SB_COMMIT); ++ W_REG(si->osh, &ccregs->broadcastdata, 0x0); ++ } else if (PCI(si)) { ++ sbpciregs_t *pciregs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0); ++ ++ /* do the buffer registers update */ ++ W_REG(si->osh, &pciregs->bcastaddr, SB_COMMIT); ++ W_REG(si->osh, &pciregs->bcastdata, 0x0); ++ } else ++ ASSERT(0); + ++ /* restore core index */ ++ sb_setcoreidx(sbh, origidx); ++ INTR_RESTORE(si, intr_val); ++} + -+/* should always check pktq_full before calling pktenq */ ++/* reset and re-enable a core ++ * inputs: ++ * bits - core specific bits that are set during and after reset sequence ++ * resetbits - core specific bits that are set only during reset sequence ++ */ +void -+pktenq(struct pktq *q, void *p, bool lifo) ++sb_core_reset(sb_t *sbh, uint32 bits, uint32 resetbits) +{ -+ void *next, *prev; ++ sb_info_t *si; ++ sbconfig_t *sb; ++ volatile uint32 dummy; + -+ /* allow 10 pkts slack */ -+ ASSERT(q->len < (q->maxlen + 10)); ++ si = SB_INFO(sbh); ++ ASSERT(GOODREGS(si->curmap)); ++ sb = REGS2SB(si->curmap); + -+ /* Queueing chains not allowed */ -+ ASSERT(PKTLINK(p) == NULL); ++ /* ++ * Must do the disable sequence first to work for arbitrary current core state. ++ */ ++ sb_core_disable(sbh, (bits | resetbits)); + -+ /* Queue is empty */ -+ if (q->tail == NULL) { -+ ASSERT(q->head == NULL); -+ q->head = q->tail = p; -+ } ++ /* ++ * Now do the initialization sequence. ++ */ + -+ /* Insert at head or tail */ -+ else if (q->priority == FALSE) { -+ /* Insert at head (LIFO) */ -+ if (lifo) { -+ PKTSETLINK(p, q->head); -+ q->head = p; -+ } -+ /* Insert at tail (FIFO) */ -+ else { -+ ASSERT(PKTLINK(q->tail) == NULL); -+ PKTSETLINK(q->tail, p); -+ PKTSETLINK(p, NULL); -+ q->tail = p; -+ } -+ } ++ /* set reset while enabling the clock and forcing them on throughout the core */ ++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | SBTML_RESET | bits | resetbits)); ++ dummy = R_SBREG(si, &sb->sbtmstatelow); ++ OSL_DELAY(1); + -+ /* Insert by priority */ -+ else { -+ /* legal priorities 0-7 */ -+ ASSERT(PKTPRIO(p) <= MAXPRIO); -+ -+ ASSERT(q->head); -+ ASSERT(q->tail); -+ /* Shortcut to insertion at tail */ -+ if (_pktq_pri(q, PKTPRIO(p)) < _pktq_pri(q, PKTPRIO(q->tail)) || -+ (!lifo && _pktq_pri(q, PKTPRIO(p)) <= _pktq_pri(q, PKTPRIO(q->tail)))) { -+ prev = q->tail; -+ next = NULL; -+ } -+ /* Insert at head or in the middle */ -+ else { -+ prev = NULL; -+ next = q->head; -+ } -+ /* Walk the queue */ -+ for (; next; prev = next, next = PKTLINK(next)) { -+ /* Priority queue invariant */ -+ ASSERT(!prev || _pktq_pri(q, PKTPRIO(prev)) >= _pktq_pri(q, PKTPRIO(next))); -+ /* Insert at head of string of packets of same priority (LIFO) */ -+ if (lifo) { -+ if (_pktq_pri(q, PKTPRIO(p)) >= _pktq_pri(q, PKTPRIO(next))) -+ break; -+ } -+ /* Insert at tail of string of packets of same priority (FIFO) */ -+ else { -+ if (_pktq_pri(q, PKTPRIO(p)) > _pktq_pri(q, PKTPRIO(next))) -+ break; -+ } -+ } -+ /* Insert at tail */ -+ if (next == NULL) { -+ ASSERT(PKTLINK(q->tail) == NULL); -+ PKTSETLINK(q->tail, p); -+ PKTSETLINK(p, NULL); -+ q->tail = p; -+ } -+ /* Insert in the middle */ -+ else if (prev) { -+ PKTSETLINK(prev, p); -+ PKTSETLINK(p, next); -+ } -+ /* Insert at head */ -+ else { -+ PKTSETLINK(p, q->head); -+ q->head = p; -+ } ++ if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_SERR) { ++ W_SBREG(si, &sb->sbtmstatehigh, 0); ++ } ++ if ((dummy = R_SBREG(si, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) { ++ AND_SBREG(si, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO)); + } + -+ /* List invariants after insertion */ -+ ASSERT(q->head); -+ ASSERT(PKTLINK(q->tail) == NULL); ++ /* clear reset and allow it to propagate throughout the core */ ++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | bits)); ++ dummy = R_SBREG(si, &sb->sbtmstatelow); ++ OSL_DELAY(1); + -+ q->len++; ++ /* leave clock enabled */ ++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_CLK | bits)); ++ dummy = R_SBREG(si, &sb->sbtmstatelow); ++ OSL_DELAY(1); +} + -+/* dequeue packet at head */ -+void* -+pktdeq(struct pktq *q) ++void ++sb_core_tofixup(sb_t *sbh) +{ -+ void *p; ++ sb_info_t *si; ++ sbconfig_t *sb; + -+ if ((p = q->head)) { -+ ASSERT(q->tail); -+ q->head = PKTLINK(p); -+ PKTSETLINK(p, NULL); -+ q->len--; -+ if (q->head == NULL) -+ q->tail = NULL; -+ } -+ else { -+ ASSERT(q->tail == NULL); ++ si = SB_INFO(sbh); ++ ++ if ((BUSTYPE(si->sb.bustype) != PCI_BUS) || PCIE(si) || ++ (PCI(si) && (si->sb.buscorerev >= 5))) ++ return; ++ ++ ASSERT(GOODREGS(si->curmap)); ++ sb = REGS2SB(si->curmap); ++ ++ if (BUSTYPE(si->sb.bustype) == SB_BUS) { ++ SET_SBREG(si, &sb->sbimconfiglow, ++ SBIMCL_RTO_MASK | SBIMCL_STO_MASK, ++ (0x5 << SBIMCL_RTO_SHIFT) | 0x3); ++ } else { ++ if (sb_coreid(sbh) == SB_PCI) { ++ SET_SBREG(si, &sb->sbimconfiglow, ++ SBIMCL_RTO_MASK | SBIMCL_STO_MASK, ++ (0x3 << SBIMCL_RTO_SHIFT) | 0x2); ++ } else { ++ SET_SBREG(si, &sb->sbimconfiglow, (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0); ++ } + } + -+ return (p); ++ sb_commit(sbh); +} + -+/* dequeue packet at tail */ -+void* -+pktdeqtail(struct pktq *q) ++/* ++ * Set the initiator timeout for the "master core". ++ * The master core is defined to be the core in control ++ * of the chip and so it issues accesses to non-memory ++ * locations (Because of dma *any* core can access memeory). ++ * ++ * The routine uses the bus to decide who is the master: ++ * SB_BUS => mips ++ * JTAG_BUS => chipc ++ * PCI_BUS => pci or pcie ++ * PCMCIA_BUS => pcmcia ++ * SDIO_BUS => pcmcia ++ * ++ * This routine exists so callers can disable initiator ++ * timeouts so accesses to very slow devices like otp ++ * won't cause an abort. The routine allows arbitrary ++ * settings of the service and request timeouts, though. ++ * ++ * Returns the timeout state before changing it or -1 ++ * on error. ++ */ ++ ++#define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK) ++ ++uint32 ++sb_set_initiator_to(sb_t *sbh, uint32 to) +{ -+ void *p; -+ void *next, *prev; ++ sb_info_t *si; ++ uint origidx, idx; ++ uint intr_val = 0; ++ uint32 tmp, ret = 0xffffffff; ++ sbconfig_t *sb; + -+ if (q->head == q->tail) { /* last packet on queue or queue empty */ -+ p = q->head; -+ q->head = q->tail = NULL; -+ q->len = 0; -+ return(p); -+ } ++ si = SB_INFO(sbh); + -+ /* start walk at head */ -+ prev = NULL; -+ next = q->head; ++ if ((to & ~TO_MASK) != 0) ++ return ret; + -+ /* Walk the queue to find prev of q->tail */ -+ for (; next; prev = next, next = PKTLINK(next)) { -+ if (next == q->tail) -+ break; ++ /* Figure out the master core */ ++ idx = BADIDX; ++ switch (BUSTYPE(si->sb.bustype)) { ++ case PCI_BUS: ++ idx = si->sb.buscoreidx; ++ break; ++ case JTAG_BUS: ++ idx = SB_CC_IDX; ++ break; ++ case PCMCIA_BUS: ++ case SDIO_BUS: ++ idx = sb_findcoreidx(si, SB_PCMCIA, 0); ++ break; ++ case SB_BUS: ++ if ((idx = sb_findcoreidx(si, SB_MIPS33, 0)) == BADIDX) ++ idx = sb_findcoreidx(si, SB_MIPS, 0); ++ break; ++ default: ++ ASSERT(0); + } ++ if (idx == BADIDX) ++ return ret; + -+ ASSERT(prev); ++ INTR_OFF(si, intr_val); ++ origidx = sb_coreidx(sbh); + -+ PKTSETLINK(prev, NULL); -+ q->tail = prev; -+ q->len--; -+ p = next; ++ sb = REGS2SB(sb_setcoreidx(sbh, idx)); + -+ return (p); -+} -+#endif ++ tmp = R_SBREG(si, &sb->sbimconfiglow); ++ ret = tmp & TO_MASK; ++ W_SBREG(si, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to); + ++ sb_commit(sbh); ++ sb_setcoreidx(sbh, origidx); ++ INTR_RESTORE(si, intr_val); ++ return ret; ++} + -diff -Naur linux.old/drivers/net/wl/hnddma.c linux.dev/drivers/net/wl/hnddma.c ---- linux.old/drivers/net/wl/hnddma.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl/hnddma.c 2006-04-06 16:58:24.000000000 +0200 -@@ -0,0 +1,1453 @@ -+/* -+ * Generic Broadcom Home Networking Division (HND) DMA module. -+ * This supports the following chips: BCM42xx, 44xx, 47xx . -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ -+ */ ++void ++sb_core_disable(sb_t *sbh, uint32 bits) ++{ ++ sb_info_t *si; ++ volatile uint32 dummy; ++ uint32 rej; ++ sbconfig_t *sb; + -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++ si = SB_INFO(sbh); + -+struct dma_info; /* forward declaration */ -+#define di_t struct dma_info ++ ASSERT(GOODREGS(si->curmap)); ++ sb = REGS2SB(si->curmap); + -+#include "sbhnddma.h" -+#include "hnddma.h" ++ /* if core is already in reset, just return */ ++ if (R_SBREG(si, &sb->sbtmstatelow) & SBTML_RESET) ++ return; + -+/* debug/trace */ -+#define DMA_ERROR(args) -+#define DMA_TRACE(args) ++ /* reject value changed between sonics 2.2 and 2.3 */ ++ if (si->sb.sonicsrev == SONICS_2_2) ++ rej = (1 << SBTML_REJ_SHIFT); ++ else ++ rej = (2 << SBTML_REJ_SHIFT); + -+/* default dma message level (if input msg_level pointer is null in dma_attach()) */ -+static uint dma_msg_level = -+ 0; ++ /* if clocks are not enabled, put into reset and return */ ++ if ((R_SBREG(si, &sb->sbtmstatelow) & SBTML_CLK) == 0) ++ goto disable; + -+#define MAXNAMEL 8 ++ /* set target reject and spin until busy is clear (preserve core-specific bits) */ ++ OR_SBREG(si, &sb->sbtmstatelow, rej); ++ dummy = R_SBREG(si, &sb->sbtmstatelow); ++ OSL_DELAY(1); ++ SPINWAIT((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000); ++ if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY) ++ SB_ERROR(("%s: target state still busy\n", __FUNCTION__)); + -+/* dma engine software state */ -+typedef struct dma_info { -+ hnddma_t hnddma; /* exported structure */ -+ uint *msg_level; /* message level pointer */ -+ char name[MAXNAMEL]; /* callers name for diag msgs */ -+ -+ void *osh; /* os handle */ -+ sb_t *sbh; /* sb handle */ -+ -+ bool dma64; /* dma64 enabled */ -+ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ -+ -+ dma32regs_t *d32txregs; /* 32 bits dma tx engine registers */ -+ dma32regs_t *d32rxregs; /* 32 bits dma rx engine registers */ -+ dma64regs_t *d64txregs; /* 64 bits dma tx engine registers */ -+ dma64regs_t *d64rxregs; /* 64 bits dma rx engine registers */ ++ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) { ++ OR_SBREG(si, &sb->sbimstate, SBIM_RJ); ++ dummy = R_SBREG(si, &sb->sbimstate); ++ OSL_DELAY(1); ++ SPINWAIT((R_SBREG(si, &sb->sbimstate) & SBIM_BY), 100000); ++ } + -+ uint32 dma64align; /* either 8k or 4k depends on number of dd */ -+ dma32dd_t *txd32; /* pointer to dma32 tx descriptor ring */ -+ dma64dd_t *txd64; /* pointer to dma64 tx descriptor ring */ -+ uint ntxd; /* # tx descriptors tunable */ -+ uint txin; /* index of next descriptor to reclaim */ -+ uint txout; /* index of next descriptor to post */ -+ uint txavail; /* # free tx descriptors */ -+ void **txp; /* pointer to parallel array of pointers to packets */ -+ ulong txdpa; /* physical address of descriptor ring */ -+ uint txdalign; /* #bytes added to alloc'd mem to align txd */ -+ uint txdalloc; /* #bytes allocated for the ring */ ++ /* set reset and reject while enabling the clocks */ ++ W_SBREG(si, &sb->sbtmstatelow, (bits | SBTML_FGC | SBTML_CLK | rej | SBTML_RESET)); ++ dummy = R_SBREG(si, &sb->sbtmstatelow); ++ OSL_DELAY(10); + -+ dma32dd_t *rxd32; /* pointer to dma32 rx descriptor ring */ -+ dma64dd_t *rxd64; /* pointer to dma64 rx descriptor ring */ -+ uint nrxd; /* # rx descriptors tunable */ -+ uint rxin; /* index of next descriptor to reclaim */ -+ uint rxout; /* index of next descriptor to post */ -+ void **rxp; /* pointer to parallel array of pointers to packets */ -+ ulong rxdpa; /* physical address of descriptor ring */ -+ uint rxdalign; /* #bytes added to alloc'd mem to align rxd */ -+ uint rxdalloc; /* #bytes allocated for the ring */ ++ /* don't forget to clear the initiator reject bit */ ++ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) ++ AND_SBREG(si, &sb->sbimstate, ~SBIM_RJ); + -+ /* tunables */ -+ uint rxbufsize; /* rx buffer size in bytes */ -+ uint nrxpost; /* # rx buffers to keep posted */ -+ uint rxoffset; /* rxcontrol offset */ -+ uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */ -+ uint ddoffsethigh; /* add to get dma address of descriptor ring, high 32 bits */ -+ uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */ -+ uint dataoffsethigh; /* add to get dma address of data buffer, high 32 bits */ -+} dma_info_t; ++disable: ++ /* leave reset and reject asserted */ ++ W_SBREG(si, &sb->sbtmstatelow, (bits | rej | SBTML_RESET)); ++ OSL_DELAY(1); ++} + -+#ifdef BCMDMA64 -+#define DMA64_ENAB(di) ((di)->dma64) -+#else -+#define DMA64_ENAB(di) (0) -+#endif ++/* set chip watchdog reset timer to fire in 'ticks' backplane cycles */ ++void ++sb_watchdog(sb_t *sbh, uint ticks) ++{ ++ sb_info_t *si = SB_INFO(sbh); + -+/* descriptor bumping macros */ -+#define XXD(x, n) ((x) & ((n) - 1)) -+#define TXD(x) XXD((x), di->ntxd) -+#define RXD(x) XXD((x), di->nrxd) -+#define NEXTTXD(i) TXD(i + 1) -+#define PREVTXD(i) TXD(i - 1) -+#define NEXTRXD(i) RXD(i + 1) -+#define NTXDACTIVE(h, t) TXD(t - h) -+#define NRXDACTIVE(h, t) RXD(t - h) ++ /* make sure we come up in fast clock mode */ ++ sb_clkctl_clk(sbh, CLK_FAST); + -+/* macros to convert between byte offsets and indexes */ -+#define B2I(bytes, type) ((bytes) / sizeof(type)) -+#define I2B(index, type) ((index) * sizeof(type)) ++ /* instant NMI */ ++ switch (si->gpioid) { ++ case SB_CC: ++#ifdef __mips__ ++ if (sb_chip(sbh) == BCM4785_CHIP_ID && ticks <= 1) ++ MTC0(C0_BROADCOM, 4, (1 << 22)); ++#endif /* __mips__ */ ++ sb_corereg(si, 0, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); ++#ifdef __mips__ ++ if (sb_chip(sbh) == BCM4785_CHIP_ID && ticks <= 1) { ++ __asm__ __volatile__ ( ++ ".set\tmips3\n\t" ++ "sync\n\t" ++ "wait\n\t" ++ ".set\tmips0" ++ ); ++ while (1); ++ } ++#endif /* __mips__ */ ++ break; ++ case SB_EXTIF: ++ sb_corereg(si, si->gpioidx, OFFSETOF(extifregs_t, watchdog), ~0, ticks); ++ break; ++ } ++} + -+#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ -+#define PCI32ADDR_HIGH_SHIFT 30 ++/* initialize the pcmcia core */ ++void ++sb_pcmcia_init(sb_t *sbh) ++{ ++ sb_info_t *si; ++ uint8 cor = 0; + ++ si = SB_INFO(sbh); + -+/* prototypes */ -+static bool dma_isaddrext(dma_info_t *di); -+static bool dma_alloc(dma_info_t *di, uint direction); ++ /* enable d11 mac interrupts */ ++ OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1); ++ cor |= COR_IRQEN | COR_FUNEN; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1); + -+static bool dma32_alloc(dma_info_t *di, uint direction); -+static void dma32_txreset(dma_info_t *di); -+static void dma32_rxreset(dma_info_t *di); -+static bool dma32_txsuspendedidle(dma_info_t *di); -+static int dma32_txfast(dma_info_t *di, void *p0, uint32 coreflags); -+static void* dma32_getnexttxp(dma_info_t *di, bool forceall); -+static void* dma32_getnextrxp(dma_info_t *di, bool forceall); -+static void dma32_txrotate(di_t *di); -+ -+/* prototype or stubs */ -+#ifdef BCMDMA64 -+static bool dma64_alloc(dma_info_t *di, uint direction); -+static void dma64_txreset(dma_info_t *di); -+static void dma64_rxreset(dma_info_t *di); -+static bool dma64_txsuspendedidle(dma_info_t *di); -+static int dma64_txfast(dma_info_t *di, void *p0, uint32 coreflags); -+static void* dma64_getnexttxp(dma_info_t *di, bool forceall); -+static void* dma64_getnextrxp(dma_info_t *di, bool forceall); -+static void dma64_txrotate(di_t *di); -+#else -+static bool dma64_alloc(dma_info_t *di, uint direction) { return TRUE; } -+static void dma64_txreset(dma_info_t *di) {} -+static void dma64_rxreset(dma_info_t *di) {} -+static bool dma64_txsuspendedidle(dma_info_t *di) { return TRUE;} -+static int dma64_txfast(dma_info_t *di, void *p0, uint32 coreflags) { return 0; } -+static void* dma64_getnexttxp(dma_info_t *di, bool forceall) { return NULL; } -+static void* dma64_getnextrxp(dma_info_t *di, bool forceall) { return NULL; } -+static void dma64_txrotate(di_t *di) { return; } -+#endif ++} + -+/* old dmaregs struct for compatibility */ -+typedef volatile struct { -+ /* transmit channel */ -+ uint32 xmtcontrol; /* enable, et al */ -+ uint32 xmtaddr; /* descriptor ring base address (4K aligned) */ -+ uint32 xmtptr; /* last descriptor posted to chip */ -+ uint32 xmtstatus; /* current active descriptor, et al */ -+ -+ /* receive channel */ -+ uint32 rcvcontrol; /* enable, et al */ -+ uint32 rcvaddr; /* descriptor ring base address (4K aligned) */ -+ uint32 rcvptr; /* last descriptor posted to chip */ -+ uint32 rcvstatus; /* current active descriptor, et al */ -+} dmaregs_t; + -+void* -+dma_attach(void *drv, void *osh, char *name, dmaregs_t *regs, uint ntxd, uint nrxd, -+ uint rxbufsize, uint nrxpost, uint rxoffset, uint ddoffset, uint dataoffset, uint *msg_level) ++/* ++ * Configure the pci core for pci client (NIC) action ++ * coremask is the bitvec of cores by index to be enabled. ++ */ ++void ++BCMINITFN(sb_pci_setup)(sb_t *sbh, uint coremask) +{ -+ dma_info_t *di; -+ uint size; -+ dma32regs_t *dmaregstx = regs; -+ dma32regs_t *dmaregsrx = dmaregstx + 1; -+ -+ /* allocate private info structure */ -+ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { -+ return (NULL); -+ } -+ bzero((char*)di, sizeof (dma_info_t)); -+ di->msg_level = msg_level ? msg_level : &dma_msg_level; ++ sb_info_t *si; ++ sbconfig_t *sb; ++ sbpciregs_t *pciregs; ++ uint32 sbflag; ++ uint32 w; ++ uint idx; ++ int reg_val; + -+ /* check arguments */ -+ ASSERT(ISPOWEROF2(ntxd)); -+ ASSERT(ISPOWEROF2(nrxd)); -+ if (nrxd == 0) -+ ASSERT(dmaregsrx == NULL); -+ if (ntxd == 0) -+ ASSERT(dmaregstx == NULL); ++ si = SB_INFO(sbh); + -+ ASSERT(ntxd <= D32MAXDD); -+ ASSERT(nrxd <= D32MAXDD); -+ di->d32txregs = (dma32regs_t *)dmaregstx; -+ di->d32rxregs = (dma32regs_t *)dmaregsrx; ++ /* if not pci bus, we're done */ ++ if (BUSTYPE(si->sb.bustype) != PCI_BUS) ++ return; + -+ /* make a private copy of our callers name */ -+ strncpy(di->name, name, MAXNAMEL); -+ di->name[MAXNAMEL-1] = '\0'; ++ ASSERT(PCI(si) || PCIE(si)); ++ ASSERT(si->sb.buscoreidx != BADIDX); + -+ di->osh = osh; -+ di->sbh = NULL; ++ /* get current core index */ ++ idx = si->curidx; + -+ /* save tunables */ -+ di->ntxd = ntxd; -+ di->nrxd = nrxd; -+ di->rxbufsize = rxbufsize; -+ di->nrxpost = nrxpost; -+ di->rxoffset = rxoffset; ++ /* we interrupt on this backplane flag number */ ++ ASSERT(GOODREGS(si->curmap)); ++ sb = REGS2SB(si->curmap); ++ sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK; + -+ di->ddoffsetlow = ddoffset; -+ di->dataoffsetlow = dataoffset; -+ di->ddoffsethigh = 0; -+ di->dataoffsethigh = 0; -+ -+ di->addrext = 0; -+ -+ DMA_TRACE(("%s: dma_attach: osh %p ntxd %d nrxd %d rxbufsize %d nrxpost %d rxoffset %d ddoffset 0x%x dataoffset 0x%x\n", -+ name, osh, ntxd, nrxd, rxbufsize, nrxpost, rxoffset, di->ddoffsetlow, di->dataoffsetlow)); ++ /* switch over to pci core */ ++ pciregs = (sbpciregs_t*) sb_setcoreidx(sbh, si->sb.buscoreidx); ++ sb = REGS2SB(pciregs); + -+ /* allocate tx packet pointer vector */ -+ if (ntxd) { -+ size = ntxd * sizeof (void*); -+ if ((di->txp = MALLOC(osh, size)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: out of tx memory, malloced %d bytes\n", di->name, MALLOCED(osh))); -+ goto fail; ++ /* ++ * Enable sb->pci interrupts. Assume ++ * PCI rev 2.3 support was added in pci core rev 6 and things changed.. ++ */ ++ if (PCIE(si) || (PCI(si) && ((si->sb.buscorerev) >= 6))) { ++ /* pci config write to set this core bit in PCIIntMask */ ++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32)); ++ w |= (coremask << PCI_SBIM_SHIFT); ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32), w); ++ } else { ++ /* set sbintvec bit for our flag number */ ++ OR_SBREG(si, &sb->sbintvec, (1 << sbflag)); ++ } ++ ++ if (PCI(si)) { ++ OR_REG(si->osh, &pciregs->sbtopci2, (SBTOPCI_PREF|SBTOPCI_BURST)); ++ if (si->sb.buscorerev >= 11) ++ OR_REG(si->osh, &pciregs->sbtopci2, SBTOPCI_RC_READMULTI); ++ if (si->sb.buscorerev < 5) { ++ SET_SBREG(si, &sb->sbimconfiglow, SBIMCL_RTO_MASK | SBIMCL_STO_MASK, ++ (0x3 << SBIMCL_RTO_SHIFT) | 0x2); ++ sb_commit(sbh); + } -+ bzero((char*)di->txp, size); + } + -+ /* allocate rx packet pointer vector */ -+ if (nrxd) { -+ size = nrxd * sizeof (void*); -+ if ((di->rxp = MALLOC(osh, size)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: out of rx memory, malloced %d bytes\n", di->name, MALLOCED(osh))); -+ goto fail; ++#ifdef PCIE_SUPPOER ++ /* PCIE workarounds */ ++ if (PCIE(si)) { ++ if ((si->sb.buscorerev == 0) || (si->sb.buscorerev == 1)) { ++ reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS, ++ PCIE_TLP_WORKAROUNDSREG); ++ reg_val |= 0x8; ++ sb_pcie_writereg((void *)sbh, (void *)PCIE_PCIEREGS, ++ PCIE_TLP_WORKAROUNDSREG, reg_val); + } -+ bzero((char*)di->rxp, size); -+ } + -+ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ -+ if (ntxd) { -+ if (!dma_alloc(di, DMA_TX)) -+ goto fail; -+ } ++ if (si->sb.buscorerev == 1) { ++ reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS, ++ PCIE_DLLP_LCREG); ++ reg_val |= (0x40); ++ sb_pcie_writereg(sbh, (void *)PCIE_PCIEREGS, PCIE_DLLP_LCREG, reg_val); ++ } + -+ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ -+ if (nrxd) { -+ if (!dma_alloc(di, DMA_RX)) -+ goto fail; ++ if (si->sb.buscorerev == 0) ++ sb_war30841(si); + } ++#endif + -+ if ((di->ddoffsetlow == SB_PCI_DMA) && (di->txdpa > SB_PCI_DMA_SZ) && !di->addrext) { -+ DMA_ERROR(("%s: dma_attach: txdpa 0x%lx: addrext not supported\n", di->name, di->txdpa)); -+ goto fail; -+ } -+ if ((di->ddoffsetlow == SB_PCI_DMA) && (di->rxdpa > SB_PCI_DMA_SZ) && !di->addrext) { -+ DMA_ERROR(("%s: dma_attach: rxdpa 0x%lx: addrext not supported\n", di->name, di->rxdpa)); -+ goto fail; -+ } ++ /* switch back to previous core */ ++ sb_setcoreidx(sbh, idx); ++} + -+ return ((void*)di); ++uint32 ++sb_base(uint32 admatch) ++{ ++ uint32 base; ++ uint type; + -+fail: -+ dma_detach((void*)di); -+ return (NULL); -+} ++ type = admatch & SBAM_TYPE_MASK; ++ ASSERT(type < 3); + ++ base = 0; + -+static bool -+dma_alloc(dma_info_t *di, uint direction) ++ if (type == 0) { ++ base = admatch & SBAM_BASE0_MASK; ++ } else if (type == 1) { ++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ ++ base = admatch & SBAM_BASE1_MASK; ++ } else if (type == 2) { ++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ ++ base = admatch & SBAM_BASE2_MASK; ++ } ++ ++ return (base); ++} ++ ++uint32 ++sb_size(uint32 admatch) +{ -+ if (DMA64_ENAB(di)) { -+ return dma64_alloc(di, direction); -+ } else { -+ return dma32_alloc(di, direction); ++ uint32 size; ++ uint type; ++ ++ type = admatch & SBAM_TYPE_MASK; ++ ASSERT(type < 3); ++ ++ size = 0; ++ ++ if (type == 0) { ++ size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1); ++ } else if (type == 1) { ++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ ++ size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1); ++ } else if (type == 2) { ++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ ++ size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1); + } ++ ++ return (size); +} + -+/* may be called with core in reset */ -+void -+dma_detach(dma_info_t *di) ++/* return the core-type instantiation # of the current core */ ++uint ++sb_coreunit(sb_t *sbh) +{ -+ if (di == NULL) -+ return; ++ sb_info_t *si; ++ uint idx; ++ uint coreid; ++ uint coreunit; ++ uint i; + -+ DMA_TRACE(("%s: dma_detach\n", di->name)); ++ si = SB_INFO(sbh); ++ coreunit = 0; + -+ /* shouldn't be here if descriptors are unreclaimed */ -+ ASSERT(di->txin == di->txout); -+ ASSERT(di->rxin == di->rxout); ++ idx = si->curidx; + -+ /* free dma descriptor rings */ -+ if (di->txd32) -+ DMA_FREE_CONSISTENT(di->osh, ((int8*)di->txd32 - di->txdalign), di->txdalloc, (di->txdpa - di->txdalign)); -+ if (di->rxd32) -+ DMA_FREE_CONSISTENT(di->osh, ((int8*)di->rxd32 - di->rxdalign), di->rxdalloc, (di->rxdpa - di->rxdalign)); ++ ASSERT(GOODREGS(si->curmap)); ++ coreid = sb_coreid(sbh); + -+ /* free packet pointer vectors */ -+ if (di->txp) -+ MFREE(di->osh, (void*)di->txp, (di->ntxd * sizeof (void*))); -+ if (di->rxp) -+ MFREE(di->osh, (void*)di->rxp, (di->nrxd * sizeof (void*))); ++ /* count the cores of our type */ ++ for (i = 0; i < idx; i++) ++ if (si->coreid[i] == coreid) ++ coreunit++; + -+ /* free our private info structure */ -+ MFREE(di->osh, (void*)di, sizeof (dma_info_t)); ++ return (coreunit); +} + -+/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ -+static bool -+dma_isaddrext(dma_info_t *di) ++static INLINE uint32 ++factor6(uint32 x) +{ -+ uint32 w; -+ -+ if (DMA64_ENAB(di)) { -+ OR_REG(&di->d64txregs->control, D64_XC_AE); -+ w = R_REG(&di->d32txregs->control); -+ AND_REG(&di->d32txregs->control, ~D64_XC_AE); -+ return ((w & XC_AE) == D64_XC_AE); -+ } else { -+ OR_REG(&di->d32txregs->control, XC_AE); -+ w = R_REG(&di->d32txregs->control); -+ AND_REG(&di->d32txregs->control, ~XC_AE); -+ return ((w & XC_AE) == XC_AE); ++ switch (x) { ++ case CC_F6_2: return 2; ++ case CC_F6_3: return 3; ++ case CC_F6_4: return 4; ++ case CC_F6_5: return 5; ++ case CC_F6_6: return 6; ++ case CC_F6_7: return 7; ++ default: return 0; + } +} + -+void -+dma_txreset(dma_info_t *di) ++/* calculate the speed the SB would run at given a set of clockcontrol values */ ++uint32 ++sb_clock_rate(uint32 pll_type, uint32 n, uint32 m) +{ -+ DMA_TRACE(("%s: dma_txreset\n", di->name)); ++ uint32 n1, n2, clock, m1, m2, m3, mc; + -+ if (DMA64_ENAB(di)) -+ dma64_txreset(di); -+ else -+ dma32_txreset(di); -+} ++ n1 = n & CN_N1_MASK; ++ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; + -+void -+dma_rxreset(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_rxreset\n", di->name)); ++ if (pll_type == PLL_TYPE6) { ++ if (m & CC_T6_MMASK) ++ return CC_T6_M1; ++ else ++ return CC_T6_M0; ++ } else if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ n1 = factor6(n1); ++ n2 += CC_F5_BIAS; ++ } else if (pll_type == PLL_TYPE2) { ++ n1 += CC_T2_BIAS; ++ n2 += CC_T2_BIAS; ++ ASSERT((n1 >= 2) && (n1 <= 7)); ++ ASSERT((n2 >= 5) && (n2 <= 23)); ++ } else if (pll_type == PLL_TYPE5) { ++ return (100000000); ++ } else ++ ASSERT(0); ++ /* PLL types 3 and 7 use BASE2 (25Mhz) */ ++ if ((pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE7)) { ++ clock = CC_CLOCK_BASE2 * n1 * n2; ++ } else ++ clock = CC_CLOCK_BASE1 * n1 * n2; + -+ if (DMA64_ENAB(di)) -+ dma64_rxreset(di); -+ else -+ dma32_rxreset(di); -+} ++ if (clock == 0) ++ return 0; ++ ++ m1 = m & CC_M1_MASK; ++ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; ++ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; ++ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; ++ ++ if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ m1 = factor6(m1); ++ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) ++ m2 += CC_F5_BIAS; ++ else ++ m2 = factor6(m2); ++ m3 = factor6(m3); + -+/* initialize descriptor table base address */ -+static void -+dma_ddtable_init(dma_info_t *di, uint direction, ulong pa) -+{ -+ if (DMA64_ENAB(di)) { -+ if (direction == DMA_TX) { -+ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); -+ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); -+ } else { -+ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); -+ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); ++ switch (mc) { ++ case CC_MC_BYPASS: return (clock); ++ case CC_MC_M1: return (clock / m1); ++ case CC_MC_M1M2: return (clock / (m1 * m2)); ++ case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); ++ case CC_MC_M1M3: return (clock / (m1 * m3)); ++ default: return (0); + } + } else { -+ uint32 offset = di->ddoffsetlow; -+ if ((offset != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { -+ if (direction == DMA_TX) -+ W_REG(&di->d32txregs->addr, (pa + offset)); -+ else -+ W_REG(&di->d32rxregs->addr, (pa + offset)); -+ } else { -+ /* dma32 address extension */ -+ uint32 ae; -+ ASSERT(di->addrext); -+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; -+ -+ if (direction == DMA_TX) { -+ W_REG(&di->d32txregs->addr, ((pa & ~PCI32ADDR_HIGH) + offset)); -+ SET_REG(&di->d32txregs->control, XC_AE, (ae << XC_AE_SHIFT)); -+ } else { -+ W_REG(&di->d32rxregs->addr, ((pa & ~PCI32ADDR_HIGH) + offset)); -+ SET_REG(&di->d32rxregs->control, RC_AE, (ae << RC_AE_SHIFT)); -+ } -+ } -+ } -+} ++ ASSERT(pll_type == PLL_TYPE2); + -+/* init the tx or rx descriptor */ -+static INLINE void -+dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, ulong pa, uint outidx, uint32 *ctrl) -+{ -+ uint offset = di->dataoffsetlow; ++ m1 += CC_T2_BIAS; ++ m2 += CC_T2M2_BIAS; ++ m3 += CC_T2_BIAS; ++ ASSERT((m1 >= 2) && (m1 <= 7)); ++ ASSERT((m2 >= 3) && (m2 <= 10)); ++ ASSERT((m3 >= 2) && (m3 <= 7)); + -+ if ((offset != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { -+ W_SM(&ddring[outidx].addr, BUS_SWAP32(pa + offset)); -+ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*ctrl)); -+ } else { -+ /* address extension */ -+ uint32 ae; -+ ASSERT(di->addrext); -+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ if ((mc & CC_T2MC_M1BYP) == 0) ++ clock /= m1; ++ if ((mc & CC_T2MC_M2BYP) == 0) ++ clock /= m2; ++ if ((mc & CC_T2MC_M3BYP) == 0) ++ clock /= m3; + -+ *ctrl |= (ae << CTRL_AE_SHIFT); -+ W_SM(&ddring[outidx].addr, BUS_SWAP32((pa & ~PCI32ADDR_HIGH) + offset)); -+ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*ctrl)); ++ return (clock); + } +} + -+/* init the tx or rx descriptor */ -+static INLINE void -+dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, ulong pa, uint outidx, uint32 *flags, uint32 bufcount) ++/* returns the current speed the SB is running at */ ++uint32 ++sb_clock(sb_t *sbh) +{ -+ uint32 bufaddr_low = pa + di->dataoffsetlow; -+ uint32 bufaddr_high = 0 + di->dataoffsethigh; -+ -+ uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; -+ -+ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(bufaddr_low)); -+ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(bufaddr_high)); -+ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); -+ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); -+} ++ sb_info_t *si; ++ extifregs_t *eir; ++ chipcregs_t *cc; ++ uint32 n, m; ++ uint idx; ++ uint32 pll_type, rate; ++ uint intr_val = 0; + -+void -+dma_txinit(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ si = SB_INFO(sbh); ++ idx = si->curidx; ++ pll_type = PLL_TYPE1; + -+ di->txin = di->txout = 0; -+ di->txavail = di->ntxd - 1; ++ INTR_OFF(si, intr_val); + -+ /* clear tx descriptor ring */ -+ if (DMA64_ENAB(di)) { -+ BZERO_SM((void*)di->txd64, (di->ntxd * sizeof (dma64dd_t))); -+ W_REG(&di->d64txregs->control, XC_XE); -+ dma_ddtable_init(di, DMA_TX, di->txdpa); ++ /* switch to extif or chipc core */ ++ if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) { ++ n = R_REG(si->osh, &eir->clockcontrol_n); ++ m = R_REG(si->osh, &eir->clockcontrol_sb); ++ } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { ++ pll_type = R_REG(si->osh, &cc->capabilities) & CAP_PLL_MASK; ++ if (pll_type == PLL_NONE) { ++ INTR_RESTORE(si, intr_val); ++ return 80000000; ++ } ++ n = R_REG(si->osh, &cc->clockcontrol_n); ++ if (pll_type == PLL_TYPE6) ++ m = R_REG(si->osh, &cc->clockcontrol_m3); ++ else if ((pll_type == PLL_TYPE3) && !(BCMINIT(sb_chip)(sbh) == 0x5365)) ++ m = R_REG(si->osh, &cc->clockcontrol_m2); ++ else ++ m = R_REG(si->osh, &cc->clockcontrol_sb); + } else { -+ BZERO_SM((void*)di->txd32, (di->ntxd * sizeof (dma32dd_t))); -+ W_REG(&di->d32txregs->control, XC_XE); -+ dma_ddtable_init(di, DMA_TX, di->txdpa); ++ INTR_RESTORE(si, intr_val); ++ return 0; + } -+} + -+bool -+dma_txenabled(dma_info_t *di) -+{ -+ uint32 xc; -+ -+ /* If the chip is dead, it is not enabled :-) */ -+ if (DMA64_ENAB(di)) { -+ xc = R_REG(&di->d64txregs->control); -+ return ((xc != 0xffffffff) && (xc & D64_XC_XE)); -+ } else { -+ xc = R_REG(&di->d32txregs->control); -+ return ((xc != 0xffffffff) && (xc & XC_XE)); ++ /* calculate rate */ ++ if (BCMINIT(sb_chip)(sbh) == 0x5365) ++ rate = 100000000; ++ else { ++ rate = sb_clock_rate(pll_type, n, m); ++ ++ if (pll_type == PLL_TYPE3) ++ rate = rate / 2; + } -+} + -+void -+dma_txsuspend(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); -+ if (DMA64_ENAB(di)) -+ OR_REG(&di->d64txregs->control, D64_XC_SE); -+ else -+ OR_REG(&di->d32txregs->control, XC_SE); -+} ++ /* switch back to previous core */ ++ sb_setcoreidx(sbh, idx); + -+void -+dma_txresume(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txresume\n", di->name)); -+ if (DMA64_ENAB(di)) -+ AND_REG(&di->d64txregs->control, ~D64_XC_SE); -+ else -+ AND_REG(&di->d32txregs->control, ~XC_SE); -+} ++ INTR_RESTORE(si, intr_val); + -+bool -+dma_txsuspendedidle(dma_info_t *di) -+{ -+ if (DMA64_ENAB(di)) -+ return dma64_txsuspendedidle(di); -+ else -+ return dma32_txsuspendedidle(di); ++ return rate; +} + -+bool -+dma_txsuspended(dma_info_t *di) ++/* change logical "focus" to the gpio core for optimized access */ ++void* ++sb_gpiosetcore(sb_t *sbh) +{ -+ if (DMA64_ENAB(di)) -+ return ((R_REG(&di->d64txregs->control) & D64_XC_SE) == D64_XC_SE); -+ else -+ return ((R_REG(&di->d32txregs->control) & XC_SE) == XC_SE); -+} ++ sb_info_t *si; + -+bool -+dma_txstopped(dma_info_t *di) -+{ -+ if (DMA64_ENAB(di)) -+ return ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_STOPPED); -+ else -+ return ((R_REG(&di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED); -+} ++ si = SB_INFO(sbh); + -+bool -+dma_rxstopped(dma_info_t *di) -+{ -+ if (DMA64_ENAB(di)) -+ return ((R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK) == D64_RS0_RS_STOPPED); -+ else -+ return ((R_REG(&di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED); ++ return (sb_setcoreidx(sbh, si->gpioidx)); +} + -+void -+dma_fifoloopbackenable(dma_info_t *di) ++/* mask&set gpiocontrol bits */ ++uint32 ++sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +{ -+ DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name)); -+ if (DMA64_ENAB(di)) -+ OR_REG(&di->d64txregs->control, D64_XC_LE); -+ else -+ OR_REG(&di->d32txregs->control, XC_LE); -+} ++ sb_info_t *si; ++ uint regoff; + -+void -+dma_rxinit(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_rxinit\n", di->name)); ++ si = SB_INFO(sbh); ++ regoff = 0; + -+ di->rxin = di->rxout = 0; ++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ + -+ /* clear rx descriptor ring */ -+ if (DMA64_ENAB(di)) { -+ BZERO_SM((void*)di->rxd64, (di->nrxd * sizeof (dma64dd_t))); -+ dma_rxenable(di); -+ dma_ddtable_init(di, DMA_RX, di->rxdpa); -+ } else { -+ BZERO_SM((void*)di->rxd32, (di->nrxd * sizeof (dma32dd_t))); -+ dma_rxenable(di); -+ dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ /* gpios could be shared on router platforms */ ++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { ++ mask = priority ? (sb_gpioreservation & mask) : ++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); ++ val &= mask; + } -+} + -+void -+dma_rxenable(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_rxenable\n", di->name)); -+ if (DMA64_ENAB(di)) -+ W_REG(&di->d64rxregs->control, ((di->rxoffset << D64_RC_RO_SHIFT) | D64_RC_RE)); -+ else -+ W_REG(&di->d32rxregs->control, ((di->rxoffset << RC_RO_SHIFT) | RC_RE)); -+} ++ switch (si->gpioid) { ++ case SB_CC: ++ regoff = OFFSETOF(chipcregs_t, gpiocontrol); ++ break; + -+bool -+dma_rxenabled(dma_info_t *di) -+{ -+ uint32 rc; ++ case SB_PCI: ++ regoff = OFFSETOF(sbpciregs_t, gpiocontrol); ++ break; + -+ if (DMA64_ENAB(di)) { -+ rc = R_REG(&di->d64rxregs->control); -+ return ((rc != 0xffffffff) && (rc & D64_RC_RE)); -+ } else { -+ rc = R_REG(&di->d32rxregs->control); -+ return ((rc != 0xffffffff) && (rc & RC_RE)); ++ case SB_EXTIF: ++ return (0); + } -+} + -+ -+/* !! tx entry routine */ -+int -+dma_txfast(dma_info_t *di, void *p0, uint32 coreflags) -+{ -+ if (DMA64_ENAB(di)) { -+ return dma64_txfast(di, p0, coreflags); -+ } else { -+ return dma32_txfast(di, p0, coreflags); -+ } ++ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); +} + -+/* !! rx entry routine, returns a pointer to the next frame received, or NULL if there are no more */ -+void* -+dma_rx(dma_info_t *di) ++/* mask&set gpio output enable bits */ ++uint32 ++sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +{ -+ void *p; -+ uint len; -+ int skiplen = 0; ++ sb_info_t *si; ++ uint regoff; + -+ while ((p = dma_getnextrxp(di, FALSE))) { -+ /* skip giant packets which span multiple rx descriptors */ -+ if (skiplen > 0) { -+ skiplen -= di->rxbufsize; -+ if (skiplen < 0) -+ skiplen = 0; -+ PKTFREE(di->osh, p, FALSE); -+ continue; -+ } ++ si = SB_INFO(sbh); ++ regoff = 0; + -+ len = ltoh16(*(uint16*)(PKTDATA(di->osh, p))); -+ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); ++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ + -+ /* bad frame length check */ -+ if (len > (di->rxbufsize - di->rxoffset)) { -+ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len)); -+ if (len > 0) -+ skiplen = len - (di->rxbufsize - di->rxoffset); -+ PKTFREE(di->osh, p, FALSE); -+ di->hnddma.rxgiants++; -+ continue; -+ } ++ /* gpios could be shared on router platforms */ ++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { ++ mask = priority ? (sb_gpioreservation & mask) : ++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); ++ val &= mask; ++ } + -+ /* set actual length */ -+ PKTSETLEN(di->osh, p, (di->rxoffset + len)); ++ switch (si->gpioid) { ++ case SB_CC: ++ regoff = OFFSETOF(chipcregs_t, gpioouten); ++ break; ++ ++ case SB_PCI: ++ regoff = OFFSETOF(sbpciregs_t, gpioouten); ++ break; + ++ case SB_EXTIF: ++ regoff = OFFSETOF(extifregs_t, gpio[0].outen); + break; + } + -+ return (p); ++ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); +} + -+/* post receive buffers */ -+void -+dma_rxfill(dma_info_t *di) ++/* mask&set gpio output bits */ ++uint32 ++sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +{ -+ void *p; -+ uint rxin, rxout; -+ uint32 ctrl; -+ uint n; -+ uint i; -+ uint32 pa; -+ uint rxbufsize; ++ sb_info_t *si; ++ uint regoff; + -+ /* -+ * Determine how many receive buffers we're lacking -+ * from the full complement, allocate, initialize, -+ * and post them, then update the chip rx lastdscr. -+ */ ++ si = SB_INFO(sbh); ++ regoff = 0; + -+ rxin = di->rxin; -+ rxout = di->rxout; -+ rxbufsize = di->rxbufsize; ++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ + -+ n = di->nrxpost - NRXDACTIVE(rxin, rxout); ++ /* gpios could be shared on router platforms */ ++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { ++ mask = priority ? (sb_gpioreservation & mask) : ++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); ++ val &= mask; ++ } + -+ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); ++ switch (si->gpioid) { ++ case SB_CC: ++ regoff = OFFSETOF(chipcregs_t, gpioout); ++ break; + -+ for (i = 0; i < n; i++) { -+ if ((p = PKTGET(di->osh, rxbufsize, FALSE)) == NULL) { -+ DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", di->name)); -+ di->hnddma.rxnobuf++; -+ break; -+ } ++ case SB_PCI: ++ regoff = OFFSETOF(sbpciregs_t, gpioout); ++ break; + -+ /* Do a cached write instead of uncached write since DMA_MAP -+ * will flush the cache. */ -+ *(uint32*)(PKTDATA(di->osh, p)) = 0; ++ case SB_EXTIF: ++ regoff = OFFSETOF(extifregs_t, gpio[0].out); ++ break; ++ } + -+ pa = (uint32) DMA_MAP(di->osh, PKTDATA(di->osh, p), rxbufsize, DMA_RX, p); -+ ASSERT(ISALIGNED(pa, 4)); ++ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); ++} + -+ /* save the free packet pointer */ -+ ASSERT(di->rxp[rxout] == NULL); -+ di->rxp[rxout] = p; ++/* reserve one gpio */ ++uint32 ++sb_gpioreserve(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) ++{ ++ sb_info_t *si; + -+ if (DMA64_ENAB(di)) { -+ /* prep the descriptor control value */ -+ if (rxout == (di->nrxd - 1)) -+ ctrl = CTRL_EOT; ++ si = SB_INFO(sbh); + -+ dma64_dd_upd(di, di->rxd64, pa, rxout, &ctrl, rxbufsize); -+ } else { -+ /* prep the descriptor control value */ -+ ctrl = rxbufsize; -+ if (rxout == (di->nrxd - 1)) -+ ctrl |= CTRL_EOT; -+ dma32_dd_upd(di, di->rxd32, pa, rxout, &ctrl); -+ } ++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ + -+ rxout = NEXTRXD(rxout); ++ /* only cores on SB_BUS share GPIO's and only applcation users need to ++ * reserve/release GPIO ++ */ ++ if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { ++ ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority)); ++ return -1; ++ } ++ /* make sure only one bit is set */ ++ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { ++ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); ++ return -1; + } + -+ di->rxout = rxout; ++ /* already reserved */ ++ if (sb_gpioreservation & gpio_bitmask) ++ return -1; ++ /* set reservation */ ++ sb_gpioreservation |= gpio_bitmask; + -+ /* update the chip lastdscr pointer */ -+ if (DMA64_ENAB(di)) { -+ W_REG(&di->d64rxregs->ptr, I2B(rxout, dma64dd_t)); -+ } else { -+ W_REG(&di->d32rxregs->ptr, I2B(rxout, dma32dd_t)); -+ } ++ return sb_gpioreservation; +} + -+void -+dma_txreclaim(dma_info_t *di, bool forceall) ++/* release one gpio */ ++/* ++ * releasing the gpio doesn't change the current value on the GPIO last write value ++ * persists till some one overwrites it ++*/ ++ ++uint32 ++sb_gpiorelease(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) +{ -+ void *p; ++ sb_info_t *si; + -+ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); ++ si = SB_INFO(sbh); + -+ while ((p = dma_getnexttxp(di, forceall))) -+ PKTFREE(di->osh, p, TRUE); -+} ++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ + -+/* -+ * Reclaim next completed txd (txds if using chained buffers) and -+ * return associated packet. -+ * If 'force' is true, reclaim txd(s) and return associated packet -+ * regardless of the value of the hardware "curr" pointer. -+ */ -+void* -+dma_getnexttxp(dma_info_t *di, bool forceall) -+{ -+ if (DMA64_ENAB(di)) { -+ return dma64_getnexttxp(di, forceall); -+ } else { -+ return dma32_getnexttxp(di, forceall); ++ /* only cores on SB_BUS share GPIO's and only applcation users need to ++ * reserve/release GPIO ++ */ ++ if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { ++ ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority)); ++ return -1; + } -+} -+ -+/* like getnexttxp but no reclaim */ -+void* -+dma_peeknexttxp(dma_info_t *di) -+{ -+ uint end, i; -+ -+ if (DMA64_ENAB(di)) { -+ end = B2I(R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK, dma64dd_t); -+ } else { -+ end = B2I(R_REG(&di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ /* make sure only one bit is set */ ++ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { ++ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); ++ return -1; + } + -+ for (i = di->txin; i != end; i = NEXTTXD(i)) -+ if (di->txp[i]) -+ return (di->txp[i]); ++ /* already released */ ++ if (!(sb_gpioreservation & gpio_bitmask)) ++ return -1; + -+ return (NULL); -+} ++ /* clear reservation */ ++ sb_gpioreservation &= ~gpio_bitmask; + -+/* -+ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). -+ */ -+void -+dma_txrotate(di_t *di) -+{ -+ if (DMA64_ENAB(di)) { -+ dma64_txrotate(di); -+ } else { -+ dma32_txrotate(di); -+ } ++ return sb_gpioreservation; +} + -+void -+dma_rxreclaim(dma_info_t *di) ++/* return the current gpioin register value */ ++uint32 ++sb_gpioin(sb_t *sbh) +{ -+ void *p; ++ sb_info_t *si; ++ uint regoff; + -+ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); ++ si = SB_INFO(sbh); ++ regoff = 0; + -+ while ((p = dma_getnextrxp(di, TRUE))) -+ PKTFREE(di->osh, p, FALSE); -+} ++ switch (si->gpioid) { ++ case SB_CC: ++ regoff = OFFSETOF(chipcregs_t, gpioin); ++ break; + -+void * -+dma_getnextrxp(dma_info_t *di, bool forceall) -+{ -+ if (DMA64_ENAB(di)) { -+ return dma64_getnextrxp(di, forceall); -+ } else { -+ return dma32_getnextrxp(di, forceall); -+ } -+} ++ case SB_PCI: ++ regoff = OFFSETOF(sbpciregs_t, gpioin); ++ break; + -+uintptr -+dma_getvar(dma_info_t *di, char *name) -+{ -+ if (!strcmp(name, "&txavail")) -+ return ((uintptr) &di->txavail); -+ else { -+ ASSERT(0); ++ case SB_EXTIF: ++ regoff = OFFSETOF(extifregs_t, gpioin); ++ break; + } -+ return (0); -+} + -+void -+dma_txblock(dma_info_t *di) -+{ -+ di->txavail = 0; ++ return (sb_corereg(si, si->gpioidx, regoff, 0, 0)); +} + -+void -+dma_txunblock(dma_info_t *di) ++/* mask&set gpio interrupt polarity bits */ ++uint32 ++sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +{ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+} ++ sb_info_t *si; ++ uint regoff; + -+uint -+dma_txactive(dma_info_t *di) -+{ -+ return (NTXDACTIVE(di->txin, di->txout)); -+} -+ -+void -+dma_rxpiomode(dma32regs_t *regs) -+{ -+ W_REG(®s->control, RC_FM); -+} ++ si = SB_INFO(sbh); ++ regoff = 0; + -+void -+dma_txpioloopback(dma32regs_t *regs) -+{ -+ OR_REG(®s->control, XC_LE); -+} ++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ ++ /* gpios could be shared on router platforms */ ++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { ++ mask = priority ? (sb_gpioreservation & mask) : ++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); ++ val &= mask; ++ } ++ ++ switch (si->gpioid) { ++ case SB_CC: ++ regoff = OFFSETOF(chipcregs_t, gpiointpolarity); ++ break; + ++ case SB_PCI: ++ /* pci gpio implementation does not support interrupt polarity */ ++ ASSERT(0); ++ break; + ++ case SB_EXTIF: ++ regoff = OFFSETOF(extifregs_t, gpiointpolarity); ++ break; ++ } + ++ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); ++} + -+/*** 32 bits DMA non-inline functions ***/ -+static bool -+dma32_alloc(dma_info_t *di, uint direction) ++/* mask&set gpio interrupt mask bits */ ++uint32 ++sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +{ -+ uint size; -+ uint ddlen; -+ void *va; ++ sb_info_t *si; ++ uint regoff; + -+ ddlen = sizeof (dma32dd_t); ++ si = SB_INFO(sbh); ++ regoff = 0; + -+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ + -+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, D32RINGALIGN)) -+ size += D32RINGALIGN; ++ /* gpios could be shared on router platforms */ ++ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { ++ mask = priority ? (sb_gpioreservation & mask) : ++ ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); ++ val &= mask; ++ } + ++ switch (si->gpioid) { ++ case SB_CC: ++ regoff = OFFSETOF(chipcregs_t, gpiointmask); ++ break; + -+ if (direction == DMA_TX) { -+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->txdpa)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name)); -+ return FALSE; -+ } ++ case SB_PCI: ++ /* pci gpio implementation does not support interrupt mask */ ++ ASSERT(0); ++ break; + -+ di->txd32 = (dma32dd_t*) ROUNDUP((uintptr)va, D32RINGALIGN); -+ di->txdalign = (uint)((int8*)di->txd32 - (int8*)va); -+ di->txdpa += di->txdalign; -+ di->txdalloc = size; -+ ASSERT(ISALIGNED((uintptr)di->txd32, D32RINGALIGN)); -+ } else { -+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->rxdpa)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name)); -+ return FALSE; -+ } -+ di->rxd32 = (dma32dd_t*) ROUNDUP((uintptr)va, D32RINGALIGN); -+ di->rxdalign = (uint)((int8*)di->rxd32 - (int8*)va); -+ di->rxdpa += di->rxdalign; -+ di->rxdalloc = size; -+ ASSERT(ISALIGNED((uintptr)di->rxd32, D32RINGALIGN)); ++ case SB_EXTIF: ++ regoff = OFFSETOF(extifregs_t, gpiointmask); ++ break; + } + -+ return TRUE; ++ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); +} + -+static void -+dma32_txreset(dma_info_t *di) ++/* assign the gpio to an led */ ++uint32 ++sb_gpioled(sb_t *sbh, uint32 mask, uint32 val) +{ -+ uint32 status; ++ sb_info_t *si; + -+ /* suspend tx DMA first */ -+ W_REG(&di->d32txregs->control, XC_SE); -+ SPINWAIT((status = (R_REG(&di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED && -+ status != XS_XS_IDLE && -+ status != XS_XS_STOPPED, -+ 10000); -+ -+ W_REG(&di->d32txregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED, -+ 10000); -+ -+ if (status != XS_XS_DISABLED) { -+ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); -+ } ++ si = SB_INFO(sbh); ++ if (si->sb.ccrev < 16) ++ return -1; ++ ++ /* gpio led powersave reg */ ++ return (sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); ++} ++ ++/* mask & set gpio timer val */ ++uint32 ++sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 gpiotimerval) ++{ ++ sb_info_t *si; ++ si = SB_INFO(sbh); ++ ++ if (si->sb.ccrev < 16) ++ return -1; + -+ /* wait for the last transaction to complete */ -+ OSL_DELAY(300); ++ return (sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); +} + -+static void -+dma32_rxreset(dma_info_t *di) ++ ++/* return the slow clock source - LPO, XTAL, or PCI */ ++static uint ++sb_slowclk_src(sb_info_t *si) +{ -+ uint32 status; ++ chipcregs_t *cc; + -+ W_REG(&di->d32rxregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED, -+ 10000); + -+ if (status != RS_RS_DISABLED) { -+ DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name)); -+ } ++ ASSERT(sb_coreid(&si->sb) == SB_CC); ++ ++ if (si->sb.ccrev < 6) { ++ if ((BUSTYPE(si->sb.bustype) == PCI_BUS) && ++ (OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32)) & ++ PCI_CFG_GPIO_SCS)) ++ return (SCC_SS_PCI); ++ else ++ return (SCC_SS_XTAL); ++ } else if (si->sb.ccrev < 10) { ++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); ++ return (R_REG(si->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); ++ } else /* Insta-clock */ ++ return (SCC_SS_XTAL); +} + -+static bool -+dma32_txsuspendedidle(dma_info_t *di) ++/* return the ILP (slowclock) min or max frequency */ ++static uint ++sb_slowclk_freq(sb_info_t *si, bool max) +{ -+ if (!(R_REG(&di->d32txregs->control) & XC_SE)) -+ return 0; -+ -+ if ((R_REG(&di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) -+ return 0; ++ chipcregs_t *cc; ++ uint32 slowclk; ++ uint div; + -+ OSL_DELAY(2); -+ return ((R_REG(&di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); -+} + -+/* -+ * supports full 32bit dma engine buffer addressing so -+ * dma buffers can cross 4 Kbyte page boundaries. -+ */ -+static int -+dma32_txfast(dma_info_t *di, void *p0, uint32 coreflags) -+{ -+ void *p, *next; -+ uchar *data; -+ uint len; -+ uint txout; -+ uint32 ctrl; -+ uint32 pa; ++ ASSERT(sb_coreid(&si->sb) == SB_CC); + -+ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); + -+ txout = di->txout; -+ ctrl = 0; ++ /* shouldn't be here unless we've established the chip has dynamic clk control */ ++ ASSERT(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL); + -+ /* -+ * Walk the chain of packet buffers -+ * allocating and initializing transmit descriptor entries. -+ */ -+ for (p = p0; p; p = next) { -+ data = PKTDATA(di->osh, p); -+ len = PKTLEN(di->osh, p); -+ next = PKTNEXT(di->osh, p); ++ slowclk = sb_slowclk_src(si); ++ if (si->sb.ccrev < 6) { ++ if (slowclk == SCC_SS_PCI) ++ return (max? (PCIMAXFREQ/64) : (PCIMINFREQ/64)); ++ else ++ return (max? (XTALMAXFREQ/32) : (XTALMINFREQ/32)); ++ } else if (si->sb.ccrev < 10) { ++ div = 4 * (((R_REG(si->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); ++ if (slowclk == SCC_SS_LPO) ++ return (max? LPOMAXFREQ : LPOMINFREQ); ++ else if (slowclk == SCC_SS_XTAL) ++ return (max? (XTALMAXFREQ/div) : (XTALMINFREQ/div)); ++ else if (slowclk == SCC_SS_PCI) ++ return (max? (PCIMAXFREQ/div) : (PCIMINFREQ/div)); ++ else ++ ASSERT(0); ++ } else { ++ /* Chipc rev 10 is InstaClock */ ++ div = R_REG(si->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; ++ div = 4 * (div + 1); ++ return (max ? XTALMAXFREQ : (XTALMINFREQ/div)); ++ } ++ return (0); ++} + -+ /* return nonzero if out of tx descriptors */ -+ if (NEXTTXD(txout) == di->txin) -+ goto outoftxd; ++static void ++BCMINITFN(sb_clkctl_setdelay)(sb_info_t *si, void *chipcregs) ++{ ++ chipcregs_t * cc; ++ uint slowmaxfreq, pll_delay, slowclk; ++ uint pll_on_delay, fref_sel_delay; + -+ if (len == 0) -+ continue; ++ pll_delay = PLL_DELAY; + -+ /* get physical address of buffer start */ -+ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); ++ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay ++ * since the xtal will also be powered down by dynamic clk control logic. ++ */ + -+ /* build the descriptor control value */ -+ ctrl = len & CTRL_BC_MASK; ++ slowclk = sb_slowclk_src(si); ++ if (slowclk != SCC_SS_XTAL) ++ pll_delay += XTAL_ON_DELAY; + -+ ctrl |= coreflags; -+ -+ if (p == p0) -+ ctrl |= CTRL_SOF; -+ if (next == NULL) -+ ctrl |= (CTRL_IOC | CTRL_EOF); -+ if (txout == (di->ntxd - 1)) -+ ctrl |= CTRL_EOT; ++ /* Starting with 4318 it is ILP that is used for the delays */ ++ slowmaxfreq = sb_slowclk_freq(si, (si->sb.ccrev >= 10) ? FALSE : TRUE); + -+ if (DMA64_ENAB(di)) { -+ dma64_dd_upd(di, di->txd64, pa, txout, &ctrl, len); -+ } else { -+ dma32_dd_upd(di, di->txd32, pa, txout, &ctrl); -+ } ++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; ++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; + -+ ASSERT(di->txp[txout] == NULL); ++ cc = (chipcregs_t *)chipcregs; ++ W_REG(si->osh, &cc->pll_on_delay, pll_on_delay); ++ W_REG(si->osh, &cc->fref_sel_delay, fref_sel_delay); ++} + -+ txout = NEXTTXD(txout); -+ } ++/* initialize power control delay registers */ ++void ++BCMINITFN(sb_clkctl_init)(sb_t *sbh) ++{ ++ sb_info_t *si; ++ uint origidx; ++ chipcregs_t *cc; + -+ /* if last txd eof not set, fix it */ -+ if (!(ctrl & CTRL_EOF)) -+ W_SM(&di->txd32[PREVTXD(txout)].ctrl, BUS_SWAP32(ctrl | CTRL_IOC | CTRL_EOF)); ++ si = SB_INFO(sbh); + -+ /* save the packet */ -+ di->txp[PREVTXD(txout)] = p0; ++ origidx = si->curidx; + -+ /* bump the tx descriptor index */ -+ di->txout = txout; ++ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) ++ return; + -+ /* kick the chip */ -+ if (DMA64_ENAB(di)) { -+ W_REG(&di->d64txregs->ptr, I2B(txout, dma64dd_t)); -+ } else { -+ W_REG(&di->d32txregs->ptr, I2B(txout, dma32dd_t)); -+ } ++ if ((si->sb.chip == BCM4321_CHIP_ID) && (si->sb.chiprev < 2)) ++ W_REG(si->osh, &cc->chipcontrol, ++ (si->sb.chiprev == 0) ? CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT); + -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ if (!(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL)) ++ goto done; + -+ return (0); ++ /* set all Instaclk chip ILP to 1 MHz */ ++ else if (si->sb.ccrev >= 10) ++ SET_REG(si->osh, &cc->system_clk_ctl, SYCC_CD_MASK, ++ (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); + -+ outoftxd: -+ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); -+ PKTFREE(di->osh, p0, TRUE); -+ di->txavail = 0; -+ di->hnddma.txnobuf++; -+ return (-1); ++ sb_clkctl_setdelay(si, (void *)cc); ++ ++done: ++ sb_setcoreidx(sbh, origidx); +} + -+static void* -+dma32_getnexttxp(dma_info_t *di, bool forceall) ++/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */ ++uint16 ++sb_clkctl_fast_pwrup_delay(sb_t *sbh) +{ -+ uint start, end, i; -+ void *txp; ++ sb_info_t *si; ++ uint origidx; ++ chipcregs_t *cc; ++ uint slowminfreq; ++ uint16 fpdelay; ++ uint intr_val = 0; + -+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); ++ si = SB_INFO(sbh); ++ fpdelay = 0; ++ origidx = si->curidx; + -+ txp = NULL; ++ INTR_OFF(si, intr_val); + -+ start = di->txin; -+ if (forceall) -+ end = di->txout; -+ else -+ end = B2I(R_REG(&di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) ++ goto done; + -+ if ((start == 0) && (end > di->txout)) -+ goto bogus; ++ if (!(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL)) ++ goto done; + -+ for (i = start; i != end && !txp; i = NEXTTXD(i)) { -+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->txd32[i].addr)) - di->dataoffsetlow), -+ (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) & CTRL_BC_MASK), DMA_TX, di->txp[i]); ++ slowminfreq = sb_slowclk_freq(si, FALSE); ++ fpdelay = (((R_REG(si->osh, &cc->pll_on_delay) + 2) * 1000000) + ++ (slowminfreq - 1)) / slowminfreq; + -+ W_SM(&di->txd32[i].addr, 0xdeadbeef); -+ txp = di->txp[i]; -+ di->txp[i] = NULL; -+ } ++done: ++ sb_setcoreidx(sbh, origidx); ++ INTR_RESTORE(si, intr_val); ++ return (fpdelay); ++} + -+ di->txin = i; ++/* turn primary xtal and/or pll off/on */ ++int ++sb_clkctl_xtal(sb_t *sbh, uint what, bool on) ++{ ++ sb_info_t *si; ++ uint32 in, out, outen; + -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ si = SB_INFO(sbh); + -+ return (txp); ++ switch (BUSTYPE(si->sb.bustype)) { + -+bogus: -+/* -+ DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", -+ start, end, di->txout, forceall)); -+*/ -+ return (NULL); -+} + -+static void * -+dma32_getnextrxp(dma_info_t *di, bool forceall) -+{ -+ uint i; -+ void *rxp; ++ case PCMCIA_BUS: ++ return (0); + -+ /* if forcing, dma engine must be disabled */ -+ ASSERT(!forceall || !dma_rxenabled(di)); + -+ i = di->rxin; ++ case PCI_BUS: + -+ /* return if no packets posted */ -+ if (i == di->rxout) -+ return (NULL); ++ /* pcie core doesn't have any mapping to control the xtal pu */ ++ if (PCIE(si)) ++ return -1; + -+ /* ignore curr if forceall */ -+ if (!forceall && (i == B2I(R_REG(&di->d32rxregs->status) & RS_CD_MASK, dma32dd_t))) -+ return (NULL); ++ in = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_IN, sizeof(uint32)); ++ out = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32)); ++ outen = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof(uint32)); + -+ /* get the packet pointer that corresponds to the rx descriptor */ -+ rxp = di->rxp[i]; -+ ASSERT(rxp); -+ di->rxp[i] = NULL; ++ /* ++ * Avoid glitching the clock if GPRS is already using it. ++ * We can't actually read the state of the PLLPD so we infer it ++ * by the value of XTAL_PU which *is* readable via gpioin. ++ */ ++ if (on && (in & PCI_CFG_GPIO_XTAL)) ++ return (0); + -+ /* clear this packet from the descriptor ring */ -+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) - di->dataoffsetlow), -+ di->rxbufsize, DMA_RX, rxp); -+ W_SM(&di->rxd32[i].addr, 0xdeadbeef); ++ if (what & XTAL) ++ outen |= PCI_CFG_GPIO_XTAL; ++ if (what & PLL) ++ outen |= PCI_CFG_GPIO_PLL; ++ ++ if (on) { ++ /* turn primary xtal on */ ++ if (what & XTAL) { ++ out |= PCI_CFG_GPIO_XTAL; ++ if (what & PLL) ++ out |= PCI_CFG_GPIO_PLL; ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, ++ sizeof(uint32), out); ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, ++ sizeof(uint32), outen); ++ OSL_DELAY(XTAL_ON_DELAY); ++ } ++ ++ /* turn pll on */ ++ if (what & PLL) { ++ out &= ~PCI_CFG_GPIO_PLL; ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, ++ sizeof(uint32), out); ++ OSL_DELAY(2000); ++ } ++ } else { ++ if (what & XTAL) ++ out &= ~PCI_CFG_GPIO_XTAL; ++ if (what & PLL) ++ out |= PCI_CFG_GPIO_PLL; ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32), out); ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN, sizeof(uint32), ++ outen); ++ } + -+ di->rxin = NEXTRXD(i); ++ default: ++ return (-1); ++ } + -+ return (rxp); ++ return (0); +} + -+static void -+dma32_txrotate(di_t *di) ++/* set dynamic clk control mode (forceslow, forcefast, dynamic) */ ++/* returns true if we are forcing fast clock */ ++bool ++sb_clkctl_clk(sb_t *sbh, uint mode) +{ -+ uint ad; -+ uint nactive; -+ uint rot; -+ uint old, new; -+ uint32 w; -+ uint first, last; -+ -+ ASSERT(dma_txsuspendedidle(di)); -+ -+ nactive = dma_txactive(di); -+ ad = B2I(((R_REG(&di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t); -+ rot = TXD(ad - di->txin); -+ -+ ASSERT(rot < di->ntxd); -+ -+ /* full-ring case is a lot harder - don't worry about this */ -+ if (rot >= (di->ntxd - nactive)) { -+ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); -+ return; -+ } -+ -+ first = di->txin; -+ last = PREVTXD(di->txout); ++ sb_info_t *si; ++ uint origidx; ++ chipcregs_t *cc; ++ uint32 scc; ++ uint intr_val = 0; + -+ /* move entries starting at last and moving backwards to first */ -+ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { -+ new = TXD(old + rot); ++ si = SB_INFO(sbh); + -+ /* -+ * Move the tx dma descriptor. -+ * EOT is set only in the last entry in the ring. -+ */ -+ w = R_SM(&di->txd32[old].ctrl) & ~CTRL_EOT; -+ if (new == (di->ntxd - 1)) -+ w |= CTRL_EOT; -+ W_SM(&di->txd32[new].ctrl, w); -+ W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr)); ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (si->sb.ccrev < 6) ++ return (FALSE); + -+ /* zap the old tx dma descriptor address field */ -+ W_SM(&di->txd32[old].addr, 0xdeadbeef); + -+ /* move the corresponding txp[] entry */ -+ ASSERT(di->txp[new] == NULL); -+ di->txp[new] = di->txp[old]; -+ di->txp[old] = NULL; -+ } ++ /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */ ++ ASSERT(si->sb.ccrev != 10); + -+ /* update txin and txout */ -+ di->txin = ad; -+ di->txout = TXD(di->txout + rot); -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ INTR_OFF(si, intr_val); + -+ /* kick the chip */ -+ W_REG(&di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); -+} ++ origidx = si->curidx; + -+/*** 64 bits DMA non-inline functions ***/ ++ if (sb_setcore(sbh, SB_MIPS33, 0) && (sb_corerev(&si->sb) <= 7) && ++ (BUSTYPE(si->sb.bustype) == SB_BUS) && (si->sb.ccrev >= 10)) ++ goto done; + -+#ifdef BCMDMA64 ++ /* PR32414WAR "Force HT clock on" all the time, no dynamic clk ctl */ ++ if ((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev <= 1)) ++ goto done; + -+static bool -+dma64_alloc(dma_info_t *di, uint direction) -+{ -+ uint size; -+ uint ddlen; -+ uint32 alignbytes; -+ void *va; ++ cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0); ++ ASSERT(cc != NULL); + -+ ddlen = sizeof (dma64dd_t); ++ if (!(R_REG(si->osh, &cc->capabilities) & CAP_PWR_CTL)) ++ goto done; + -+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ switch (mode) { ++ case CLK_FAST: /* force fast (pll) clock */ ++ if (si->sb.ccrev < 10) { ++ /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */ ++ sb_clkctl_xtal(&si->sb, XTAL, ON); + -+ alignbytes = di->dma64align; ++ SET_REG(si->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); ++ } else ++ OR_REG(si->osh, &cc->system_clk_ctl, SYCC_HR); ++ /* wait for the PLL */ ++ OSL_DELAY(PLL_DELAY); ++ break; + -+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, alignbytes)) -+ size += alignbytes; ++ case CLK_DYNAMIC: /* enable dynamic clock control */ + ++ if (si->sb.ccrev < 10) { ++ scc = R_REG(si->osh, &cc->slow_clk_ctl); ++ scc &= ~(SCC_FS | SCC_IP | SCC_XC); ++ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) ++ scc |= SCC_XC; ++ W_REG(si->osh, &cc->slow_clk_ctl, scc); + -+ if (direction == DMA_TX) { -+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->txdpa)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name)); -+ return FALSE; ++ /* for dynamic control, we have to release our xtal_pu "force on" */ ++ if (scc & SCC_XC) ++ sb_clkctl_xtal(&si->sb, XTAL, OFF); ++ } else { ++ /* Instaclock */ ++ AND_REG(si->osh, &cc->system_clk_ctl, ~SYCC_HR); + } ++ break; + -+ di->txd64 = (dma64dd_t*) ROUNDUP((uintptr)va, alignbytes); -+ di->txdalign = (uint)((int8*)di->txd64 - (int8*)va); -+ di->txdpa += di->txdalign; -+ di->txdalloc = size; -+ ASSERT(ISALIGNED((uintptr)di->txd64, alignbytes)); -+ } else { -+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->rxdpa)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name)); -+ return FALSE; -+ } -+ di->rxd64 = (dma64dd_t*) ROUNDUP((uintptr)va, alignbytes); -+ di->rxdalign = (uint)((int8*)di->rxd64 - (int8*)va); -+ di->rxdpa += di->rxdalign; -+ di->rxdalloc = size; -+ ASSERT(ISALIGNED((uintptr)di->rxd64, alignbytes)); ++ default: ++ ASSERT(0); + } + -+ return TRUE; ++done: ++ sb_setcoreidx(sbh, origidx); ++ INTR_RESTORE(si, intr_val); ++ return (mode == CLK_FAST); +} + -+static void -+dma64_txreset(dma_info_t *di) ++/* register driver interrupt disabling and restoring callback functions */ ++void ++sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, void *intrsrestore_fn, ++ void *intrsenabled_fn, void *intr_arg) +{ -+ uint32 status; -+ -+ /* suspend tx DMA first */ -+ W_REG(&di->d64txregs->control, D64_XC_SE); -+ SPINWAIT((status = (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED && -+ status != D64_XS0_XS_IDLE && -+ status != D64_XS0_XS_STOPPED, -+ 10000); -+ -+ W_REG(&di->d64txregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED, -+ 10000); -+ -+ if (status != D64_XS0_XS_DISABLED) { -+ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); -+ } ++ sb_info_t *si; + -+ /* wait for the last transaction to complete */ -+ OSL_DELAY(300); ++ si = SB_INFO(sbh); ++ si->intr_arg = intr_arg; ++ si->intrsoff_fn = (sb_intrsoff_t)intrsoff_fn; ++ si->intrsrestore_fn = (sb_intrsrestore_t)intrsrestore_fn; ++ si->intrsenabled_fn = (sb_intrsenabled_t)intrsenabled_fn; ++ /* save current core id. when this function called, the current core ++ * must be the core which provides driver functions(il, et, wl, etc.) ++ */ ++ si->dev_coreid = si->coreid[si->curidx]; +} + -+static void -+dma64_rxreset(dma_info_t *di) -+{ -+ uint32 status; -+ -+ W_REG(&di->d64rxregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED, -+ 10000); -+ -+ if (status != D64_RS0_RS_DISABLED) { -+ DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name)); -+ } -+} + -+static bool -+dma64_txsuspendedidle(dma_info_t *di) ++int ++sb_corepciid(sb_t *sbh, uint func, uint16 *pcivendor, uint16 *pcidevice, ++ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, ++ uint8 *pciheader) +{ ++ uint16 vendor = 0xffff, device = 0xffff; ++ uint core, unit; ++ uint chip, chippkg; ++ uint nfunc; ++ char varname[SB_DEVPATH_BUFSZ + 8]; ++ uint8 class, subclass, progif; ++ char devpath[SB_DEVPATH_BUFSZ]; ++ uint8 header; + -+ if (!(R_REG(&di->d64txregs->control) & D64_XC_SE)) -+ return 0; -+ -+ if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_IDLE) -+ return 1; ++ core = sb_coreid(sbh); ++ unit = sb_coreunit(sbh); + -+ return 0; -+} ++ chip = sb_chip(sbh); ++ chippkg = sb_chippkg(sbh); + -+/* -+ * supports full 32bit dma engine buffer addressing so -+ * dma buffers can cross 4 Kbyte page boundaries. -+ */ -+static int -+dma64_txfast(dma_info_t *di, void *p0, uint32 coreflags) -+{ -+ void *p, *next; -+ uchar *data; -+ uint len; -+ uint txout; -+ uint32 flags; -+ uint32 pa; ++ progif = 0; ++ header = PCI_HEADER_NORMAL; + -+ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ /* Verify whether the function exists for the core */ ++ nfunc = (core == SB_USB20H) ? 2 : 1; ++ if (func >= nfunc) ++ return BCME_ERROR; + -+ txout = di->txout; -+ flags = 0; ++ /* Known vendor translations */ ++ switch (sb_corevendor(sbh)) { ++ case SB_VEND_BCM: ++ vendor = VENDOR_BROADCOM; ++ break; ++ default: ++ return BCME_ERROR; ++ } + -+ /* -+ * Walk the chain of packet buffers -+ * allocating and initializing transmit descriptor entries. -+ */ -+ for (p = p0; p; p = next) { -+ data = PKTDATA(di->osh, p); -+ len = PKTLEN(di->osh, p); -+ next = PKTNEXT(di->osh, p); ++ /* Determine class based on known core codes */ ++ switch (core) { ++ case SB_ILINE20: ++ class = PCI_CLASS_NET; ++ subclass = PCI_NET_ETHER; ++ device = BCM47XX_ILINE_ID; ++ break; ++ case SB_ENET: ++ class = PCI_CLASS_NET; ++ subclass = PCI_NET_ETHER; ++ device = BCM47XX_ENET_ID; ++ break; ++ case SB_GIGETH: ++ class = PCI_CLASS_NET; ++ subclass = PCI_NET_ETHER; ++ device = BCM47XX_GIGETH_ID; ++ break; ++ case SB_SDRAM: ++ case SB_MEMC: ++ class = PCI_CLASS_MEMORY; ++ subclass = PCI_MEMORY_RAM; ++ device = (uint16)core; ++ break; ++ case SB_PCI: ++ case SB_PCIE: ++ class = PCI_CLASS_BRIDGE; ++ subclass = PCI_BRIDGE_PCI; ++ device = (uint16)core; ++ header = PCI_HEADER_BRIDGE; ++ break; ++ case SB_MIPS: ++ case SB_MIPS33: ++ class = PCI_CLASS_CPU; ++ subclass = PCI_CPU_MIPS; ++ device = (uint16)core; ++ break; ++ case SB_CODEC: ++ class = PCI_CLASS_COMM; ++ subclass = PCI_COMM_MODEM; ++ device = BCM47XX_V90_ID; ++ break; ++ case SB_USB: ++ class = PCI_CLASS_SERIAL; ++ subclass = PCI_SERIAL_USB; ++ progif = 0x10; /* OHCI */ ++ device = BCM47XX_USB_ID; ++ break; ++ case SB_USB11H: ++ class = PCI_CLASS_SERIAL; ++ subclass = PCI_SERIAL_USB; ++ progif = 0x10; /* OHCI */ ++ device = BCM47XX_USBH_ID; ++ break; ++ case SB_USB20H: ++ class = PCI_CLASS_SERIAL; ++ subclass = PCI_SERIAL_USB; ++ progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */ ++ device = BCM47XX_USB20H_ID; ++ header = 0x80; /* multifunction */ ++ break; ++ case SB_USB11D: ++ class = PCI_CLASS_SERIAL; ++ subclass = PCI_SERIAL_USB; ++ device = BCM47XX_USBD_ID; ++ break; ++ case SB_USB20D: ++ class = PCI_CLASS_SERIAL; ++ subclass = PCI_SERIAL_USB; ++ device = BCM47XX_USB20D_ID; ++ break; ++ case SB_IPSEC: ++ class = PCI_CLASS_CRYPT; ++ subclass = PCI_CRYPT_NETWORK; ++ device = BCM47XX_IPSEC_ID; ++ break; ++ case SB_ROBO: ++ class = PCI_CLASS_NET; ++ subclass = PCI_NET_OTHER; ++ device = BCM47XX_ROBO_ID; ++ break; ++ case SB_EXTIF: ++ case SB_CC: ++ class = PCI_CLASS_MEMORY; ++ subclass = PCI_MEMORY_FLASH; ++ device = (uint16)core; ++ break; ++ case SB_D11: ++ class = PCI_CLASS_NET; ++ subclass = PCI_NET_OTHER; ++ /* Let nvram variable override core ID */ ++ sb_devpath(sbh, devpath, sizeof(devpath)); ++ sprintf(varname, "%sdevid", devpath); ++ if ((device = (uint16)getintvar(NULL, varname))) ++ break; ++ /* ++ * no longer support wl%did, but keep the code ++ * here for backward compatibility. ++ */ ++ sprintf(varname, "wl%did", unit); ++ if ((device = (uint16)getintvar(NULL, varname))) ++ break; ++ /* Chip specific conversion */ ++ if (chip == BCM4712_CHIP_ID) { ++ if (chippkg == BCM4712SMALL_PKG_ID) ++ device = BCM4306_D11G_ID; ++ else ++ device = BCM4306_D11DUAL_ID; ++ break; ++ } ++ /* ignore it */ ++ device = 0xffff; ++ break; ++ case SB_SATAXOR: ++ class = PCI_CLASS_XOR; ++ subclass = PCI_XOR_QDMA; ++ device = BCM47XX_SATAXOR_ID; ++ break; ++ case SB_ATA100: ++ class = PCI_CLASS_DASDI; ++ subclass = PCI_DASDI_IDE; ++ device = BCM47XX_ATA100_ID; ++ break; + -+ /* return nonzero if out of tx descriptors */ -+ if (NEXTTXD(txout) == di->txin) -+ goto outoftxd; ++ default: ++ class = subclass = progif = 0xff; ++ device = (uint16)core; ++ break; ++ } + -+ if (len == 0) -+ continue; ++ *pcivendor = vendor; ++ *pcidevice = device; ++ *pciclass = class; ++ *pcisubclass = subclass; ++ *pciprogif = progif; ++ *pciheader = header; + -+ /* get physical address of buffer start */ -+ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); ++ return 0; ++} + -+ flags = coreflags; -+ -+ if (p == p0) -+ flags |= D64_CTRL1_SOF; -+ if (next == NULL) -+ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); -+ if (txout == (di->ntxd - 1)) -+ flags |= D64_CTRL1_EOT; + -+ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); + -+ ASSERT(di->txp[txout] == NULL); ++/* use the mdio interface to write to mdio slaves */ ++static int ++sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint regaddr, uint val) ++{ ++ uint mdiodata; ++ uint i = 0; ++ sbpcieregs_t *pcieregs; + -+ txout = NEXTTXD(txout); -+ } ++ pcieregs = (sbpcieregs_t*) sb_setcoreidx(&si->sb, si->sb.buscoreidx); ++ ASSERT(pcieregs); + -+ /* if last txd eof not set, fix it */ -+ if (!(flags & D64_CTRL1_EOF)) -+ W_SM(&di->txd64[PREVTXD(txout)].ctrl1, BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF)); ++ /* enable mdio access to SERDES */ ++ W_REG(si->osh, (&pcieregs->mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); + -+ /* save the packet */ -+ di->txp[PREVTXD(txout)] = p0; ++ mdiodata = MDIODATA_START | MDIODATA_WRITE | ++ (physmedia << MDIODATA_DEVADDR_SHF) | ++ (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA | val; + -+ /* bump the tx descriptor index */ -+ di->txout = txout; ++ W_REG(si->osh, (&pcieregs->mdiodata), mdiodata); + -+ /* kick the chip */ -+ W_REG(&di->d64txregs->ptr, I2B(txout, dma64dd_t)); ++ PR28829_DELAY(); + -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ /* retry till the transaction is complete */ ++ while (i < 10) { ++ if (R_REG(si->osh, &(pcieregs->mdiocontrol)) & MDIOCTL_ACCESS_DONE) { ++ /* Disable mdio access to SERDES */ ++ W_REG(si->osh, (&pcieregs->mdiocontrol), 0); ++ return 0; ++ } ++ OSL_DELAY(1000); ++ i++; ++ } + -+ return (0); ++ SB_ERROR(("sb_pcie_mdiowrite: timed out\n")); ++ /* Disable mdio access to SERDES */ ++ W_REG(si->osh, (&pcieregs->mdiocontrol), 0); ++ ASSERT(0); ++ return 1; + -+outoftxd: -+ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); -+ PKTFREE(di->osh, p0, TRUE); -+ di->txavail = 0; -+ di->hnddma.txnobuf++; -+ return (-1); +} + -+static void* -+dma64_getnexttxp(dma_info_t *di, bool forceall) ++/* indirect way to read pcie config regs */ ++uint ++sb_pcie_readreg(void *sb, void* arg1, uint offset) +{ -+ uint start, end, i; -+ void *txp; ++ sb_info_t *si; ++ sb_t *sbh; ++ uint retval = 0xFFFFFFFF; ++ sbpcieregs_t *pcieregs; ++ uint addrtype; + -+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); ++ sbh = (sb_t *)sb; ++ si = SB_INFO(sbh); ++ ASSERT(PCIE(si)); + -+ txp = NULL; ++ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); ++ ASSERT(pcieregs); + -+ start = di->txin; -+ if (forceall) -+ end = di->txout; -+ else -+ end = B2I(R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK, dma64dd_t); ++ addrtype = (uint)((uintptr)arg1); ++ switch (addrtype) { ++ case PCIE_CONFIGREGS: ++ W_REG(si->osh, (&pcieregs->configaddr), offset); ++ retval = R_REG(si->osh, &(pcieregs->configdata)); ++ break; ++ case PCIE_PCIEREGS: ++ W_REG(si->osh, &(pcieregs->pcieaddr), offset); ++ retval = R_REG(si->osh, &(pcieregs->pciedata)); ++ break; ++ default: ++ ASSERT(0); ++ break; ++ } ++ return retval; ++} + -+ if ((start == 0) && (end > di->txout)) -+ goto bogus; ++/* indirect way to write pcie config/mdio/pciecore regs */ ++uint ++sb_pcie_writereg(sb_t *sbh, void *arg1, uint offset, uint val) ++{ ++ sb_info_t *si; ++ sbpcieregs_t *pcieregs; ++ uint addrtype; + -+ for (i = start; i != end && !txp; i = NEXTTXD(i)) { -+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) - di->dataoffsetlow), -+ (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) & D64_CTRL2_BC_MASK), DMA_TX, di->txp[i]); ++ si = SB_INFO(sbh); ++ ASSERT(PCIE(si)); ++ ++ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); ++ ASSERT(pcieregs); + -+ W_SM(&di->txd64[i].addrlow, 0xdeadbeef); -+ W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); ++ addrtype = (uint)((uintptr)arg1); + -+ txp = di->txp[i]; -+ di->txp[i] = NULL; ++ switch (addrtype) { ++ case PCIE_CONFIGREGS: ++ W_REG(si->osh, (&pcieregs->configaddr), offset); ++ W_REG(si->osh, (&pcieregs->configdata), val); ++ break; ++ case PCIE_PCIEREGS: ++ W_REG(si->osh, (&pcieregs->pcieaddr), offset); ++ W_REG(si->osh, (&pcieregs->pciedata), val); ++ break; ++ default: ++ ASSERT(0); ++ break; + } ++ return 0; ++} + -+ di->txin = i; -+ -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++/* Build device path. Support SB, PCI, and JTAG for now. */ ++int ++sb_devpath(sb_t *sbh, char *path, int size) ++{ ++ ASSERT(path); ++ ASSERT(size >= SB_DEVPATH_BUFSZ); + -+ return (txp); ++ switch (BUSTYPE((SB_INFO(sbh))->sb.bustype)) { ++ case SB_BUS: ++ case JTAG_BUS: ++ sprintf(path, "sb/%u/", sb_coreidx(sbh)); ++ break; ++ case PCI_BUS: ++ ASSERT((SB_INFO(sbh))->osh); ++ sprintf(path, "pci/%u/%u/", OSL_PCI_BUS((SB_INFO(sbh))->osh), ++ OSL_PCI_SLOT((SB_INFO(sbh))->osh)); ++ break; ++ case PCMCIA_BUS: ++ SB_ERROR(("sb_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n")); ++ SB_ERROR(("sb_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n")); ++ sprintf(path, "pc/%u/%u/", 1, 1); ++ break; ++ case SDIO_BUS: ++ SB_ERROR(("sb_devpath: device 0 assumed\n")); ++ sprintf(path, "sd/%u/", sb_coreidx(sbh)); ++ break; ++ default: ++ ASSERT(0); ++ break; ++ } + -+bogus: -+/* -+ DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", -+ start, end, di->txout, forceall)); -+*/ -+ return (NULL); ++ return 0; +} + -+static void * -+dma64_getnextrxp(dma_info_t *di, bool forceall) ++/* ++ * Fixup SROMless PCI device's configuration. ++ * The current core may be changed upon return. ++ */ ++static int ++sb_pci_fixcfg(sb_info_t *si) +{ -+ uint i; -+ void *rxp; ++ uint origidx, pciidx; ++ sbpciregs_t *pciregs; ++ sbpcieregs_t *pcieregs; ++ uint16 val16, *reg16; ++ char name[SB_DEVPATH_BUFSZ+16], *value; ++ char devpath[SB_DEVPATH_BUFSZ]; + -+ /* if forcing, dma engine must be disabled */ -+ ASSERT(!forceall || !dma_rxenabled(di)); ++ ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS); + -+ i = di->rxin; ++ /* Fixup PI in SROM shadow area to enable the correct PCI core access */ ++ /* save the current index */ ++ origidx = sb_coreidx(&si->sb); + -+ /* return if no packets posted */ -+ if (i == di->rxout) -+ return (NULL); ++ /* check 'pi' is correct and fix it if not */ ++ if (si->sb.buscoretype == SB_PCIE) { ++ pcieregs = (sbpcieregs_t *)sb_setcore(&si->sb, SB_PCIE, 0); ++ ASSERT(pcieregs); ++ reg16 = &pcieregs->sprom[SRSH_PI_OFFSET]; ++ } else if (si->sb.buscoretype == SB_PCI) { ++ pciregs = (sbpciregs_t *)sb_setcore(&si->sb, SB_PCI, 0); ++ ASSERT(pciregs); ++ reg16 = &pciregs->sprom[SRSH_PI_OFFSET]; ++ } else { ++ ASSERT(0); ++ return -1; ++ } ++ pciidx = sb_coreidx(&si->sb); ++ val16 = R_REG(si->osh, reg16); ++ if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) { ++ val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK); ++ W_REG(si->osh, reg16, val16); ++ } + -+ /* ignore curr if forceall */ -+ if (!forceall && (i == B2I(R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK, dma64dd_t))) -+ return (NULL); ++ /* restore the original index */ ++ sb_setcoreidx(&si->sb, origidx); + -+ /* get the packet pointer that corresponds to the rx descriptor */ -+ rxp = di->rxp[i]; -+ ASSERT(rxp); -+ di->rxp[i] = NULL; ++ /* ++ * Fixup bar0window in PCI config space to make the core indicated ++ * by the nvram variable the current core. ++ * !Do it last, it may change the current core! ++ */ ++ if (sb_devpath(&si->sb, devpath, sizeof(devpath))) ++ return -1; ++ sprintf(name, "%sb0w", devpath); ++ if ((value = getvar(NULL, name))) { ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32), ++ bcm_strtoul(value, NULL, 16)); ++ /* update curidx since the current core is changed */ ++ si->curidx = _sb_coreidx(si); ++ if (si->curidx == BADIDX) { ++ SB_ERROR(("sb_pci_fixcfg: bad core index\n")); ++ return -1; ++ } ++ } + -+ /* clear this packet from the descriptor ring */ -+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) - di->dataoffsetlow), -+ di->rxbufsize, DMA_RX, rxp); ++ return 0; ++} + -+ W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); -+ W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); ++static uint ++sb_chipc_capability(sb_t *sbh) ++{ ++ sb_info_t *si; + -+ di->rxin = NEXTRXD(i); ++ si = SB_INFO(sbh); + -+ return (rxp); ++ /* Make sure that there is ChipCommon core present */ ++ if (si->coreid[SB_CC_IDX] == SB_CC) ++ return (sb_corereg(si, SB_CC_IDX, OFFSETOF(chipcregs_t, capabilities), ++ 0, 0)); ++ return 0; +} + -+static void -+dma64_txrotate(di_t *di) ++/* Return ADDR64 capability of the backplane */ ++bool ++sb_backplane64(sb_t *sbh) +{ -+ uint ad; -+ uint nactive; -+ uint rot; -+ uint old, new; -+ uint32 w; -+ uint first, last; ++ return ((sb_chipc_capability(sbh) & CAP_BKPLN64) != 0); ++} + -+ ASSERT(dma_txsuspendedidle(di)); ++void ++sb_btcgpiowar(sb_t *sbh) ++{ ++ sb_info_t *si; ++ uint origidx; ++ uint intr_val = 0; ++ chipcregs_t *cc; ++ si = SB_INFO(sbh); + -+ nactive = dma_txactive(di); -+ ad = B2I((R_REG(&di->d64txregs->status1) & D64_XS1_AD_MASK), dma64dd_t); -+ rot = TXD(ad - di->txin); ++ /* Make sure that there is ChipCommon core present && ++ * UART_TX is strapped to 1 ++ */ ++ if (!(sb_chipc_capability(sbh) & CAP_UARTGPIO)) ++ return; + -+ ASSERT(rot < di->ntxd); ++ /* sb_corereg cannot be used as we have to guarantee 8-bit read/writes */ ++ INTR_OFF(si, intr_val); + -+ /* full-ring case is a lot harder - don't worry about this */ -+ if (rot >= (di->ntxd - nactive)) { -+ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); -+ return; -+ } ++ origidx = sb_coreidx(sbh); + -+ first = di->txin; -+ last = PREVTXD(di->txout); ++ cc = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0); ++ if (cc == NULL) ++ goto end; + -+ /* move entries starting at last and moving backwards to first */ -+ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { -+ new = TXD(old + rot); ++ W_REG(si->osh, &cc->uart0mcr, R_REG(si->osh, &cc->uart0mcr) | 0x04); + -+ /* -+ * Move the tx dma descriptor. -+ * EOT is set only in the last entry in the ring. -+ */ -+ w = R_SM(&di->txd64[old].ctrl1) & ~D64_CTRL1_EOT; -+ if (new == (di->ntxd - 1)) -+ w |= D64_CTRL1_EOT; -+ W_SM(&di->txd64[new].ctrl1, w); ++end: ++ /* restore the original index */ ++ sb_setcoreidx(sbh, origidx); + -+ w = R_SM(&di->txd64[old].ctrl2); -+ W_SM(&di->txd64[new].ctrl2, w); ++ INTR_RESTORE(si, intr_val); ++} + -+ W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); -+ W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); ++/* check if the device is removed */ ++bool ++sb_deviceremoved(sb_t *sbh) ++{ ++ uint32 w; ++ sb_info_t *si; + -+ /* zap the old tx dma descriptor address field */ -+ W_SM(&di->txd64[old].addrlow, 0xdeadbeef); -+ W_SM(&di->txd64[old].addrhigh, 0xdeadbeef); ++ si = SB_INFO(sbh); + -+ /* move the corresponding txp[] entry */ -+ ASSERT(di->txp[new] == NULL); -+ di->txp[new] = di->txp[old]; -+ di->txp[old] = NULL; ++ switch (BUSTYPE(si->sb.bustype)) { ++ case PCI_BUS: ++ ASSERT(si->osh); ++ w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_VID, sizeof(uint32)); ++ if ((w & 0xFFFF) != VENDOR_BROADCOM) ++ return TRUE; ++ else ++ return FALSE; ++ default: ++ return FALSE; + } ++ return FALSE; ++} + -+ /* update txin and txout */ -+ di->txin = ad; -+ di->txout = TXD(di->txout + rot); -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++/* Return the RAM size of the SOCRAM core */ ++uint32 ++sb_socram_size(sb_t *sbh) ++{ ++ sb_info_t *si; ++ uint origidx; ++ uint intr_val = 0; + -+ /* kick the chip */ -+ W_REG(&di->d64txregs->ptr, I2B(di->txout, dma64dd_t)); -+} ++ sbsocramregs_t *regs; ++ bool wasup; ++ uint corerev; ++ uint32 coreinfo; ++ uint memsize = 0; + -+#endif ++ si = SB_INFO(sbh); ++ ASSERT(si); + -diff -Naur linux.old/drivers/net/wl/hnddma.h linux.dev/drivers/net/wl/hnddma.h ---- linux.old/drivers/net/wl/hnddma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl/hnddma.h 2006-04-06 16:57:44.000000000 +0200 -@@ -0,0 +1,69 @@ -+/* -+ * Generic Broadcom Home Networking Division (HND) DMA engine SW interface -+ * This supports the following chips: BCM42xx, 44xx, 47xx . -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ ++ /* Block ints and save current core */ ++ INTR_OFF(si, intr_val); ++ origidx = sb_coreidx(sbh); + -+#ifndef _hnddma_h_ -+#define _hnddma_h_ ++ /* Switch to SOCRAM core */ ++ if (!(regs = sb_setcore(sbh, SB_SOCRAM, 0))) ++ goto done; + -+/* export structure */ -+typedef volatile struct { -+ /* rx error counters */ -+ uint rxgiants; /* rx giant frames */ -+ uint rxnobuf; /* rx out of dma descriptors */ -+ /* tx error counters */ -+ uint txnobuf; /* tx out of dma descriptors */ -+} hnddma_t; ++ /* Get info for determining size */ ++ if (!(wasup = sb_iscoreup(sbh))) ++ sb_core_reset(sbh, 0, 0); ++ corerev = sb_corerev(sbh); ++ coreinfo = R_REG(si->osh, ®s->coreinfo); + -+#ifndef di_t -+#define di_t void -+#endif ++ /* Calculate size from coreinfo based on rev */ ++ switch (corerev) { ++ case 0: ++ memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK)); ++ break; ++ default: /* rev >= 1 */ ++ memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK)); ++ memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; ++ break; ++ } + -+#ifndef osl_t -+#define osl_t void -+#endif ++ /* Return to previous state and core */ ++ if (!wasup) ++ sb_core_disable(sbh, 0); ++ sb_setcoreidx(sbh, origidx); + -+/* externs */ -+extern void dma_detach(di_t *di); -+extern void dma_txreset(di_t *di); -+extern void dma_rxreset(di_t *di); -+extern void dma_txinit(di_t *di); -+extern bool dma_txenabled(di_t *di); -+extern void dma_rxinit(di_t *di); -+extern void dma_rxenable(di_t *di); -+extern bool dma_rxenabled(di_t *di); -+extern void dma_txsuspend(di_t *di); -+extern void dma_txresume(di_t *di); -+extern bool dma_txsuspended(di_t *di); -+extern bool dma_txsuspendedidle(di_t *di); -+extern bool dma_txstopped(di_t *di); -+extern bool dma_rxstopped(di_t *di); -+extern int dma_txfast(di_t *di, void *p, uint32 coreflags); -+extern void dma_fifoloopbackenable(di_t *di); -+extern void *dma_rx(di_t *di); -+extern void dma_rxfill(di_t *di); -+extern void dma_txreclaim(di_t *di, bool forceall); -+extern void dma_rxreclaim(di_t *di); -+extern uintptr dma_getvar(di_t *di, char *name); -+extern void *dma_getnexttxp(di_t *di, bool forceall); -+extern void *dma_peeknexttxp(di_t *di); -+extern void *dma_getnextrxp(di_t *di, bool forceall); -+extern void dma_txblock(di_t *di); -+extern void dma_txunblock(di_t *di); -+extern uint dma_txactive(di_t *di); -+extern void dma_txrotate(di_t *di); -+ -+extern void dma_rxpiomode(dma32regs_t *); -+extern void dma_txpioloopback(dma32regs_t *); ++done: ++ INTR_RESTORE(si, intr_val); ++ return memsize; ++} + + -+#endif /* _hnddma_h_ */ -diff -Naur linux.old/drivers/net/wl/pktq.h linux.dev/drivers/net/wl/pktq.h ---- linux.old/drivers/net/wl/pktq.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl/pktq.h 2006-04-06 17:32:52.000000000 +0200 -@@ -0,0 +1,48 @@ +diff -urN linux.old/arch/mips/bcm947xx/setup.c linux.dev/arch/mips/bcm947xx/setup.c +--- linux.old/arch/mips/bcm947xx/setup.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/setup.c 2006-04-27 23:22:53.000000000 +0200 +@@ -0,0 +1,241 @@ +/* -+ * Misc useful os-independent macros and functions. ++ * Generic setup routines for Broadcom MIPS boards ++ * ++ * Copyright (C) 2005 Felix Fietkau ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * THIS SOFTWARE IS PROVIDED ``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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * + * + * Copyright 2005, Broadcom Corporation + * All Rights Reserved. @@ -17483,776 +15114,1315 @@ diff -Naur linux.old/drivers/net/wl/pktq.h linux.dev/drivers/net/wl/pktq.h + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ ++ * + */ + -+#ifndef _pktq_h_ -+#define _pktq_h_ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+/*** driver-only section ***/ -+#ifdef BCMDRIVER ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+/* generic osl packet queue */ -+struct pktq { -+ void *head; /* first packet to dequeue */ -+ void *tail; /* last packet to dequeue */ -+ uint len; /* number of queued packets */ -+ uint maxlen; /* maximum number of queued packets */ -+ bool priority; /* enqueue by packet priority */ -+ uint8 prio_map[MAXPRIO+1]; /* user priority to packet enqueue policy map */ -+}; -+#define DEFAULT_QLEN 128 ++/* Virtual IRQ base, after last hw IRQ */ ++#define SBMIPS_VIRTIRQ_BASE 6 + -+#define pktq_len(q) ((q)->len) -+#define pktq_avail(q) ((q)->maxlen - (q)->len) -+#define pktq_head(q) ((q)->head) -+#define pktq_full(q) ((q)->len >= (q)->maxlen) -+#define _pktq_pri(q, pri) ((q)->prio_map[pri]) -+#define pktq_tailpri(q) ((q)->tail ? _pktq_pri(q, PKTPRIO((q)->tail)) : _pktq_pri(q, 0)) ++/* # IRQs, hw and sw IRQs */ ++#define SBMIPS_NUMIRQS 8 + -+/* externs */ -+/* packet */ -+extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); -+extern uint pkttotlen(osl_t *osh, void *); -+extern void pktq_init(struct pktq *q, uint maxlen, const uint8 prio_map[]); -+extern void pktenq(struct pktq *q, void *p, bool lifo); -+extern void *pktdeq(struct pktq *q); -+extern void *pktdeqtail(struct pktq *q); ++/* Global SB handle */ ++sb_t *bcm947xx_sbh = NULL; ++spinlock_t bcm947xx_sbh_lock = SPIN_LOCK_UNLOCKED; ++ ++/* Convenience */ ++#define sbh bcm947xx_sbh ++#define sbh_lock bcm947xx_sbh_lock ++ ++extern void bcm947xx_time_init(void); ++extern void bcm947xx_timer_setup(struct irqaction *irq); + ++#ifdef CONFIG_REMOTE_DEBUG ++extern void set_debug_traps(void); ++extern void rs_kgdb_hook(struct serial_state *); ++extern void breakpoint(void); +#endif -+#endif /* _pktq_h_ */ -diff -Naur linux.old/drivers/net/wl/sbhnddma.h linux.dev/drivers/net/wl/sbhnddma.h ---- linux.old/drivers/net/wl/sbhnddma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl/sbhnddma.h 2006-04-06 15:34:14.000000000 +0200 -@@ -0,0 +1,312 @@ -+/* -+ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface -+ * This supports the following chips: BCM42xx, 44xx, 47xx . -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ + -+#ifndef _sbhnddma_h_ -+#define _sbhnddma_h_ ++#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) ++extern struct ide_ops std_ide_ops; ++#endif + -+ -+/* 2byte-wide pio register set per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint16 fifocontrol; -+ uint16 fifodata; -+ uint16 fifofree; /* only valid in xmt channel, not in rcv channel */ -+ uint16 PAD; -+} pio2regs_t; ++/* Kernel command line */ ++char arcs_cmdline[CL_SIZE] __initdata = CONFIG_CMDLINE; ++extern void sb_serial_init(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift)); + -+/* a pair of pio channels(tx and rx) */ -+typedef volatile struct { -+ pio2regs_t tx; -+ pio2regs_t rx; -+} pio2regp_t; ++void ++bcm947xx_machine_restart(char *command) ++{ ++ printk("Please stand by while rebooting the system...\n"); + -+/* 4byte-wide pio register set per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint32 fifocontrol; -+ uint32 fifodata; -+} pio4regs_t; ++ /* Set the watchdog timer to reset immediately */ ++ __cli(); ++ sb_watchdog(sbh, 1); ++ while (1); ++} + -+/* a pair of pio channels(tx and rx) */ -+typedef volatile struct { -+ pio4regs_t tx; -+ pio4regs_t rx; -+} pio4regp_t; ++void ++bcm947xx_machine_halt(void) ++{ ++ printk("System halted\n"); + ++ /* Disable interrupts and watchdog and spin forever */ ++ __cli(); ++ sb_watchdog(sbh, 0); ++ while (1); ++} + ++#ifdef CONFIG_SERIAL + -+/* DMA structure: -+ * support two DMA engines: 32 bits address or 64 bit addressing -+ * basic DMA register set is per channel(transmit or receive) -+ * a pair of channels is defined for convenience -+ */ ++static int ser_line = 0; + ++typedef struct { ++ void *regs; ++ uint irq; ++ uint baud_base; ++ uint reg_shift; ++} serial_port; + -+/*** 32 bits addressing ***/ ++static serial_port ports[4]; ++static int num_ports = 0; + -+/* dma registers per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint32 control; /* enable, et al */ -+ uint32 addr; /* descriptor ring base address (4K aligned) */ -+ uint32 ptr; /* last descriptor posted to chip */ -+ uint32 status; /* current active descriptor, et al */ -+} dma32regs_t; ++static void ++serial_add(void *regs, uint irq, uint baud_base, uint reg_shift) ++{ ++ ports[num_ports].regs = regs; ++ ports[num_ports].irq = irq; ++ ports[num_ports].baud_base = baud_base; ++ ports[num_ports].reg_shift = reg_shift; ++ num_ports++; ++} + -+typedef volatile struct { -+ dma32regs_t xmt; /* dma tx channel */ -+ dma32regs_t rcv; /* dma rx channel */ -+} dma32regp_t; ++static void ++do_serial_add(serial_port *port) ++{ ++ void *regs; ++ uint irq; ++ uint baud_base; ++ uint reg_shift; ++ struct serial_struct s; ++ ++ regs = port->regs; ++ irq = port->irq; ++ baud_base = port->baud_base; ++ reg_shift = port->reg_shift; + -+typedef volatile struct { /* diag access */ -+ uint32 fifoaddr; /* diag address */ -+ uint32 fifodatalow; /* low 32bits of data */ -+ uint32 fifodatahigh; /* high 32bits of data */ -+ uint32 pad; /* reserved */ -+} dma32diag_t; ++ memset(&s, 0, sizeof(s)); + -+/* -+ * DMA Descriptor -+ * Descriptors are only read by the hardware, never written back. -+ */ -+typedef volatile struct { -+ uint32 ctrl; /* misc control bits & bufcount */ -+ uint32 addr; /* data buffer address */ -+} dma32dd_t; ++ s.line = ser_line++; ++ s.iomem_base = regs; ++ s.irq = irq + 2; ++ s.baud_base = baud_base / 16; ++ s.flags = ASYNC_BOOT_AUTOCONF; ++ s.io_type = SERIAL_IO_MEM; ++ s.iomem_reg_shift = reg_shift; + -+/* -+ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. -+ */ -+#define D32MAXRINGSZ 4096 -+#define D32RINGALIGN 4096 -+#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) ++ if (early_serial_setup(&s) != 0) { ++ printk(KERN_ERR "Serial setup failed!\n"); ++ } ++} + -+/* transmit channel control */ -+#define XC_XE ((uint32)1 << 0) /* transmit enable */ -+#define XC_SE ((uint32)1 << 1) /* transmit suspend request */ -+#define XC_LE ((uint32)1 << 2) /* loopback enable */ -+#define XC_FL ((uint32)1 << 4) /* flush request */ -+#define XC_AE ((uint32)3 << 16) /* address extension bits */ -+#define XC_AE_SHIFT 16 ++#endif /* CONFIG_SERIAL */ ++ ++void __init ++brcm_setup(void) ++{ ++ char *s; ++ int i; ++ char *value; ++ ++ /* Get global SB handle */ ++ sbh = sb_kattach(); ++ ++ /* Initialize clocks and interrupts */ ++ sb_mips_init(sbh, SBMIPS_VIRTIRQ_BASE); + -+/* transmit descriptor table pointer */ -+#define XP_LD_MASK 0xfff /* last valid descriptor */ ++ if (BCM330X(current_cpu_data.processor_id) && ++ (read_c0_diag() & BRCM_PFC_AVAIL)) { ++ /* ++ * Now that the sbh is inited set the proper PFC value ++ */ ++ printk("Setting the PFC to its default value\n"); ++ enable_pfc(PFC_AUTO); ++ } + -+/* transmit channel status */ -+#define XS_CD_MASK 0x0fff /* current descriptor pointer */ -+#define XS_XS_MASK 0xf000 /* transmit state */ -+#define XS_XS_SHIFT 12 -+#define XS_XS_DISABLED 0x0000 /* disabled */ -+#define XS_XS_ACTIVE 0x1000 /* active */ -+#define XS_XS_IDLE 0x2000 /* idle wait */ -+#define XS_XS_STOPPED 0x3000 /* stopped */ -+#define XS_XS_SUSP 0x4000 /* suspend pending */ -+#define XS_XE_MASK 0xf0000 /* transmit errors */ -+#define XS_XE_SHIFT 16 -+#define XS_XE_NOERR 0x00000 /* no error */ -+#define XS_XE_DPE 0x10000 /* descriptor protocol error */ -+#define XS_XE_DFU 0x20000 /* data fifo underrun */ -+#define XS_XE_BEBR 0x30000 /* bus error on buffer read */ -+#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */ -+#define XS_AD_MASK 0xfff00000 /* active descriptor */ -+#define XS_AD_SHIFT 20 + -+/* receive channel control */ -+#define RC_RE ((uint32)1 << 0) /* receive enable */ -+#define RC_RO_MASK 0xfe /* receive frame offset */ -+#define RC_RO_SHIFT 1 -+#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */ -+#define RC_AE ((uint32)3 << 16) /* address extension bits */ -+#define RC_AE_SHIFT 16 ++#ifdef CONFIG_SERIAL ++ sb_serial_init(sbh, serial_add); + -+/* receive descriptor table pointer */ -+#define RP_LD_MASK 0xfff /* last valid descriptor */ ++ /* reverse serial ports if nvram variable starts with console=ttyS1 */ ++ /* Initialize UARTs */ ++ s = nvram_get("kernel_args"); ++ if (!s) s = ""; ++ if (!strncmp(s, "console=ttyS1", 13)) { ++ for (i = num_ports; i; i--) ++ do_serial_add(&ports[i - 1]); ++ } else { ++ for (i = 0; i < num_ports; i++) ++ do_serial_add(&ports[i]); ++ } ++#endif + -+/* receive channel status */ -+#define RS_CD_MASK 0x0fff /* current descriptor pointer */ -+#define RS_RS_MASK 0xf000 /* receive state */ -+#define RS_RS_SHIFT 12 -+#define RS_RS_DISABLED 0x0000 /* disabled */ -+#define RS_RS_ACTIVE 0x1000 /* active */ -+#define RS_RS_IDLE 0x2000 /* idle wait */ -+#define RS_RS_STOPPED 0x3000 /* reserved */ -+#define RS_RE_MASK 0xf0000 /* receive errors */ -+#define RS_RE_SHIFT 16 -+#define RS_RE_NOERR 0x00000 /* no error */ -+#define RS_RE_DPE 0x10000 /* descriptor protocol error */ -+#define RS_RE_DFO 0x20000 /* data fifo overflow */ -+#define RS_RE_BEBW 0x30000 /* bus error on buffer write */ -+#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */ -+#define RS_AD_MASK 0xfff00000 /* active descriptor */ -+#define RS_AD_SHIFT 20 ++#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) ++ ide_ops = &std_ide_ops; ++#endif + -+/* fifoaddr */ -+#define FA_OFF_MASK 0xffff /* offset */ -+#define FA_SEL_MASK 0xf0000 /* select */ -+#define FA_SEL_SHIFT 16 -+#define FA_SEL_XDD 0x00000 /* transmit dma data */ -+#define FA_SEL_XDP 0x10000 /* transmit dma pointers */ -+#define FA_SEL_RDD 0x40000 /* receive dma data */ -+#define FA_SEL_RDP 0x50000 /* receive dma pointers */ -+#define FA_SEL_XFD 0x80000 /* transmit fifo data */ -+#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */ -+#define FA_SEL_RFD 0xc0000 /* receive fifo data */ -+#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */ -+#define FA_SEL_RSD 0xe0000 /* receive frame status data */ -+#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ /* Override default command line arguments */ ++ value = nvram_get("kernel_cmdline"); ++ if (value && strlen(value) && strncmp(value, "empty", 5)) ++ strncpy(arcs_cmdline, value, sizeof(arcs_cmdline)); + -+/* descriptor control flags */ -+#define CTRL_BC_MASK 0x1fff /* buffer byte count */ -+#define CTRL_AE ((uint32)3 << 16) /* address extension bits */ -+#define CTRL_AE_SHIFT 16 -+#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */ -+#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */ -+#define CTRL_EOF ((uint32)1 << 30) /* end of frame */ -+#define CTRL_SOF ((uint32)1 << 31) /* start of frame */ + -+/* control flags in the range [27:20] are core-specific and not defined here */ -+#define CTRL_CORE_MASK 0x0ff00000 ++ /* Generic setup */ ++ _machine_restart = bcm947xx_machine_restart; ++ _machine_halt = bcm947xx_machine_halt; ++ _machine_power_off = bcm947xx_machine_halt; + -+/*** 64 bits addressing ***/ ++ board_time_init = bcm947xx_time_init; ++ board_timer_setup = bcm947xx_timer_setup; ++} + -+/* dma registers per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint32 control; /* enable, et al */ -+ uint32 ptr; /* last descriptor posted to chip */ -+ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ -+ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ -+ uint32 status0; /* current descriptor, xmt state */ -+ uint32 status1; /* active descriptor, xmt error */ -+} dma64regs_t; ++const char * ++get_system_type(void) ++{ ++ static char s[32]; + -+typedef volatile struct { -+ dma64regs_t tx; /* dma64 tx channel */ -+ dma64regs_t rx; /* dma64 rx channel */ -+} dma64regp_t; ++ if (bcm947xx_sbh) { ++ sprintf(s, "Broadcom BCM%X chip rev %d", sb_chip(bcm947xx_sbh), ++ sb_chiprev(bcm947xx_sbh)); ++ return s; ++ } ++ else ++ return "Broadcom BCM947XX"; ++} + -+typedef volatile struct { /* diag access */ -+ uint32 fifoaddr; /* diag address */ -+ uint32 fifodatalow; /* low 32bits of data */ -+ uint32 fifodatahigh; /* high 32bits of data */ -+ uint32 pad; /* reserved */ -+} dma64diag_t; ++void __init ++bus_error_init(void) ++{ ++} + +diff -urN linux.old/arch/mips/bcm947xx/sflash.c linux.dev/arch/mips/bcm947xx/sflash.c +--- linux.old/arch/mips/bcm947xx/sflash.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/sflash.c 2006-04-27 22:11:27.000000000 +0200 +@@ -0,0 +1,422 @@ +/* -+ * DMA Descriptor -+ * Descriptors are only read by the hardware, never written back. ++ * Broadcom SiliconBackplane chipcommon serial flash interface ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: sflash.c,v 1.1.1.13 2006/02/27 03:43:16 honor Exp $ + */ -+typedef volatile struct { -+ uint32 ctrl1; /* misc control bits & bufcount */ -+ uint32 ctrl2; /* buffer count and address extension */ -+ uint32 addrlow; /* memory address of the first byte of the date buffer, bits 31:0 */ -+ uint32 addrhigh; /* memory address of the first byte of the date buffer, bits 63:32 */ -+} dma64dd_t; + -+/* -+ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. -+ */ -+#define D64MAXRINGSZ 8192 -+#define D64RINGALIGN 8192 -+#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+/* transmit channel control */ -+#define D64_XC_XE 0x00000001 /* transmit enable */ -+#define D64_XC_SE 0x00000002 /* transmit suspend request */ -+#define D64_XC_LE 0x00000004 /* loopback enable */ -+#define D64_XC_FL 0x00000010 /* flush request */ -+#define D64_XC_AE 0x00110000 /* address extension bits */ -+#define D64_XC_AE_SHIFT 16 ++/* Private global state */ ++static struct sflash sflash; + -+/* transmit descriptor table pointer */ -+#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ ++/* Issue a serial flash command */ ++static INLINE void ++sflash_cmd(chipcregs_t *cc, uint opcode) ++{ ++ W_REG(NULL, &cc->flashcontrol, SFLASH_START | opcode); ++ while (R_REG(NULL, &cc->flashcontrol) & SFLASH_BUSY); ++} + -+/* transmit channel status */ -+#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ -+#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ -+#define D64_XS0_XS_SHIFT 28 -+#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ -+#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ -+#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ -+#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ -+#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ ++/* Initialize serial flash access */ ++struct sflash * ++sflash_init(chipcregs_t *cc) ++{ ++ uint32 id, id2; + -+#define D64_XS1_AD_MASK 0x0001ffff /* active descriptor */ -+#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ -+#define D64_XS1_XE_SHIFT 28 -+#define D64_XS1_XE_NOERR 0x00000000 /* no error */ -+#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ -+#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ -+#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ -+#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ -+#define D64_XS1_XE_COREE 0x50000000 /* core error */ ++ bzero(&sflash, sizeof(sflash)); + -+/* receive channel control */ -+#define D64_RC_RE 0x00000001 /* receive enable */ -+#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ -+#define D64_RC_RO_SHIFT 1 -+#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ -+#define D64_RC_AE 0x00110000 /* address extension bits */ -+#define D64_RC_AE_SHIFT 16 ++ sflash.type = R_REG(NULL, &cc->capabilities) & CAP_FLASH_MASK; ++ ++ switch (sflash.type) { ++ case SFLASH_ST: ++ /* Probe for ST chips */ ++ sflash_cmd(cc, SFLASH_ST_DP); ++ sflash_cmd(cc, SFLASH_ST_RES); ++ id = R_REG(NULL, &cc->flashdata); ++ switch (id) { ++ case 0x11: ++ /* ST M25P20 2 Mbit Serial Flash */ ++ sflash.blocksize = 64 * 1024; ++ sflash.numblocks = 4; ++ break; ++ case 0x12: ++ /* ST M25P40 4 Mbit Serial Flash */ ++ sflash.blocksize = 64 * 1024; ++ sflash.numblocks = 8; ++ break; ++ case 0x13: ++ /* ST M25P80 8 Mbit Serial Flash */ ++ sflash.blocksize = 64 * 1024; ++ sflash.numblocks = 16; ++ break; ++ case 0x14: ++ /* ST M25P16 16 Mbit Serial Flash */ ++ sflash.blocksize = 64 * 1024; ++ sflash.numblocks = 32; ++ break; ++ case 0x15: ++ /* ST M25P32 32 Mbit Serial Flash */ ++ sflash.blocksize = 64 * 1024; ++ sflash.numblocks = 64; ++ break; ++ case 0x16: ++ /* ST M25P64 64 Mbit Serial Flash */ ++ sflash.blocksize = 64 * 1024; ++ sflash.numblocks = 128; ++ break; ++ case 0xbf: ++ W_REG(NULL, &cc->flashaddress, 1); ++ sflash_cmd(cc, SFLASH_ST_RES); ++ id2 = R_REG(NULL, &cc->flashdata); ++ if (id2 == 0x44) { ++ /* SST M25VF80 4 Mbit Serial Flash */ ++ sflash.blocksize = 64 * 1024; ++ sflash.numblocks = 8; ++ } ++ break; ++ } ++ break; + -+/* receive descriptor table pointer */ -+#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ ++ case SFLASH_AT: ++ /* Probe for Atmel chips */ ++ sflash_cmd(cc, SFLASH_AT_STATUS); ++ id = R_REG(NULL, &cc->flashdata) & 0x3c; ++ switch (id) { ++ case 0xc: ++ /* Atmel AT45DB011 1Mbit Serial Flash */ ++ sflash.blocksize = 256; ++ sflash.numblocks = 512; ++ break; ++ case 0x14: ++ /* Atmel AT45DB021 2Mbit Serial Flash */ ++ sflash.blocksize = 256; ++ sflash.numblocks = 1024; ++ break; ++ case 0x1c: ++ /* Atmel AT45DB041 4Mbit Serial Flash */ ++ sflash.blocksize = 256; ++ sflash.numblocks = 2048; ++ break; ++ case 0x24: ++ /* Atmel AT45DB081 8Mbit Serial Flash */ ++ sflash.blocksize = 256; ++ sflash.numblocks = 4096; ++ break; ++ case 0x2c: ++ /* Atmel AT45DB161 16Mbit Serial Flash */ ++ sflash.blocksize = 512; ++ sflash.numblocks = 4096; ++ break; ++ case 0x34: ++ /* Atmel AT45DB321 32Mbit Serial Flash */ ++ sflash.blocksize = 512; ++ sflash.numblocks = 8192; ++ break; ++ case 0x3c: ++ /* Atmel AT45DB642 64Mbit Serial Flash */ ++ sflash.blocksize = 1024; ++ sflash.numblocks = 8192; ++ break; ++ } ++ break; ++ } + -+/* receive channel status */ -+#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ -+#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ -+#define D64_RS0_RS_SHIFT 28 -+#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ -+#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ -+#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ -+#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ -+#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ ++ sflash.size = sflash.blocksize * sflash.numblocks; ++ return sflash.size ? &sflash : NULL; ++} + -+#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ -+#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ -+#define D64_RS1_RE_SHIFT 28 -+#define D64_RS1_RE_NOERR 0x00000000 /* no error */ -+#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ -+#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ -+#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ -+#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ -+#define D64_RS1_RE_COREE 0x50000000 /* core error */ ++/* Read len bytes starting at offset into buf. Returns number of bytes read. */ ++int ++sflash_read(chipcregs_t *cc, uint offset, uint len, uchar *buf) ++{ ++ int cnt; ++ uint32 *from, *to; + -+/* fifoaddr */ -+#define D64_FA_OFF_MASK 0xffff /* offset */ -+#define D64_FA_SEL_MASK 0xf0000 /* select */ -+#define D64_FA_SEL_SHIFT 16 -+#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ -+#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ -+#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ -+#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ -+#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ -+#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ -+#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ -+#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ -+#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ -+#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ if (!len) ++ return 0; + -+/* descriptor control flags 1 */ -+#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */ -+#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */ -+#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */ -+#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */ ++ if ((offset + len) > sflash.size) ++ return -22; + -+/* descriptor control flags 2 */ -+#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count mask */ -+#define D64_CTRL2_AE 0x00110000 /* address extension bits */ -+#define D64_CTRL2_AE_SHIFT 16 ++ if ((len >= 4) && (offset & 3)) ++ cnt = 4 - (offset & 3); ++ else if ((len >= 4) && ((uint32)buf & 3)) ++ cnt = 4 - ((uint32)buf & 3); ++ else ++ cnt = len; + -+/* control flags in the range [27:20] are core-specific and not defined here */ -+#define D64_CTRL_CORE_MASK 0x0ff00000 ++ from = (uint32 *)KSEG1ADDR(SB_FLASH2 + offset); ++ to = (uint32 *)buf; + ++ if (cnt < 4) { ++ bcopy(from, to, cnt); ++ return cnt; ++ } + -+#endif /* _sbhnddma_h_ */ -diff -Naur linux.old/drivers/net/wl2/Makefile linux.dev/drivers/net/wl2/Makefile ---- linux.old/drivers/net/wl2/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl2/Makefile 2006-04-06 16:56:27.000000000 +0200 -@@ -0,0 +1,23 @@ -+# -+# Makefile for the Broadcom wl driver -+# -+# Copyright 2004, Broadcom Corporation -+# All Rights Reserved. -+# -+# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+# -+# $Id: Makefile,v 1.2 2005/03/29 03:32:18 mbm Exp $ ++ while (cnt >= 4) { ++ *to++ = *from++; ++ cnt -= 4; ++ } + -+EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER ++ return (len - cnt); ++} + -+O_TARGET := wl.o ++/* Poll for command completion. Returns zero when complete. */ ++int ++sflash_poll(chipcregs_t *cc, uint offset) ++{ ++ if (offset >= sflash.size) ++ return -22; + -+obj-y := wl_apsta.o -+obj-y += compat.o hnddma.o ++ switch (sflash.type) { ++ case SFLASH_ST: ++ /* Check for ST Write In Progress bit */ ++ sflash_cmd(cc, SFLASH_ST_RDSR); ++ return R_REG(NULL, &cc->flashdata) & SFLASH_ST_WIP; ++ case SFLASH_AT: ++ /* Check for Atmel Ready bit */ ++ sflash_cmd(cc, SFLASH_AT_STATUS); ++ return !(R_REG(NULL, &cc->flashdata) & SFLASH_AT_READY); ++ } + -+obj-m := $(O_TARGET) ++ return 0; ++} + -+include $(TOPDIR)/Rules.make -diff -Naur linux.old/drivers/net/wl2/compat.c linux.dev/drivers/net/wl2/compat.c ---- linux.old/drivers/net/wl2/compat.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl2/compat.c 2006-04-06 17:08:21.000000000 +0200 -@@ -0,0 +1,376 @@ -+/* -+ * Misc useful OS-independent routines. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ ++/* Write len bytes starting at offset into buf. Returns number of bytes ++ * written. Caller should poll for completion. + */ -+ -+#include -+#ifdef BCMDRIVER -+#include -+#include -+#include -+#else -+#include -+#include -+#endif -+#include "pktq.h" -+#include -+#include -+#include -+ -+#ifdef BCMDRIVER -+/* copy a pkt buffer chain into a buffer */ -+uint -+pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++int ++sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf) +{ -+ uint n, ret = 0; -+ -+ if (len < 0) -+ len = 4096; /* "infinite" */ -+ -+ /* skip 'offset' bytes */ -+ for (; p && offset; p = PKTNEXT(osh, p)) { -+ if (offset < (uint)PKTLEN(osh, p)) -+ break; -+ offset -= PKTLEN(osh, p); -+ } ++ struct sflash *sfl; ++ int ret = 0; ++ bool is4712b0; ++ uint32 page, byte, mask; + -+ if (!p) ++ if (!len) + return 0; + -+ /* copy the data */ -+ for (; p && len; p = PKTNEXT(osh, p)) { -+ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); -+ bcopy(PKTDATA(osh, p) + offset, buf, n); -+ buf += n; -+ len -= n; -+ ret += n; -+ offset = 0; ++ if ((offset + len) > sflash.size) ++ return -22; ++ ++ sfl = &sflash; ++ switch (sfl->type) { ++ case SFLASH_ST: ++ mask = R_REG(NULL, &cc->chipid); ++ is4712b0 = (((mask & CID_ID_MASK) == BCM4712_CHIP_ID) && ++ ((mask & CID_REV_MASK) == (3 << CID_REV_SHIFT))); ++ /* Enable writes */ ++ sflash_cmd(cc, SFLASH_ST_WREN); ++ if (is4712b0) { ++ mask = 1 << 14; ++ W_REG(NULL, &cc->flashaddress, offset); ++ W_REG(NULL, &cc->flashdata, *buf++); ++ /* Set chip select */ ++ OR_REG(NULL, &cc->gpioout, mask); ++ /* Issue a page program with the first byte */ ++ sflash_cmd(cc, SFLASH_ST_PP); ++ ret = 1; ++ offset++; ++ len--; ++ while (len > 0) { ++ if ((offset & 255) == 0) { ++ /* Page boundary, drop cs and return */ ++ AND_REG(NULL, &cc->gpioout, ~mask); ++ if (!sflash_poll(cc, offset)) { ++ /* Flash rejected command */ ++ return -11; ++ } ++ return ret; ++ } else { ++ /* Write single byte */ ++ sflash_cmd(cc, *buf++); ++ } ++ ret++; ++ offset++; ++ len--; ++ } ++ /* All done, drop cs if needed */ ++ if ((offset & 255) != 1) { ++ /* Drop cs */ ++ AND_REG(NULL, &cc->gpioout, ~mask); ++ if (!sflash_poll(cc, offset)) { ++ /* Flash rejected command */ ++ return -12; ++ } ++ } ++ } else { ++ ret = 1; ++ W_REG(NULL, &cc->flashaddress, offset); ++ W_REG(NULL, &cc->flashdata, *buf); ++ /* Page program */ ++ sflash_cmd(cc, SFLASH_ST_PP); ++ } ++ break; ++ case SFLASH_AT: ++ mask = sfl->blocksize - 1; ++ page = (offset & ~mask) << 1; ++ byte = offset & mask; ++ /* Read main memory page into buffer 1 */ ++ if (byte || (len < sfl->blocksize)) { ++ W_REG(NULL, &cc->flashaddress, page); ++ sflash_cmd(cc, SFLASH_AT_BUF1_LOAD); ++ /* 250 us for AT45DB321B */ ++ SPINWAIT(sflash_poll(cc, offset), 1000); ++ ASSERT(!sflash_poll(cc, offset)); ++ } ++ /* Write into buffer 1 */ ++ for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) { ++ W_REG(NULL, &cc->flashaddress, byte++); ++ W_REG(NULL, &cc->flashdata, *buf++); ++ sflash_cmd(cc, SFLASH_AT_BUF1_WRITE); ++ } ++ /* Write buffer 1 into main memory page */ ++ W_REG(NULL, &cc->flashaddress, page); ++ sflash_cmd(cc, SFLASH_AT_BUF1_PROGRAM); ++ break; + } + + return ret; +} + -+/* return total length of buffer chain */ -+uint -+pkttotlen(osl_t *osh, void *p) -+{ -+ uint total; -+ -+ total = 0; -+ for (; p; p = PKTNEXT(osh, p)) -+ total += PKTLEN(osh, p); -+ return (total); -+} -+ -+/* -+ * osl multiple-precedence packet queue -+ * hi_prec is always >= the number of the highest non-empty queue ++/* Erase a region. Returns number of bytes scheduled for erasure. ++ * Caller should poll for completion. + */ -+ -+void * -+pktq_penq(struct pktq *pq, int prec, void *p) ++int ++sflash_erase(chipcregs_t *cc, uint offset) +{ -+ struct pktq_prec *q; -+ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ -+ -+ ASSERT(!pktq_full(pq)); -+ ASSERT(!pktq_pfull(pq, prec)); -+ -+ q = &pq->q[prec]; -+ -+ if (q->head) -+ PKTSETLINK(q->tail, p); -+ else -+ q->head = p; -+ -+ q->tail = p; -+ q->len++; ++ struct sflash *sfl; + -+ if (pq->hi_prec < prec) -+ pq->hi_prec = (uint8)prec; ++ if (offset >= sflash.size) ++ return -22; + -+ pq->len++; ++ sfl = &sflash; ++ switch (sfl->type) { ++ case SFLASH_ST: ++ sflash_cmd(cc, SFLASH_ST_WREN); ++ W_REG(NULL, &cc->flashaddress, offset); ++ sflash_cmd(cc, SFLASH_ST_SE); ++ return sfl->blocksize; ++ case SFLASH_AT: ++ W_REG(NULL, &cc->flashaddress, offset << 1); ++ sflash_cmd(cc, SFLASH_AT_PAGE_ERASE); ++ return sfl->blocksize; ++ } + -+ return p; ++ return 0; +} + -+void * -+pktq_penq_head(struct pktq *pq, int prec, void *p) ++/* ++ * writes the appropriate range of flash, a NULL buf simply erases ++ * the region of flash ++ */ ++int ++sflash_commit(chipcregs_t *cc, uint offset, uint len, const uchar *buf) +{ -+ struct pktq_prec *q; -+ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ -+ -+ ASSERT(!pktq_full(pq)); -+ ASSERT(!pktq_pfull(pq, prec)); -+ -+ q = &pq->q[prec]; ++ struct sflash *sfl; ++ uchar *block = NULL, *cur_ptr, *blk_ptr; ++ uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder; ++ uint blk_offset, blk_len, copied; ++ int bytes, ret = 0; + -+ if (q->head) -+ PKTSETLINK(p, q->head); -+ else -+ q->tail = p; ++ /* Check address range */ ++ if (len <= 0) ++ return 0; + -+ q->head = p; -+ q->len++; ++ sfl = &sflash; ++ if ((offset + len) > sfl->size) ++ return -1; + -+ if (pq->hi_prec < prec) -+ pq->hi_prec = (uint8)prec; ++ blocksize = sfl->blocksize; ++ mask = blocksize - 1; + -+ pq->len++; ++ /* Allocate a block of mem */ ++ if (!(block = MALLOC(NULL, blocksize))) ++ return -1; + -+ return p; -+} ++ while (len) { ++ /* Align offset */ ++ cur_offset = offset & ~mask; ++ cur_length = blocksize; ++ cur_ptr = block; + -+void * -+pktq_pdeq(struct pktq *pq, int prec) -+{ -+ struct pktq_prec *q; -+ void *p; ++ remainder = blocksize - (offset & mask); ++ if (len < remainder) ++ cur_retlen = len; ++ else ++ cur_retlen = remainder; + -+ ASSERT(prec >= 0 && prec < pq->num_prec); ++ /* buf == NULL means erase only */ ++ if (buf) { ++ /* Copy existing data into holding block if necessary */ ++ if ((offset & mask) || (len < blocksize)) { ++ blk_offset = cur_offset; ++ blk_len = cur_length; ++ blk_ptr = cur_ptr; + -+ q = &pq->q[prec]; ++ /* Copy entire block */ ++ while (blk_len) { ++ copied = sflash_read(cc, blk_offset, blk_len, blk_ptr); ++ blk_offset += copied; ++ blk_len -= copied; ++ blk_ptr += copied; ++ } ++ } + -+ if ((p = q->head) == NULL) -+ return NULL; ++ /* Copy input data into holding block */ ++ memcpy(cur_ptr + (offset & mask), buf, cur_retlen); ++ } + -+ if ((q->head = PKTLINK(p)) == NULL) -+ q->tail = NULL; ++ /* Erase block */ ++ if ((ret = sflash_erase(cc, (uint) cur_offset)) < 0) ++ goto done; ++ while (sflash_poll(cc, (uint) cur_offset)); + -+ q->len--; ++ /* buf == NULL means erase only */ ++ if (!buf) { ++ offset += cur_retlen; ++ len -= cur_retlen; ++ continue; ++ } + -+ pq->len--; ++ /* Write holding block */ ++ while (cur_length > 0) { ++ if ((bytes = sflash_write(cc, ++ (uint) cur_offset, ++ (uint) cur_length, ++ (uchar *) cur_ptr)) < 0) { ++ ret = bytes; ++ goto done; ++ } ++ while (sflash_poll(cc, (uint) cur_offset)); ++ cur_offset += bytes; ++ cur_length -= bytes; ++ cur_ptr += bytes; ++ } + -+ PKTSETLINK(p, NULL); ++ offset += cur_retlen; ++ len -= cur_retlen; ++ buf += cur_retlen; ++ } + -+ return p; ++ ret = len; ++done: ++ if (block) ++ MFREE(NULL, block, blocksize); ++ return ret; +} +diff -urN linux.old/arch/mips/bcm947xx/time.c linux.dev/arch/mips/bcm947xx/time.c +--- linux.old/arch/mips/bcm947xx/time.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/bcm947xx/time.c 2006-04-28 00:45:40.000000000 +0200 +@@ -0,0 +1,119 @@ ++/* ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: time.c,v 1.1.1.10 2006/02/27 03:42:55 honor Exp $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+void * -+pktq_pdeq_tail(struct pktq *pq, int prec) -+{ -+ struct pktq_prec *q; -+ void *p, *prev; -+ -+ ASSERT(prec >= 0 && prec < pq->num_prec); -+ -+ q = &pq->q[prec]; -+ -+ if ((p = q->head) == NULL) -+ return NULL; -+ -+ for (prev = NULL; p != q->tail; p = PKTLINK(p)) -+ prev = p; -+ -+ if (prev) -+ PKTSETLINK(prev, NULL); -+ else -+ q->head = NULL; ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ q->tail = prev; -+ q->len--; ++/* Global SB handle */ ++extern void *bcm947xx_sbh; ++extern spinlock_t bcm947xx_sbh_lock; + -+ pq->len--; ++/* Convenience */ ++#define sbh bcm947xx_sbh ++#define sbh_lock bcm947xx_sbh_lock + -+ return p; -+} ++extern int panic_timeout; ++static int watchdog = 0; ++static u8 *mcr = NULL; + -+void -+pktq_init(struct pktq *pq, int num_prec, int max) ++void __init ++bcm947xx_time_init(void) +{ -+ int prec; -+ -+ ASSERT(num_prec >= 0 && num_prec <= PKTQ_MAX_PREC); -+ -+ bzero(pq, sizeof (*pq)); -+ -+ pq->num_prec = (uint16)num_prec; ++ unsigned int hz; ++ extifregs_t *eir; + -+ pq->max = (uint16)max; ++ /* ++ * Use deterministic values for initial counter interrupt ++ * so that calibrate delay avoids encountering a counter wrap. ++ */ ++ write_c0_count(0); ++ write_c0_compare(0xffff); + -+ for (prec = 0; prec < num_prec; prec++) -+ pq->q[prec].max = pq->max; -+} ++ if (!(hz = sb_cpu_clock(sbh))) ++ hz = 100000000; + -+void * -+pktq_deq(struct pktq *pq, int *prec_out) -+{ -+ struct pktq_prec *q; -+ void *p; -+ int prec; ++ printk("CPU: BCM%04x rev %d at %d MHz\n", sb_chip(sbh), sb_chiprev(sbh), ++ (hz + 500000) / 1000000); + -+ if (pq->len == 0) -+ return NULL; ++ /* Set MIPS counter frequency for fixed_rate_gettimeoffset() */ ++ mips_hpt_frequency = hz / 2; + -+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) -+ pq->hi_prec--; ++ /* Set watchdog interval in ms */ ++ watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0); + -+ q = &pq->q[prec]; ++ /* Please set the watchdog to 3 sec if it is less than 3 but not equal to 0 */ ++ if (watchdog > 0) { ++ if (watchdog < 3000) ++ watchdog = 3000; ++ } + -+ if ((p = q->head) == NULL) -+ return NULL; ++ /* Set panic timeout in seconds */ ++ panic_timeout = watchdog / 1000; + -+ if ((q->head = PKTLINK(p)) == NULL) -+ q->tail = NULL; ++ /* Setup blink */ ++ if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) { ++ sbconfig_t *sb = (sbconfig_t *)((unsigned int) eir + SBCONFIGOFF); ++ unsigned long base = EXTIF_CFGIF_BASE(sb_base(readl(&sb->sbadmatch1))); ++ mcr = (u8 *) ioremap_nocache(base + UART_MCR, 1); ++ } ++} + -+ q->len--; ++static void ++bcm947xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ /* Generic MIPS timer code */ ++ timer_interrupt(irq, dev_id, regs); + -+ if (prec_out) -+ *prec_out = prec; ++ /* Set the watchdog timer to reset after the specified number of ms */ ++ if (watchdog > 0) ++ sb_watchdog(sbh, WATCHDOG_CLOCK / 1000 * watchdog); + -+ pq->len--; ++#ifdef CONFIG_HWSIM ++ (*((int *)0xa0000f1c))++; ++#else ++ /* Blink one of the LEDs in the external UART */ ++ if (mcr && !(jiffies % (HZ/2))) ++ writeb(readb(mcr) ^ UART_MCR_OUT2, mcr); ++#endif ++} + -+ PKTSETLINK(p, NULL); ++static struct irqaction bcm947xx_timer_irqaction = { ++ bcm947xx_timer_interrupt, ++ SA_INTERRUPT, ++ 0, ++ "timer", ++ NULL, ++ NULL ++}; + -+ return p; ++void __init ++bcm947xx_timer_setup(struct irqaction *irq) ++{ ++ /* Enable the timer interrupt */ ++ setup_irq(7, &bcm947xx_timer_irqaction); +} +diff -urN linux.old/arch/mips/config-shared.in linux.dev/arch/mips/config-shared.in +--- linux.old/arch/mips/config-shared.in 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/arch/mips/config-shared.in 2006-04-27 19:24:19.000000000 +0200 +@@ -208,6 +208,14 @@ + fi + define_bool CONFIG_MIPS_RTC y + fi ++dep_bool 'Support for Broadcom MIPS-based boards' CONFIG_MIPS_BRCM $CONFIG_EXPERIMENTAL ++dep_bool 'Support for Broadcom BCM947XX' CONFIG_BCM947XX $CONFIG_MIPS_BRCM ++if [ "$CONFIG_BCM947XX" = "y" ] ; then ++ bool ' Support for Broadcom BCM4710' CONFIG_BCM4710 ++ bool ' Support for Broadcom BCM4310' CONFIG_BCM4310 ++ bool ' Support for Broadcom BCM4704' CONFIG_BCM4704 ++ bool ' Support for Broadcom BCM5365' CONFIG_BCM5365 ++fi + bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI + bool 'Support for TANBAC TB0226 (Mbase)' CONFIG_TANBAC_TB0226 + bool 'Support for TANBAC TB0229 (VR4131DIMM)' CONFIG_TANBAC_TB0229 +@@ -229,6 +237,11 @@ + define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n + + # ++# Provide an option for a default kernel command line ++# ++string 'Default kernel command string' CONFIG_CMDLINE "" + -+void * -+pktq_deq_tail(struct pktq *pq, int *prec_out) ++# + # Select some configuration options automatically based on user selections. + # + if [ "$CONFIG_ACER_PICA_61" = "y" ]; then +@@ -554,6 +567,13 @@ + define_bool CONFIG_SWAP_IO_SPACE_L y + define_bool CONFIG_BOOT_ELF32 y + fi ++if [ "$CONFIG_BCM947XX" = "y" ] ; then ++ define_bool CONFIG_PCI y ++ define_bool CONFIG_NONCOHERENT_IO y ++ define_bool CONFIG_NEW_TIME_C y ++ define_bool CONFIG_NEW_IRQ y ++ define_bool CONFIG_HND y ++fi + if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then + define_bool CONFIG_ARC32 y + define_bool CONFIG_ARC_MEMORY y +@@ -1042,7 +1062,11 @@ + + bool 'Are you using a crosscompiler' CONFIG_CROSSCOMPILE + bool 'Enable run-time debugging' CONFIG_RUNTIME_DEBUG +-bool 'Remote GDB kernel debugging' CONFIG_KGDB ++if [ "$CONFIG_BCM947XX" = "y" ] ; then ++ bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG ++else ++ bool 'Remote GDB kernel debugging' CONFIG_KGDB ++fi + dep_bool ' Console output to GDB' CONFIG_GDB_CONSOLE $CONFIG_KGDB + if [ "$CONFIG_KGDB" = "y" ]; then + define_bool CONFIG_DEBUG_INFO y +diff -urN linux.old/arch/mips/kernel/cpu-probe.c linux.dev/arch/mips/kernel/cpu-probe.c +--- linux.old/arch/mips/kernel/cpu-probe.c 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/arch/mips/kernel/cpu-probe.c 2006-04-27 19:24:19.000000000 +0200 +@@ -162,7 +162,7 @@ + + static inline void cpu_probe_legacy(struct cpuinfo_mips *c) + { +- switch (c->processor_id & 0xff00) { ++ switch (c->processor_id & PRID_IMP_MASK) { + case PRID_IMP_R2000: + c->cputype = CPU_R2000; + c->isa_level = MIPS_CPU_ISA_I; +@@ -172,7 +172,7 @@ + c->tlbsize = 64; + break; + case PRID_IMP_R3000: +- if ((c->processor_id & 0xff) == PRID_REV_R3000A) ++ if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) + if (cpu_has_confreg()) + c->cputype = CPU_R3081E; + else +@@ -187,12 +187,12 @@ + break; + case PRID_IMP_R4000: + if (read_c0_config() & CONF_SC) { +- if ((c->processor_id & 0xff) >= PRID_REV_R4400) ++ if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_R4400) + c->cputype = CPU_R4400PC; + else + c->cputype = CPU_R4000PC; + } else { +- if ((c->processor_id & 0xff) >= PRID_REV_R4400) ++ if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_R4400) + c->cputype = CPU_R4400SC; + else + c->cputype = CPU_R4000SC; +@@ -438,7 +438,7 @@ + static inline void cpu_probe_mips(struct cpuinfo_mips *c) + { + decode_config1(c); +- switch (c->processor_id & 0xff00) { ++ switch (c->processor_id & PRID_IMP_MASK) { + case PRID_IMP_4KC: + c->cputype = CPU_4KC; + c->isa_level = MIPS_CPU_ISA_M32; +@@ -479,10 +479,10 @@ + { + decode_config1(c); + c->options |= MIPS_CPU_PREFETCH; +- switch (c->processor_id & 0xff00) { ++ switch (c->processor_id & PRID_IMP_MASK) { + case PRID_IMP_AU1_REV1: + case PRID_IMP_AU1_REV2: +- switch ((c->processor_id >> 24) & 0xff) { ++ switch ((c->processor_id >> 24) & PRID_REV_MASK) { + case 0: + c->cputype = CPU_AU1000; + break; +@@ -510,10 +510,34 @@ + } + } + ++static inline void cpu_probe_broadcom(struct cpuinfo_mips *c) +{ -+ struct pktq_prec *q; -+ void *p, *prev; -+ int prec; ++ decode_config1(c); ++ c->options |= MIPS_CPU_PREFETCH; ++ switch (c->processor_id & PRID_IMP_MASK) { ++ case PRID_IMP_BCM4710: ++ c->cputype = CPU_BCM4710; ++ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | ++ MIPS_CPU_4KTLB | MIPS_CPU_COUNTER; ++ c->scache.flags = MIPS_CACHE_NOT_PRESENT; ++ break; ++ case PRID_IMP_4KC: ++ case PRID_IMP_BCM3302: ++ c->cputype = CPU_BCM3302; ++ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | ++ MIPS_CPU_4KTLB | MIPS_CPU_COUNTER; ++ c->scache.flags = MIPS_CACHE_NOT_PRESENT; ++ break; ++ default: ++ c->cputype = CPU_UNKNOWN; ++ break; ++ } ++} ++ + static inline void cpu_probe_sibyte(struct cpuinfo_mips *c) + { + decode_config1(c); +- switch (c->processor_id & 0xff00) { ++ switch (c->processor_id & PRID_IMP_MASK) { + case PRID_IMP_SB1: + c->cputype = CPU_SB1; + c->isa_level = MIPS_CPU_ISA_M64; +@@ -535,7 +559,7 @@ + static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c) + { + decode_config1(c); +- switch (c->processor_id & 0xff00) { ++ switch (c->processor_id & PRID_IMP_MASK) { + case PRID_IMP_SR71000: + c->cputype = CPU_SR71000; + c->isa_level = MIPS_CPU_ISA_M64; +@@ -560,7 +584,7 @@ + c->cputype = CPU_UNKNOWN; + + c->processor_id = read_c0_prid(); +- switch (c->processor_id & 0xff0000) { ++ switch (c->processor_id & PRID_COMP_MASK) { + + case PRID_COMP_LEGACY: + cpu_probe_legacy(c); +@@ -571,6 +595,9 @@ + case PRID_COMP_ALCHEMY: + cpu_probe_alchemy(c); + break; ++ case PRID_COMP_BROADCOM: ++ cpu_probe_broadcom(c); ++ break; + case PRID_COMP_SIBYTE: + cpu_probe_sibyte(c); + break; +diff -urN linux.old/arch/mips/kernel/head.S linux.dev/arch/mips/kernel/head.S +--- linux.old/arch/mips/kernel/head.S 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/arch/mips/kernel/head.S 2006-04-27 19:24:19.000000000 +0200 +@@ -28,12 +28,20 @@ + #include + #include + ++#ifdef CONFIG_BCM4710 ++#undef eret ++#define eret nop; nop; eret ++#endif + -+ if (pq->len == 0) -+ return NULL; + .text ++ j kernel_entry ++ nop + -+ for (prec = 0; prec < pq->hi_prec; prec++) -+ if (pq->q[prec].head) + /* + * Reserved space for exception handlers. + * Necessary for machines which link their kernels at KSEG0. + */ +- .fill 0x400 ++ .fill 0x3f4 + + /* The following two symbols are used for kernel profiling. */ + EXPORT(stext) +diff -urN linux.old/arch/mips/kernel/proc.c linux.dev/arch/mips/kernel/proc.c +--- linux.old/arch/mips/kernel/proc.c 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/arch/mips/kernel/proc.c 2006-04-27 19:24:19.000000000 +0200 +@@ -78,9 +78,10 @@ + [CPU_AU1550] "Au1550", + [CPU_24K] "MIPS 24K", + [CPU_AU1200] "Au1200", ++ [CPU_BCM4710] "BCM4710", ++ [CPU_BCM3302] "BCM3302", + }; + +- + static int show_cpuinfo(struct seq_file *m, void *v) + { + unsigned int version = current_cpu_data.processor_id; +diff -urN linux.old/arch/mips/kernel/setup.c linux.dev/arch/mips/kernel/setup.c +--- linux.old/arch/mips/kernel/setup.c 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/arch/mips/kernel/setup.c 2006-04-27 19:24:19.000000000 +0200 +@@ -493,6 +493,7 @@ + void swarm_setup(void); + void hp_setup(void); + void au1x00_setup(void); ++ void brcm_setup(void); + void frame_info_init(void); + + frame_info_init(); +@@ -691,6 +692,11 @@ + pmc_yosemite_setup(); + break; + #endif ++#if defined(CONFIG_BCM4710) || defined(CONFIG_BCM4310) ++ case MACH_GROUP_BRCM: ++ brcm_setup(); + break; ++#endif + default: + panic("Unsupported architecture"); + } +diff -urN linux.old/arch/mips/kernel/traps.c linux.dev/arch/mips/kernel/traps.c +--- linux.old/arch/mips/kernel/traps.c 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/arch/mips/kernel/traps.c 2006-04-27 19:24:19.000000000 +0200 +@@ -920,6 +920,7 @@ + void __init trap_init(void) + { + extern char except_vec1_generic; ++ extern char except_vec2_generic; + extern char except_vec3_generic, except_vec3_r4000; + extern char except_vec_ejtag_debug; + extern char except_vec4; +@@ -927,6 +928,7 @@ + + /* Copy the generic exception handler code to it's final destination. */ + memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80); ++ memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); + + /* + * Setup default vectors +@@ -985,6 +987,12 @@ + set_except_vector(13, handle_tr); + set_except_vector(22, handle_mdmx); + ++ if (current_cpu_data.cputype == CPU_SB1) { ++ /* Enable timer interrupt and scd mapped interrupt */ ++ clear_c0_status(0xf000); ++ set_c0_status(0xc00); ++ } + -+ q = &pq->q[prec]; -+ -+ if ((p = q->head) == NULL) -+ return NULL; -+ -+ for (prev = NULL; p != q->tail; p = PKTLINK(p)) -+ prev = p; -+ -+ if (prev) -+ PKTSETLINK(prev, NULL); -+ else -+ q->head = NULL; -+ -+ q->tail = prev; -+ q->len--; -+ -+ if (prec_out) -+ *prec_out = prec; -+ -+ pq->len--; -+ -+ PKTSETLINK(p, NULL); -+ -+ return p; -+} + if (cpu_has_fpu && !cpu_has_nofpuex) + set_except_vector(15, handle_fpe); + +diff -urN linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c +--- linux.old/arch/mips/mm/c-r4k.c 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/arch/mips/mm/c-r4k.c 2006-04-27 19:24:19.000000000 +0200 +@@ -1166,3 +1166,47 @@ + build_clear_page(); + build_copy_page(); + } + -+void * -+pktq_peek(struct pktq *pq, int *prec_out) ++#ifdef CONFIG_BCM4704 ++static void __init mips32_icache_fill(unsigned long addr, uint nbytes) +{ -+ void *p; -+ int prec; -+ -+ if (pq->len == 0) -+ return NULL; -+ -+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) -+ pq->hi_prec--; -+ -+ if ((p = pq->q[prec].head) == NULL) -+ return NULL; -+ -+ if (prec_out) -+ *prec_out = prec; -+ -+ return p; ++ unsigned long ic_lsize = current_cpu_data.icache.linesz; ++ int i; ++ for (i = 0; i < nbytes; i += ic_lsize) ++ fill_icache_line((addr + i)); +} + -+void * -+pktq_peek_tail(struct pktq *pq, int *prec_out) ++/* ++ * This must be run from the cache on 4704A0 ++ * so there are no mips core BIU ops in progress ++ * when the PFC is enabled. ++ */ ++#define PFC_CR0 0xff400000 /* control reg 0 */ ++#define PFC_CR1 0xff400004 /* control reg 1 */ ++static void __init enable_pfc(u32 mode) +{ -+ void *p; -+ int prec; -+ -+ if (pq->len == 0) -+ return NULL; -+ -+ for (prec = 0; prec < pq->hi_prec; prec++) -+ if (pq->q[prec].head) -+ break; -+ -+ if ((p = pq->q[prec].tail) == NULL) -+ return NULL; -+ -+ if (prec_out) -+ *prec_out = prec; ++ /* write range */ ++ *(volatile u32 *)PFC_CR1 = 0xffff0000; + -+ return p; ++ /* enable */ ++ *(volatile u32 *)PFC_CR0 = mode; +} ++#endif + -+int -+pktq_mlen(struct pktq *pq, uint prec_bmp) -+{ -+ int prec, len; + -+ len = 0; ++void check_enable_mips_pfc(int val) ++{ + -+ for (prec = 0; prec <= pq->hi_prec; prec++) -+ if (prec_bmp & (1 << prec)) -+ len += pq->q[prec].len; ++#ifdef CONFIG_BCM4704 ++ struct cpuinfo_mips *c = ¤t_cpu_data; + -+ return len; ++ /* enable prefetch cache */ ++ if (((c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) == PRID_IMP_BCM3302) ++ && (read_c0_diag() & (1 << 29))) { ++ mips32_icache_fill((unsigned long) &enable_pfc, 64); ++ enable_pfc(val); ++ } ++#endif +} + -+void * -+pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) -+{ -+ struct pktq_prec *q; -+ void *p; -+ int prec; -+ -+ if (pq->len == 0) -+ return NULL; + -+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) -+ pq->hi_prec--; +diff -urN linux.old/arch/mips/pci/Makefile linux.dev/arch/mips/pci/Makefile +--- linux.old/arch/mips/pci/Makefile 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/arch/mips/pci/Makefile 2006-04-27 19:24:19.000000000 +0200 +@@ -13,7 +13,9 @@ + obj-$(CONFIG_MIPS_MSC) += ops-msc.o + obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o + obj-$(CONFIG_SNI_RM200_PCI) += ops-sni.o ++ifndef CONFIG_BCM947XX + obj-y += pci.o ++endif + obj-$(CONFIG_PCI_AUTO) += pci_auto.o + + include $(TOPDIR)/Rules.make +diff -urN linux.old/drivers/char/serial.c linux.dev/drivers/char/serial.c +--- linux.old/drivers/char/serial.c 2006-04-27 18:04:37.000000000 +0200 ++++ linux.dev/drivers/char/serial.c 2006-04-27 19:24:19.000000000 +0200 +@@ -444,6 +444,10 @@ + return inb(info->port+1); + #endif + case SERIAL_IO_MEM: ++#ifdef CONFIG_BCM4310 ++ readb((unsigned long) info->iomem_base + ++ (UART_SCR<iomem_reg_shift)); ++#endif + return readb((unsigned long) info->iomem_base + + (offset<iomem_reg_shift)); + default: +@@ -464,6 +468,9 @@ + case SERIAL_IO_MEM: + writeb(value, (unsigned long) info->iomem_base + + (offset<iomem_reg_shift)); ++#ifdef CONFIG_BCM4704 ++ *((volatile unsigned int *) KSEG1ADDR(0x18000000)); ++#endif + break; + default: + outb(value, info->port+offset); +@@ -1728,7 +1735,7 @@ + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) +- quot = baud_base / baud; ++ quot = (baud_base + (baud / 2)) / baud; + } + /* If the quotient is zero refuse the change */ + if (!quot && old_termios) { +@@ -1745,12 +1752,12 @@ + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) +- quot = baud_base / baud; ++ quot = (baud_base + (baud / 2)) / baud; + } + } + /* As a last resort, if the quotient is zero, default to 9600 bps */ + if (!quot) +- quot = baud_base / 9600; ++ quot = (baud_base + 4800) / 9600; + /* + * Work around a bug in the Oxford Semiconductor 952 rev B + * chip which causes it to seriously miscalculate baud rates +@@ -5994,6 +6001,13 @@ + * Divisor, bytesize and parity + */ + state = rs_table + co->index; ++ /* ++ * Safe guard: state structure must have been initialized ++ */ ++ if (state->iomem_base == NULL) { ++ printk("!unable to setup serial console!\n"); ++ return -1; ++ } + if (doflow) + state->flags |= ASYNC_CONS_FLOW; + info = &async_sercons; +@@ -6007,7 +6021,7 @@ + info->io_type = state->io_type; + info->iomem_base = state->iomem_base; + info->iomem_reg_shift = state->iomem_reg_shift; +- quot = state->baud_base / baud; ++ quot = (state->baud_base + (baud / 2)) / baud; + cval = cflag & (CSIZE | CSTOPB); + #if defined(__powerpc__) || defined(__alpha__) + cval >>= 8; +diff -urN linux.old/drivers/net/Config.in linux.dev/drivers/net/Config.in +--- linux.old/drivers/net/Config.in 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/drivers/net/Config.in 2006-04-27 19:24:19.000000000 +0200 +@@ -2,6 +2,8 @@ + # Network device configuration + # + ++tristate 'Broadcom Home Network Division' CONFIG_HND $CONFIG_PCI + -+ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) -+ if (prec-- == 0) -+ return NULL; + source drivers/net/arcnet/Config.in + + tristate 'Dummy net driver support' CONFIG_DUMMY +diff -urN linux.old/drivers/net/Makefile linux.dev/drivers/net/Makefile +--- linux.old/drivers/net/Makefile 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/drivers/net/Makefile 2006-05-04 01:41:03.000000000 +0200 +@@ -3,6 +3,8 @@ + # Makefile for the Linux network (ethercard) device drivers. + # + ++EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include + -+ q = &pq->q[prec]; + obj-y := + obj-m := + obj-n := +@@ -39,6 +41,7 @@ + obj-$(CONFIG_ISDN) += slhc.o + endif + ++subdir-$(CONFIG_WL) += wl + subdir-$(CONFIG_NET_PCMCIA) += pcmcia + subdir-$(CONFIG_NET_WIRELESS) += wireless + subdir-$(CONFIG_TULIP) += tulip +diff -urN linux.old/drivers/net/wireless/Config.in linux.dev/drivers/net/wireless/Config.in +--- linux.old/drivers/net/wireless/Config.in 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/drivers/net/wireless/Config.in 2006-05-04 01:42:48.000000000 +0200 +@@ -13,6 +13,7 @@ + fi + + if [ "$CONFIG_PCI" = "y" ]; then ++ dep_tristate ' Proprietary Broadcom BCM43xx 802.11 Wireless support' CONFIG_WL + dep_tristate ' Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)' CONFIG_PLX_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL + dep_tristate ' Hermes in TMD7160/NCP130 based PCI adaptor support (Pheecom WL-PCI etc.) (EXPERIMENTAL)' CONFIG_TMD_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL + dep_tristate ' Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)' CONFIG_PCI_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL +diff -urN linux.old/drivers/net/wl/patchtable.pl linux.dev/drivers/net/wl/patchtable.pl +--- linux.old/drivers/net/wl/patchtable.pl 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/patchtable.pl 2006-04-28 01:33:52.000000000 +0200 +@@ -0,0 +1,54 @@ ++#!/usr/bin/perl ++use strict; ++ ++my $TABLE = pack("V", 0xbadc0ded); ++my $TABLE_SIZE = 512; ++my $SLT1 = "\x01\x00\x00\x00"; ++my $SLT2 = "\x02\x00\x00\x00"; ++my $ACKW = "\x03\x00\x00\x00"; ++my $PTABLE_END = "\xff\xff\xff\xff"; ++ ++my $addr = ""; ++my $opcode = ""; ++my $function = ""; ++ ++sub add_entry { ++ my $key = shift; ++ my $value = shift; ++ my $default = shift; ++ ++ $TABLE .= $key; ++ $TABLE .= pack("V", $value); ++ $TABLE .= pack("V", $default); ++} ++ ++while (<>) { ++ $addr = $opcode = ""; ++ /^\w{8}\s*<(.*)>:$/ and $function = $1; ++ /^\s*(\w+):\s*(\w{8})\s*/ and do { ++ $addr = $1; ++ $opcode = $2; ++ }; + -+ if ((p = q->head) == NULL) -+ return NULL; ++ ($function eq 'wlc_update_slot_timing') and do { ++ # li a2,9 -- short slot time ++ ($opcode eq '24060009') and add_entry($SLT1, hex($addr), hex($opcode)); ++ # li v0,519 -- 510 + short slot time ++ ($opcode eq '24020207') and add_entry($SLT2, hex($addr), hex($opcode)); ++ ++ # li a2,20 -- long slot time ++ ($opcode eq '24060014') and add_entry($SLT1, hex($addr), hex($opcode)); ++ # li v0,530 -- 510 + long slot time ++ ($opcode eq '24020212') and add_entry($SLT2, hex($addr), hex($opcode)); ++ }; ++ ($function eq 'wlc_d11hdrs') and do { ++ # ori s6,s6,0x1 -- ack flag (new) ++ ($opcode eq '36d60001') and add_entry($ACKW, hex($addr), hex($opcode)); ++ # ori s3,s3,0x1 -- ack flag (old) ++ ($opcode eq '36730001') and add_entry($ACKW, hex($addr), hex($opcode)); ++ } ++} + -+ if ((q->head = PKTLINK(p)) == NULL) -+ q->tail = NULL; ++$TABLE .= $PTABLE_END; ++$TABLE .= ("\x00" x ($TABLE_SIZE - length($TABLE))); ++print $TABLE; +diff -urN linux.old/drivers/net/wl/Makefile linux.dev/drivers/net/wl/Makefile +--- linux.old/drivers/net/wl/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/Makefile 2006-04-28 01:33:52.000000000 +0200 +@@ -0,0 +1,32 @@ ++# ++# Makefile for the Broadcom wl driver ++# ++# Copyright 2004, Broadcom Corporation ++# All Rights Reserved. ++# ++# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++# ++# $Id: Makefile,v 1.2 2005/03/29 03:32:18 mbm Exp $ + -+ q->len--; ++EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER + -+ if (prec_out) -+ *prec_out = prec; ++O_TARGET := wl_link.o + -+ pq->len--; ++obj-y := wl_mod.o ++obj-y += bcmutils.o hnddma.o linux_osl.o + -+ PKTSETLINK(p, NULL); ++obj-m := $(O_TARGET) + -+ return p; -+} ++wl_mod.o: wl_apsta.o ++ sed -e 's,eth%d,wl%d\x00,g' < $< > $@ + -+#endif ++wl.o: wl_link.o ++ $(OBJDUMP) -d $< | perl patchtable.pl > patchtable.bin ++ cat wl_link.o patchtable.bin > $@ + ++modules: wl.o + -diff -Naur linux.old/drivers/net/wl2/hnddma.c linux.dev/drivers/net/wl2/hnddma.c ---- linux.old/drivers/net/wl2/hnddma.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl2/hnddma.c 2006-04-06 16:32:33.000000000 +0200 -@@ -0,0 +1,1487 @@ ++include $(TOPDIR)/Rules.make +diff -urN linux.old/drivers/net/wl/bcmip.h linux.dev/drivers/net/wl/bcmip.h +--- linux.old/drivers/net/wl/bcmip.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/bcmip.h 2006-04-28 02:11:28.000000000 +0200 +@@ -0,0 +1,101 @@ +/* -+ * Generic Broadcom Home Networking Division (HND) DMA module. -+ * This supports the following chips: BCM42xx, 44xx, 47xx . -+ * -+ * Copyright 2005, Broadcom Corporation ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -18260,2362 +16430,2288 @@ diff -Naur linux.old/drivers/net/wl2/hnddma.c linux.dev/drivers/net/wl2/hnddma.c + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * $Id$ ++ * Fundamental constants relating to IP Protocol ++ * ++ * $Id: bcmip.h,v 1.1.1.3 2006/02/27 03:43:16 honor Exp $ + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct dma_info; /* forward declaration */ -+#define di_t struct dma_info -+ -+#include "sbhnddma.h" -+#include "hnddma.h" -+ -+/* debug/trace */ -+#define DMA_ERROR(args) -+#define DMA_TRACE(args) -+ -+/* default dma message level (if input msg_level pointer is null in dma_attach()) */ -+static uint dma_msg_level = -+ 0; -+ -+#define MAXNAMEL 8 -+ -+/* dma engine software state */ -+typedef struct dma_info { -+ hnddma_t hnddma; /* exported structure */ -+ uint *msg_level; /* message level pointer */ -+ char name[MAXNAMEL]; /* callers name for diag msgs */ -+ -+ void *osh; /* os handle */ -+ sb_t *sbh; /* sb handle */ -+ -+ bool dma64; /* dma64 enabled */ -+ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ -+ -+ dma32regs_t *d32txregs; /* 32 bits dma tx engine registers */ -+ dma32regs_t *d32rxregs; /* 32 bits dma rx engine registers */ -+ dma64regs_t *d64txregs; /* 64 bits dma tx engine registers */ -+ dma64regs_t *d64rxregs; /* 64 bits dma rx engine registers */ -+ -+ uint32 dma64align; /* either 8k or 4k depends on number of dd */ -+ dma32dd_t *txd32; /* pointer to dma32 tx descriptor ring */ -+ dma64dd_t *txd64; /* pointer to dma64 tx descriptor ring */ -+ uint ntxd; /* # tx descriptors tunable */ -+ uint txin; /* index of next descriptor to reclaim */ -+ uint txout; /* index of next descriptor to post */ -+ uint txavail; /* # free tx descriptors */ -+ void **txp; /* pointer to parallel array of pointers to packets */ -+ ulong txdpa; /* physical address of descriptor ring */ -+ uint txdalign; /* #bytes added to alloc'd mem to align txd */ -+ uint txdalloc; /* #bytes allocated for the ring */ -+ -+ dma32dd_t *rxd32; /* pointer to dma32 rx descriptor ring */ -+ dma64dd_t *rxd64; /* pointer to dma64 rx descriptor ring */ -+ uint nrxd; /* # rx descriptors tunable */ -+ uint rxin; /* index of next descriptor to reclaim */ -+ uint rxout; /* index of next descriptor to post */ -+ void **rxp; /* pointer to parallel array of pointers to packets */ -+ ulong rxdpa; /* physical address of descriptor ring */ -+ uint rxdalign; /* #bytes added to alloc'd mem to align rxd */ -+ uint rxdalloc; /* #bytes allocated for the ring */ -+ -+ /* tunables */ -+ uint rxbufsize; /* rx buffer size in bytes */ -+ uint nrxpost; /* # rx buffers to keep posted */ -+ uint rxoffset; /* rxcontrol offset */ -+ uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */ -+ uint ddoffsethigh; /* add to get dma address of descriptor ring, high 32 bits */ -+ uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */ -+ uint dataoffsethigh; /* add to get dma address of data buffer, high 32 bits */ -+} dma_info_t; -+ -+#ifdef BCMDMA64 -+#define DMA64_ENAB(di) ((di)->dma64) -+#else -+#define DMA64_ENAB(di) (0) -+#endif -+ -+/* descriptor bumping macros */ -+#define XXD(x, n) ((x) & ((n) - 1)) -+#define TXD(x) XXD((x), di->ntxd) -+#define RXD(x) XXD((x), di->nrxd) -+#define NEXTTXD(i) TXD(i + 1) -+#define PREVTXD(i) TXD(i - 1) -+#define NEXTRXD(i) RXD(i + 1) -+#define NTXDACTIVE(h, t) TXD(t - h) -+#define NRXDACTIVE(h, t) RXD(t - h) ++#ifndef _bcmip_h_ ++#define _bcmip_h_ + -+/* macros to convert between byte offsets and indexes */ -+#define B2I(bytes, type) ((bytes) / sizeof(type)) -+#define I2B(index, type) ((index) * sizeof(type)) ++/* IPV4 and IPV6 common */ ++#define IP_VER_OFFSET 0x0 /* offset to version field */ ++#define IP_VER_MASK 0xf0 /* version mask */ ++#define IP_VER_SHIFT 4 /* version shift */ ++#define IP_VER_4 4 /* version number for IPV4 */ ++#define IP_VER_6 6 /* version number for IPV6 */ + -+#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ -+#define PCI32ADDR_HIGH_SHIFT 30 ++#define IP_VER(ip_body) \ ++ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) + ++#define IP_PROT_ICMP 0x1 /* ICMP protocol */ ++#define IP_PROT_TCP 0x6 /* TCP protocol */ ++#define IP_PROT_UDP 0x11 /* UDP protocol type */ + -+/* prototypes */ -+static bool dma_isaddrext(dma_info_t *di); -+static bool dma_alloc(dma_info_t *di, uint direction); ++/* IPV4 field offsets */ ++#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ ++#define IPV4_TOS_OFFSET 1 /* type of service offset */ ++#define IPV4_PROT_OFFSET 9 /* protocol type offset */ ++#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */ ++#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */ ++#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */ + -+static bool dma32_alloc(dma_info_t *di, uint direction); -+static void dma32_txreset(dma_info_t *di); -+static void dma32_rxreset(dma_info_t *di); -+static bool dma32_txsuspendedidle(dma_info_t *di); -+static int dma32_txfast(dma_info_t *di, void *p0, uint32 coreflags); -+static void* dma32_getnexttxp(dma_info_t *di, bool forceall); -+static void* dma32_getnextrxp(dma_info_t *di, bool forceall); -+static void dma32_txrotate(di_t *di); -+ -+/* prototype or stubs */ -+#ifdef BCMDMA64 -+static bool dma64_alloc(dma_info_t *di, uint direction); -+static void dma64_txreset(dma_info_t *di); -+static void dma64_rxreset(dma_info_t *di); -+static bool dma64_txsuspendedidle(dma_info_t *di); -+static int dma64_txfast(dma_info_t *di, void *p0, uint32 coreflags); -+static void* dma64_getnexttxp(dma_info_t *di, bool forceall); -+static void* dma64_getnextrxp(dma_info_t *di, bool forceall); -+static void dma64_txrotate(di_t *di); -+#else -+static bool dma64_alloc(dma_info_t *di, uint direction) { return TRUE; } -+static void dma64_txreset(dma_info_t *di) {} -+static void dma64_rxreset(dma_info_t *di) {} -+static bool dma64_txsuspendedidle(dma_info_t *di) { return TRUE;} -+static int dma64_txfast(dma_info_t *di, void *p0, uint32 coreflags) { return 0; } -+static void* dma64_getnexttxp(dma_info_t *di, bool forceall) { return NULL; } -+static void* dma64_getnextrxp(dma_info_t *di, bool forceall) { return NULL; } -+static void dma64_txrotate(di_t *di) { return; } -+#endif ++/* IPV4 field decodes */ ++#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */ ++#define IPV4_VER_SHIFT 4 /* IPV4 version shift */ + ++#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ ++#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) + ++#define IPV4_ADDR_LEN 4 /* IPV4 address length */ + -+void* -+dma_attach(osl_t *osh, char *name, sb_t *sbh, void *dmaregstx, void *dmaregsrx, -+ uint ntxd, uint nrxd, uint rxbufsize, uint nrxpost, uint rxoffset, uint *msg_level) -+{ -+ dma_info_t *di; -+ uint size; ++#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ ++ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) + -+ /* allocate private info structure */ -+ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { -+ return (NULL); -+ } -+ bzero((char*)di, sizeof (dma_info_t)); ++#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */ ++#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */ + -+ di->msg_level = msg_level ? msg_level : &dma_msg_level; ++#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) + -+ if (sbh != NULL) -+ di->dma64 = ((sb_coreflagshi(sbh, 0, 0) & SBTMH_DMA64) == SBTMH_DMA64); ++#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */ ++#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */ + -+#ifndef BCMDMA64 -+ if (di->dma64) { -+ DMA_ERROR(("dma_attach: driver doesn't have the capability to support 64 bits DMA\n")); -+ goto fail; -+ } -+#endif -+ -+ /* check arguments */ -+ ASSERT(ISPOWEROF2(ntxd)); -+ ASSERT(ISPOWEROF2(nrxd)); -+ if (nrxd == 0) -+ ASSERT(dmaregsrx == NULL); -+ if (ntxd == 0) -+ ASSERT(dmaregstx == NULL); ++#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */ ++#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */ ++#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */ + ++#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) + -+ /* init dma reg pointer */ -+ if (di->dma64) { -+ ASSERT(ntxd <= D64MAXDD); -+ ASSERT(nrxd <= D64MAXDD); -+ di->d64txregs = (dma64regs_t *)dmaregstx; -+ di->d64rxregs = (dma64regs_t *)dmaregsrx; -+ -+ di->dma64align = D64RINGALIGN; -+ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) { -+ /* for smaller dd table, HW relax the alignment requirement */ -+ di->dma64align = D64RINGALIGN / 2; -+ } -+ } else { -+ ASSERT(ntxd <= D32MAXDD); -+ ASSERT(nrxd <= D32MAXDD); -+ di->d32txregs = (dma32regs_t *)dmaregstx; -+ di->d32rxregs = (dma32regs_t *)dmaregsrx; -+ } ++#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ + ++/* IPV6 field offsets */ ++#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ ++#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ ++#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */ ++#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */ ++#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */ + -+ /* make a private copy of our callers name */ -+ strncpy(di->name, name, MAXNAMEL); -+ di->name[MAXNAMEL-1] = '\0'; ++/* IPV6 field decodes */ ++#define IPV6_TRAFFIC_CLASS(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ ++ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) + -+ di->osh = osh; -+ di->sbh = sbh; ++#define IPV6_FLOW_LABEL(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ ++ (((uint8 *)(ipv6_body))[2] << 8) | \ ++ (((uint8 *)(ipv6_body))[3])) + -+ /* save tunables */ -+ di->ntxd = ntxd; -+ di->nrxd = nrxd; -+ di->rxbufsize = rxbufsize; -+ di->nrxpost = nrxpost; -+ di->rxoffset = rxoffset; ++#define IPV6_PAYLOAD_LEN(ipv6_body) \ ++ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ ++ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) + -+ /* -+ * figure out the DMA physical address offset for dd and data -+ * for old chips w/o sb, use zero -+ * for new chips w sb, -+ * PCI/PCIE: they map silicon backplace address to zero based memory, need offset -+ * Other bus: use zero -+ * SB_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor -+ */ -+ di->ddoffsetlow = 0; -+ di->dataoffsetlow = 0; -+ if (sbh != NULL) { -+ if (sbh->bustype == PCI_BUS) { /* for pci bus, add offset */ -+ if ((sbh->buscoretype == SB_PCIE) && di->dma64){ -+ di->ddoffsetlow = 0; -+ di->ddoffsethigh = SB_PCIE_DMA_H32; -+ } else { -+ di->ddoffsetlow = SB_PCI_DMA; -+ di->ddoffsethigh = 0; -+ } -+ di->dataoffsetlow = di->ddoffsetlow; -+ di->dataoffsethigh = di->ddoffsethigh; -+ } -+#if defined(__mips__) && defined(IL_BIGENDIAN) -+ /* use sdram swapped region for data buffers but not dma descriptors */ -+ di->dataoffsetlow = di->dataoffsetlow + SB_SDRAM_SWAPPED; -+#endif -+ } ++#define IPV6_NEXT_HDR(ipv6_body) \ ++ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) + -+ di->addrext = dma_isaddrext(di); ++#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) + -+ DMA_TRACE(("%s: dma_attach: osh %p ntxd %d nrxd %d rxbufsize %d nrxpost %d rxoffset %d ddoffset 0x%x dataoffset 0x%x\n", -+ name, osh, ntxd, nrxd, rxbufsize, nrxpost, rxoffset, di->ddoffsetlow, di->dataoffsetlow)); ++#define IPV6_ADDR_LEN 16 /* IPV6 address length */ + -+ /* allocate tx packet pointer vector */ -+ if (ntxd) { -+ size = ntxd * sizeof (void*); -+ if ((di->txp = MALLOC(osh, size)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: out of tx memory, malloced %d bytes\n", di->name, MALLOCED(osh))); -+ goto fail; -+ } -+ bzero((char*)di->txp, size); -+ } ++/* IPV4 TOS or IPV6 Traffic Classifier or 0 */ ++#define IP_TOS(ip_body) \ ++ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ ++ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) + -+ /* allocate rx packet pointer vector */ -+ if (nrxd) { -+ size = nrxd * sizeof (void*); -+ if ((di->rxp = MALLOC(osh, size)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: out of rx memory, malloced %d bytes\n", di->name, MALLOCED(osh))); -+ goto fail; -+ } -+ bzero((char*)di->rxp, size); -+ } ++#endif /* _bcmip_h_ */ +diff -urN linux.old/drivers/net/wl/bcmutils.c linux.dev/drivers/net/wl/bcmutils.c +--- linux.old/drivers/net/wl/bcmutils.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/bcmutils.c 2006-04-28 02:27:20.000000000 +0200 +@@ -0,0 +1,857 @@ ++/* ++ * Misc useful OS-independent routines. ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * $Id: bcmutils.c,v 1.1.1.12 2006/02/27 03:43:16 honor Exp $ ++ */ + -+ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ -+ if (ntxd) { -+ if (!dma_alloc(di, DMA_TX)) -+ goto fail; -+ } ++#include ++#include ++#include ++#include ++#include "linux_osl.h" ++#include "pktq.h" ++#include ++#include ++#include ++#include ++#include ++#include "bcmip.h" + -+ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ -+ if (nrxd) { -+ if (!dma_alloc(di, DMA_RX)) -+ goto fail; -+ } ++#define ETHER_TYPE_8021Q 0x8100 ++#define ETHER_TYPE_IP 0x0800 ++#define VLAN_PRI_SHIFT 13 ++#define VLAN_PRI_MASK 7 + -+ if ((di->ddoffsetlow == SB_PCI_DMA) && (di->txdpa > SB_PCI_DMA_SZ) && !di->addrext) { -+ DMA_ERROR(("%s: dma_attach: txdpa 0x%lx: addrext not supported\n", di->name, di->txdpa)); -+ goto fail; -+ } -+ if ((di->ddoffsetlow == SB_PCI_DMA) && (di->rxdpa > SB_PCI_DMA_SZ) && !di->addrext) { -+ DMA_ERROR(("%s: dma_attach: rxdpa 0x%lx: addrext not supported\n", di->name, di->rxdpa)); -+ goto fail; -+ } + -+ return ((void*)di); ++struct ether_header { ++ uint8 ether_dhost[6]; ++ uint8 ether_shost[6]; ++ uint16 ether_type; ++} __attribute__((packed)); + -+fail: -+ dma_detach((void*)di); -+ return (NULL); -+} + -+static bool -+dma_alloc(dma_info_t *di, uint direction) -+{ -+ if (DMA64_ENAB(di)) { -+ return dma64_alloc(di, direction); -+ } else { -+ return dma32_alloc(di, direction); -+ } -+} ++struct ethervlan_header { ++ uint8 ether_dhost[6]; ++ uint8 ether_shost[6]; ++ uint16 vlan_type; /* 0x8100 */ ++ uint16 vlan_tag; /* priority, cfi and vid */ ++ uint16 ether_type; ++}; + -+/* may be called with core in reset */ -+void -+dma_detach(dma_info_t *di) ++/* copy a pkt buffer chain into a buffer */ ++uint ++pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) +{ -+ if (di == NULL) -+ return; ++ uint n, ret = 0; + -+ DMA_TRACE(("%s: dma_detach\n", di->name)); ++ if (len < 0) ++ len = 4096; /* "infinite" */ + -+ /* shouldn't be here if descriptors are unreclaimed */ -+ ASSERT(di->txin == di->txout); -+ ASSERT(di->rxin == di->rxout); ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); ++ } + -+ /* free dma descriptor rings */ -+ if (di->txd32) -+ DMA_FREE_CONSISTENT(di->osh, ((int8*)di->txd32 - di->txdalign), di->txdalloc, (di->txdpa - di->txdalign)); -+ if (di->rxd32) -+ DMA_FREE_CONSISTENT(di->osh, ((int8*)di->rxd32 - di->rxdalign), di->rxdalloc, (di->rxdpa - di->rxdalign)); ++ if (!p) ++ return 0; + -+ /* free packet pointer vectors */ -+ if (di->txp) -+ MFREE(di->osh, (void*)di->txp, (di->ntxd * sizeof (void*))); -+ if (di->rxp) -+ MFREE(di->osh, (void*)di->rxp, (di->nrxd * sizeof (void*))); ++ /* copy the data */ ++ for (; p && len; p = PKTNEXT(osh, p)) { ++ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); ++ bcopy(PKTDATA(osh, p) + offset, buf, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } + -+ /* free our private info structure */ -+ MFREE(di->osh, (void*)di, sizeof (dma_info_t)); ++ return ret; +} + -+/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ -+static bool -+dma_isaddrext(dma_info_t *di) ++/* return total length of buffer chain */ ++uint ++pkttotlen(osl_t *osh, void *p) +{ -+ uint32 w; ++ uint total; + -+ if (DMA64_ENAB(di)) { -+ OR_REG(&di->d64txregs->control, D64_XC_AE); -+ w = R_REG(&di->d32txregs->control); -+ AND_REG(&di->d32txregs->control, ~D64_XC_AE); -+ return ((w & XC_AE) == D64_XC_AE); -+ } else { -+ OR_REG(&di->d32txregs->control, XC_AE); -+ w = R_REG(&di->d32txregs->control); -+ AND_REG(&di->d32txregs->control, ~XC_AE); -+ return ((w & XC_AE) == XC_AE); -+ } ++ total = 0; ++ for (; p; p = PKTNEXT(osh, p)) ++ total += PKTLEN(osh, p); ++ return (total); +} + -+void -+dma_txreset(dma_info_t *di) ++/* return the last buffer of chained pkt */ ++void * ++pktlast(osl_t *osh, void *p) +{ -+ DMA_TRACE(("%s: dma_txreset\n", di->name)); ++ for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) ++ ; + -+ if (DMA64_ENAB(di)) -+ dma64_txreset(di); -+ else -+ dma32_txreset(di); ++ return (p); +} + -+void -+dma_rxreset(dma_info_t *di) ++ ++/* ++ * osl multiple-precedence packet queue ++ * hi_prec is always >= the number of the highest non-empty queue ++ */ ++void * ++pktq_penq(struct pktq *pq, int prec, void *p) +{ -+ DMA_TRACE(("%s: dma_rxreset\n", di->name)); ++ struct pktq_prec *q; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ++ ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); + -+ if (DMA64_ENAB(di)) -+ dma64_rxreset(di); ++ q = &pq->q[prec]; ++ ++ if (q->head) ++ PKTSETLINK(q->tail, p); + else -+ dma32_rxreset(di); -+} ++ q->head = p; + -+/* initialize descriptor table base address */ -+static void -+dma_ddtable_init(dma_info_t *di, uint direction, ulong pa) -+{ -+ if (DMA64_ENAB(di)) { -+ if (direction == DMA_TX) { -+ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); -+ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); -+ } else { -+ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); -+ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); -+ } -+ } else { -+ uint32 offset = di->ddoffsetlow; -+ if ((offset != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { -+ if (direction == DMA_TX) -+ W_REG(&di->d32txregs->addr, (pa + offset)); -+ else -+ W_REG(&di->d32rxregs->addr, (pa + offset)); -+ } else { -+ /* dma32 address extension */ -+ uint32 ae; -+ ASSERT(di->addrext); -+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; -+ -+ if (direction == DMA_TX) { -+ W_REG(&di->d32txregs->addr, ((pa & ~PCI32ADDR_HIGH) + offset)); -+ SET_REG(&di->d32txregs->control, XC_AE, (ae << XC_AE_SHIFT)); -+ } else { -+ W_REG(&di->d32rxregs->addr, ((pa & ~PCI32ADDR_HIGH) + offset)); -+ SET_REG(&di->d32rxregs->control, RC_AE, (ae << RC_AE_SHIFT)); -+ } -+ } -+ } -+} ++ q->tail = p; ++ q->len++; + -+/* init the tx or rx descriptor */ -+static INLINE void -+dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, ulong pa, uint outidx, uint32 *ctrl) -+{ -+ uint offset = di->dataoffsetlow; ++ pq->len++; + -+ if ((offset != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { -+ W_SM(&ddring[outidx].addr, BUS_SWAP32(pa + offset)); -+ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*ctrl)); -+ } else { -+ /* address extension */ -+ uint32 ae; -+ ASSERT(di->addrext); -+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; + -+ *ctrl |= (ae << CTRL_AE_SHIFT); -+ W_SM(&ddring[outidx].addr, BUS_SWAP32((pa & ~PCI32ADDR_HIGH) + offset)); -+ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*ctrl)); -+ } ++ return p; +} + -+/* init the tx or rx descriptor */ -+static INLINE void -+dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, ulong pa, uint outidx, uint32 *flags, uint32 bufcount) ++void * ++pktq_penq_head(struct pktq *pq, int prec, void *p) +{ -+ uint32 bufaddr_low = pa + di->dataoffsetlow; -+ uint32 bufaddr_high = 0 + di->dataoffsethigh; ++ struct pktq_prec *q; + -+ uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ + -+ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(bufaddr_low)); -+ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(bufaddr_high)); -+ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); -+ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); -+} ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); + -+void -+dma_txinit(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ q = &pq->q[prec]; + -+ di->txin = di->txout = 0; -+ di->txavail = di->ntxd - 1; ++ if (q->head == NULL) ++ q->tail = p; + -+ /* clear tx descriptor ring */ -+ if (DMA64_ENAB(di)) { -+ BZERO_SM((void*)di->txd64, (di->ntxd * sizeof (dma64dd_t))); -+ W_REG(&di->d64txregs->control, XC_XE); -+ dma_ddtable_init(di, DMA_TX, di->txdpa); -+ } else { -+ BZERO_SM((void*)di->txd32, (di->ntxd * sizeof (dma32dd_t))); -+ W_REG(&di->d32txregs->control, XC_XE); -+ dma_ddtable_init(di, DMA_TX, di->txdpa); -+ } -+} ++ PKTSETLINK(p, q->head); ++ q->head = p; ++ q->len++; + -+bool -+dma_txenabled(dma_info_t *di) -+{ -+ uint32 xc; -+ -+ /* If the chip is dead, it is not enabled :-) */ -+ if (DMA64_ENAB(di)) { -+ xc = R_REG(&di->d64txregs->control); -+ return ((xc != 0xffffffff) && (xc & D64_XC_XE)); -+ } else { -+ xc = R_REG(&di->d32txregs->control); -+ return ((xc != 0xffffffff) && (xc & XC_XE)); -+ } -+} ++ pq->len++; + -+void -+dma_txsuspend(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); -+ if (DMA64_ENAB(di)) -+ OR_REG(&di->d64txregs->control, D64_XC_SE); -+ else -+ OR_REG(&di->d32txregs->control, XC_SE); -+} ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; + -+void -+dma_txresume(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txresume\n", di->name)); -+ if (DMA64_ENAB(di)) -+ AND_REG(&di->d64txregs->control, ~D64_XC_SE); -+ else -+ AND_REG(&di->d32txregs->control, ~XC_SE); ++ return p; +} + -+bool -+dma_txsuspendedidle(dma_info_t *di) ++void * ++pktq_pdeq(struct pktq *pq, int prec) +{ -+ if (DMA64_ENAB(di)) -+ return dma64_txsuspendedidle(di); -+ else -+ return dma32_txsuspendedidle(di); -+} ++ struct pktq_prec *q; ++ void *p; + -+bool -+dma_txsuspended(dma_info_t *di) -+{ -+ if (DMA64_ENAB(di)) -+ return ((R_REG(&di->d64txregs->control) & D64_XC_SE) == D64_XC_SE); -+ else -+ return ((R_REG(&di->d32txregs->control) & XC_SE) == XC_SE); -+} ++ ASSERT(prec >= 0 && prec < pq->num_prec); + -+bool -+dma_txstopped(dma_info_t *di) -+{ -+ if (DMA64_ENAB(di)) -+ return ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_STOPPED); -+ else -+ return ((R_REG(&di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED); -+} ++ q = &pq->q[prec]; + -+bool -+dma_rxstopped(dma_info_t *di) -+{ -+ if (DMA64_ENAB(di)) -+ return ((R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK) == D64_RS0_RS_STOPPED); -+ else -+ return ((R_REG(&di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED); -+} ++ if ((p = q->head) == NULL) ++ return NULL; + -+void -+dma_fifoloopbackenable(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name)); -+ if (DMA64_ENAB(di)) -+ OR_REG(&di->d64txregs->control, D64_XC_LE); -+ else -+ OR_REG(&di->d32txregs->control, XC_LE); -+} ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; + -+void -+dma_rxinit(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_rxinit\n", di->name)); ++ q->len--; + -+ di->rxin = di->rxout = 0; ++ pq->len--; + -+ /* clear rx descriptor ring */ -+ if (DMA64_ENAB(di)) { -+ BZERO_SM((void*)di->rxd64, (di->nrxd * sizeof (dma64dd_t))); -+ dma_rxenable(di); -+ dma_ddtable_init(di, DMA_RX, di->rxdpa); -+ } else { -+ BZERO_SM((void*)di->rxd32, (di->nrxd * sizeof (dma32dd_t))); -+ dma_rxenable(di); -+ dma_ddtable_init(di, DMA_RX, di->rxdpa); -+ } ++ PKTSETLINK(p, NULL); ++ ++ return p; +} + -+void -+dma_rxenable(dma_info_t *di) ++void * ++pktq_pdeq_tail(struct pktq *pq, int prec) +{ -+ DMA_TRACE(("%s: dma_rxenable\n", di->name)); -+ if (DMA64_ENAB(di)) -+ W_REG(&di->d64rxregs->control, ((di->rxoffset << D64_RC_RO_SHIFT) | D64_RC_RE)); ++ struct pktq_prec *q; ++ void *p, *prev; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; ++ ++ if (prev) ++ PKTSETLINK(prev, NULL); + else -+ W_REG(&di->d32rxregs->control, ((di->rxoffset << RC_RO_SHIFT) | RC_RE)); -+} ++ q->head = NULL; + -+bool -+dma_rxenabled(dma_info_t *di) -+{ -+ uint32 rc; ++ q->tail = prev; ++ q->len--; + -+ if (DMA64_ENAB(di)) { -+ rc = R_REG(&di->d64rxregs->control); -+ return ((rc != 0xffffffff) && (rc & D64_RC_RE)); -+ } else { -+ rc = R_REG(&di->d32rxregs->control); -+ return ((rc != 0xffffffff) && (rc & RC_RE)); -+ } -+} ++ pq->len--; + ++ return p; ++} + -+/* !! tx entry routine */ -+int -+dma_txfast(dma_info_t *di, void *p0, uint32 coreflags) ++void ++pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir) +{ -+ if (DMA64_ENAB(di)) { -+ return dma64_txfast(di, p0, coreflags); -+ } else { -+ return dma32_txfast(di, p0, coreflags); ++ struct pktq_prec *q; ++ void *p; ++ ++ q = &pq->q[prec]; ++ p = q->head; ++ while (p) { ++ q->head = PKTLINK(p); ++ PKTSETLINK(p, NULL); ++ PKTFREE(osh, p, dir); ++ q->len--; ++ pq->len--; ++ p = q->head; + } ++ ASSERT(q->len == 0); ++ q->tail = NULL; +} + -+/* !! rx entry routine, returns a pointer to the next frame received, or NULL if there are no more */ -+void* -+dma_rx(dma_info_t *di) ++bool ++pktq_pdel(struct pktq *pq, void *pktbuf, int prec) +{ ++ struct pktq_prec *q; + void *p; -+ uint len; -+ int skiplen = 0; + -+ while ((p = dma_getnextrxp(di, FALSE))) { -+ /* skip giant packets which span multiple rx descriptors */ -+ if (skiplen > 0) { -+ skiplen -= di->rxbufsize; -+ if (skiplen < 0) -+ skiplen = 0; -+ PKTFREE(di->osh, p, FALSE); -+ continue; -+ } ++ ASSERT(prec >= 0 && prec < pq->num_prec); + -+ len = ltoh16(*(uint16*)(PKTDATA(di->osh, p))); -+ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); ++ if (!pktbuf) ++ return FALSE; + -+ /* bad frame length check */ -+ if (len > (di->rxbufsize - di->rxoffset)) { -+ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len)); -+ if (len > 0) -+ skiplen = len - (di->rxbufsize - di->rxoffset); -+ PKTFREE(di->osh, p, FALSE); -+ di->hnddma.rxgiants++; -+ continue; -+ } ++ q = &pq->q[prec]; + -+ /* set actual length */ -+ PKTSETLEN(di->osh, p, (di->rxoffset + len)); ++ if (q->head == pktbuf) { ++ if ((q->head = PKTLINK(pktbuf)) == NULL) ++ q->tail = NULL; ++ } else { ++ for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p)) ++ ; ++ if (p == NULL) ++ return FALSE; + -+ break; ++ PKTSETLINK(p, PKTLINK(pktbuf)); ++ if (q->tail == pktbuf) ++ q->tail = p; + } + -+ return (p); ++ q->len--; ++ pq->len--; ++ PKTSETLINK(pktbuf, NULL); ++ return TRUE; +} + -+/* post receive buffers */ +void -+dma_rxfill(dma_info_t *di) ++pktq_init(struct pktq *pq, int num_prec, int max_len) +{ -+ void *p; -+ uint rxin, rxout; -+ uint32 ctrl; -+ uint n; -+ uint i; -+ uint32 pa; -+ uint rxbufsize; ++ int prec; + -+ /* -+ * Determine how many receive buffers we're lacking -+ * from the full complement, allocate, initialize, -+ * and post them, then update the chip rx lastdscr. -+ */ ++ ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); + -+ rxin = di->rxin; -+ rxout = di->rxout; -+ rxbufsize = di->rxbufsize; ++ bzero(pq, sizeof(*pq)); + -+ n = di->nrxpost - NRXDACTIVE(rxin, rxout); ++ pq->num_prec = (uint16)num_prec; + -+ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); ++ pq->max = (uint16)max_len; + -+ for (i = 0; i < n; i++) { -+ if ((p = PKTGET(di->osh, rxbufsize, FALSE)) == NULL) { -+ DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", di->name)); -+ di->hnddma.rxnobuf++; -+ break; -+ } ++ for (prec = 0; prec < num_prec; prec++) ++ pq->q[prec].max = pq->max; ++} + -+ /* Do a cached write instead of uncached write since DMA_MAP -+ * will flush the cache. */ -+ *(uint32*)(PKTDATA(di->osh, p)) = 0; ++void * ++pktq_deq(struct pktq *pq, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; + -+ pa = (uint32) DMA_MAP(di->osh, PKTDATA(di->osh, p), rxbufsize, DMA_RX, p); -+ ASSERT(ISALIGNED(pa, 4)); ++ if (pq->len == 0) ++ return NULL; + -+ /* save the free packet pointer */ -+ ASSERT(di->rxp[rxout] == NULL); -+ di->rxp[rxout] = p; ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; + -+ if (DMA64_ENAB(di)) { -+ /* prep the descriptor control value */ -+ if (rxout == (di->nrxd - 1)) -+ ctrl = CTRL_EOT; ++ q = &pq->q[prec]; + -+ dma64_dd_upd(di, di->rxd64, pa, rxout, &ctrl, rxbufsize); -+ } else { -+ /* prep the descriptor control value */ -+ ctrl = rxbufsize; -+ if (rxout == (di->nrxd - 1)) -+ ctrl |= CTRL_EOT; -+ dma32_dd_upd(di, di->rxd32, pa, rxout, &ctrl); -+ } ++ if ((p = q->head) == NULL) ++ return NULL; + -+ rxout = NEXTRXD(rxout); -+ } ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; + -+ di->rxout = rxout; ++ q->len--; + -+ /* update the chip lastdscr pointer */ -+ if (DMA64_ENAB(di)) { -+ W_REG(&di->d64rxregs->ptr, I2B(rxout, dma64dd_t)); -+ } else { -+ W_REG(&di->d32rxregs->ptr, I2B(rxout, dma32dd_t)); -+ } -+} ++ pq->len--; + -+void -+dma_txreclaim(dma_info_t *di, bool forceall) -+{ -+ void *p; ++ if (prec_out) ++ *prec_out = prec; + -+ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); ++ PKTSETLINK(p, NULL); + -+ while ((p = dma_getnexttxp(di, forceall))) -+ PKTFREE(di->osh, p, TRUE); ++ return p; +} + -+/* -+ * Reclaim next completed txd (txds if using chained buffers) and -+ * return associated packet. -+ * If 'force' is true, reclaim txd(s) and return associated packet -+ * regardless of the value of the hardware "curr" pointer. -+ */ -+void* -+dma_getnexttxp(dma_info_t *di, bool forceall) -+{ -+ if (DMA64_ENAB(di)) { -+ return dma64_getnexttxp(di, forceall); -+ } else { -+ return dma32_getnexttxp(di, forceall); -+ } -+} -+ -+/* like getnexttxp but no reclaim */ -+void* -+dma_peeknexttxp(dma_info_t *di) ++void * ++pktq_deq_tail(struct pktq *pq, int *prec_out) +{ -+ uint end, i; ++ struct pktq_prec *q; ++ void *p, *prev; ++ int prec; + -+ if (DMA64_ENAB(di)) { -+ end = B2I(R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK, dma64dd_t); -+ } else { -+ end = B2I(R_REG(&di->d32txregs->status) & XS_CD_MASK, dma32dd_t); -+ } ++ if (pq->len == 0) ++ return NULL; + -+ for (i = di->txin; i != end; i = NEXTTXD(i)) -+ if (di->txp[i]) -+ return (di->txp[i]); ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; + -+ return (NULL); -+} ++ q = &pq->q[prec]; + -+/* -+ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). -+ */ -+void -+dma_txrotate(di_t *di) -+{ -+ if (DMA64_ENAB(di)) { -+ dma64_txrotate(di); -+ } else { -+ dma32_txrotate(di); -+ } -+} ++ if ((p = q->head) == NULL) ++ return NULL; + -+void -+dma_rxreclaim(dma_info_t *di) -+{ -+ void *p; ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; + -+ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; + -+ while ((p = dma_getnextrxp(di, TRUE))) -+ PKTFREE(di->osh, p, FALSE); ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; +} + +void * -+dma_getnextrxp(dma_info_t *di, bool forceall) ++pktq_peek(struct pktq *pq, int *prec_out) +{ -+ if (DMA64_ENAB(di)) { -+ return dma64_getnextrxp(di, forceall); -+ } else { -+ return dma32_getnextrxp(di, forceall); -+ } -+} ++ int prec; + -+uintptr -+dma_getvar(dma_info_t *di, char *name) -+{ -+ if (!strcmp(name, "&txavail")) -+ return ((uintptr) &di->txavail); -+ else { -+ ASSERT(0); -+ } -+ return (0); -+} ++ if (pq->len == 0) ++ return NULL; + -+void -+dma_txblock(dma_info_t *di) -+{ -+ di->txavail = 0; -+} ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; + -+void -+dma_txunblock(dma_info_t *di) -+{ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].head); +} + -+uint -+dma_txactive(dma_info_t *di) ++void * ++pktq_peek_tail(struct pktq *pq, int *prec_out) +{ -+ return (NTXDACTIVE(di->txin, di->txout)); ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].tail); +} -+ ++ +void -+dma_rxpiomode(dma32regs_t *regs) ++pktq_flush(osl_t *osh, struct pktq *pq, bool dir) +{ -+ W_REG(®s->control, RC_FM); ++ int prec; ++ for (prec = 0; prec < pq->num_prec; prec++) ++ pktq_pflush(osh, pq, prec, dir); ++ ASSERT(pq->len == 0); +} + -+void -+dma_txpioloopback(dma32regs_t *regs) ++/* Return sum of lengths of a specific set of precedences */ ++int ++pktq_mlen(struct pktq *pq, uint prec_bmp) +{ -+ OR_REG(®s->control, XC_LE); -+} ++ int prec, len; + ++ len = 0; + ++ for (prec = 0; prec <= pq->hi_prec; prec++) ++ if (prec_bmp & (1 << prec)) ++ len += pq->q[prec].len; + ++ return len; ++} + -+/*** 32 bits DMA non-inline functions ***/ -+static bool -+dma32_alloc(dma_info_t *di, uint direction) ++/* Priority dequeue from a specific set of precedences */ ++void * ++pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) +{ -+ uint size; -+ uint ddlen; -+ void *va; ++ struct pktq_prec *q; ++ void *p; ++ int prec; + -+ ddlen = sizeof (dma32dd_t); ++ if (pq->len == 0) ++ return NULL; + -+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; + -+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, D32RINGALIGN)) -+ size += D32RINGALIGN; ++ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) ++ if (prec-- == 0) ++ return NULL; + ++ q = &pq->q[prec]; + -+ if (direction == DMA_TX) { -+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->txdpa)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name)); -+ return FALSE; -+ } ++ if ((p = q->head) == NULL) ++ return NULL; + -+ di->txd32 = (dma32dd_t*) ROUNDUP((uintptr)va, D32RINGALIGN); -+ di->txdalign = (uint)((int8*)di->txd32 - (int8*)va); -+ di->txdpa += di->txdalign; -+ di->txdalloc = size; -+ ASSERT(ISALIGNED((uintptr)di->txd32, D32RINGALIGN)); -+ } else { -+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->rxdpa)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name)); -+ return FALSE; -+ } -+ di->rxd32 = (dma32dd_t*) ROUNDUP((uintptr)va, D32RINGALIGN); -+ di->rxdalign = (uint)((int8*)di->rxd32 - (int8*)va); -+ di->rxdpa += di->rxdalign; -+ di->rxdalloc = size; -+ ASSERT(ISALIGNED((uintptr)di->rxd32, D32RINGALIGN)); -+ } ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; + -+ return TRUE; -+} ++ q->len--; ++ ++ if (prec_out) ++ *prec_out = prec; + -+static void -+dma32_txreset(dma_info_t *di) -+{ -+ uint32 status; ++ pq->len--; + -+ /* suspend tx DMA first */ -+ W_REG(&di->d32txregs->control, XC_SE); -+ SPINWAIT((status = (R_REG(&di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED && -+ status != XS_XS_IDLE && -+ status != XS_XS_STOPPED, -+ 10000); -+ -+ W_REG(&di->d32txregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED, -+ 10000); -+ -+ if (status != XS_XS_DISABLED) { -+ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); -+ } ++ PKTSETLINK(p, NULL); + -+ /* wait for the last transaction to complete */ -+ OSL_DELAY(300); ++ return p; +} + -+static void -+dma32_rxreset(dma_info_t *di) ++char* ++bcmstrcat(char *dest, const char *src) +{ -+ uint32 status; -+ -+ W_REG(&di->d32rxregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED, -+ 10000); ++ strcpy(&dest[strlen(dest)], src); ++ return (dest); ++} + -+ if (status != RS_RS_DISABLED) { -+ DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name)); -+ } ++char* ++bcm_ether_ntoa(struct ether_addr *ea, char *buf) ++{ ++ sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", ++ ea->octet[0]&0xff, ea->octet[1]&0xff, ea->octet[2]&0xff, ++ ea->octet[3]&0xff, ea->octet[4]&0xff, ea->octet[5]&0xff); ++ return (buf); +} + -+static bool -+dma32_txsuspendedidle(dma_info_t *di) ++/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ ++int ++bcm_ether_atoe(char *p, struct ether_addr *ea) +{ -+ if (!(R_REG(&di->d32txregs->control) & XC_SE)) -+ return 0; -+ -+ if ((R_REG(&di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) -+ return 0; ++ int i = 0; + -+ OSL_DELAY(2); -+ return ((R_REG(&di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); ++ for (;;) { ++ ea->octet[i++] = (char) bcm_strtoul(p, &p, 16); ++ if (!*p++ || i == 6) ++ break; ++ } ++ ++ return (i == 6); +} + -+/* -+ * supports full 32bit dma engine buffer addressing so -+ * dma buffers can cross 4 Kbyte page boundaries. ++/* Takes an Ethernet frame and sets out-of-bound PKTPRIO ++ * Also updates the inplace vlan tag if requested + */ -+static int -+dma32_txfast(dma_info_t *di, void *p0, uint32 coreflags) ++void ++pktsetprio(void *pkt, bool update_vtag) +{ -+ void *p, *next; -+ uchar *data; -+ uint len; -+ uint txout; -+ uint32 ctrl; -+ uint32 pa; -+ -+ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ struct ether_header *eh; ++ struct ethervlan_header *evh; ++ uint8 *pktdata; ++ int priority = 0; + -+ txout = di->txout; -+ ctrl = 0; ++ pktdata = (uint8 *) PKTDATA(NULL, pkt); ++ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); + -+ /* -+ * Walk the chain of packet buffers -+ * allocating and initializing transmit descriptor entries. -+ */ -+ for (p = p0; p; p = next) { -+ data = PKTDATA(di->osh, p); -+ len = PKTLEN(di->osh, p); -+ next = PKTNEXT(di->osh, p); ++ eh = (struct ether_header *) pktdata; + -+ /* return nonzero if out of tx descriptors */ -+ if (NEXTTXD(txout) == di->txin) -+ goto outoftxd; ++ if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) { ++ uint16 vlan_tag; ++ int vlan_prio, dscp_prio = 0; + -+ if (len == 0) -+ continue; ++ evh = (struct ethervlan_header *)eh; + -+ /* get physical address of buffer start */ -+ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); ++ vlan_tag = ntoh16(evh->vlan_tag); ++ vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; + -+ /* build the descriptor control value */ -+ ctrl = len & CTRL_BC_MASK; ++ if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) { ++ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); ++ uint8 tos_tc = IP_TOS(ip_body); ++ dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ } + -+ ctrl |= coreflags; -+ -+ if (p == p0) -+ ctrl |= CTRL_SOF; -+ if (next == NULL) -+ ctrl |= (CTRL_IOC | CTRL_EOF); -+ if (txout == (di->ntxd - 1)) -+ ctrl |= CTRL_EOT; ++ /* DSCP priority gets precedence over 802.1P (vlan tag) */ ++ priority = (dscp_prio != 0) ? dscp_prio : vlan_prio; + -+ if (DMA64_ENAB(di)) { -+ dma64_dd_upd(di, di->txd64, pa, txout, &ctrl, len); -+ } else { -+ dma32_dd_upd(di, di->txd32, pa, txout, &ctrl); ++ /* ++ * If the DSCP priority is not the same as the VLAN priority, ++ * then overwrite the priority field in the vlan tag, with the ++ * DSCP priority value. This is required for Linux APs because ++ * the VLAN driver on Linux, overwrites the skb->priority field ++ * with the priority value in the vlan tag ++ */ ++ if (update_vtag && (priority != vlan_prio)) { ++ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); ++ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; ++ evh->vlan_tag = hton16(vlan_tag); + } ++ } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) { ++ uint8 *ip_body = pktdata + sizeof(struct ether_header); ++ uint8 tos_tc = IP_TOS(ip_body); ++ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ } + -+ ASSERT(di->txp[txout] == NULL); ++ ASSERT(priority >= 0 && priority <= MAXPRIO); ++ PKTSETPRIO(pkt, priority); ++} + -+ txout = NEXTTXD(txout); -+ } ++static char bcm_undeferrstr[BCME_STRLEN]; + -+ /* if last txd eof not set, fix it */ -+ if (!(ctrl & CTRL_EOF)) -+ W_SM(&di->txd32[PREVTXD(txout)].ctrl, BUS_SWAP32(ctrl | CTRL_IOC | CTRL_EOF)); ++static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE; + -+ /* save the packet */ -+ di->txp[PREVTXD(txout)] = p0; ++/* Convert the Error codes into related Error strings */ ++const char * ++bcmerrorstr(int bcmerror) ++{ ++ int abs_bcmerror; + -+ /* bump the tx descriptor index */ -+ di->txout = txout; ++ abs_bcmerror = ABS(bcmerror); + -+ /* kick the chip */ -+ if (DMA64_ENAB(di)) { -+ W_REG(&di->d64txregs->ptr, I2B(txout, dma64dd_t)); -+ } else { -+ W_REG(&di->d32txregs->ptr, I2B(txout, dma32dd_t)); ++ /* check if someone added a bcmerror code but forgot to add errorstring */ ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); ++ if ((bcmerror > 0) || (abs_bcmerror > ABS(BCME_LAST))) { ++ sprintf(bcm_undeferrstr, "undefined Error %d", bcmerror); ++ return bcm_undeferrstr; + } + -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ return (0); ++ ASSERT((strlen((char*)bcmerrorstrtable[abs_bcmerror])) < BCME_STRLEN); + -+ outoftxd: -+ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); -+ PKTFREE(di->osh, p0, TRUE); -+ di->txavail = 0; -+ di->hnddma.txnobuf++; -+ return (-1); ++ return bcmerrorstrtable[abs_bcmerror]; +} + -+static void* -+dma32_getnexttxp(dma_info_t *di, bool forceall) -+{ -+ uint start, end, i; -+ void *txp; -+ -+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); -+ -+ txp = NULL; + -+ start = di->txin; -+ if (forceall) -+ end = di->txout; -+ else -+ end = B2I(R_REG(&di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++int ++bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) ++{ ++ int bcmerror = 0; ++ ++ /* length check on io buf */ ++ switch (vi->type) { ++ case IOVT_BOOL: ++ case IOVT_INT8: ++ case IOVT_INT16: ++ case IOVT_INT32: ++ case IOVT_UINT8: ++ case IOVT_UINT16: ++ case IOVT_UINT32: ++ /* all integers are int32 sized args at the ioctl interface */ ++ if (len < (int)sizeof(int)) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; + -+ if ((start == 0) && (end > di->txout)) -+ goto bogus; ++ case IOVT_BUFFER: ++ /* buffer must meet minimum length requirement */ ++ if (len < vi->minlen) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; + -+ for (i = start; i != end && !txp; i = NEXTTXD(i)) { -+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->txd32[i].addr)) - di->dataoffsetlow), -+ (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) & CTRL_BC_MASK), DMA_TX, di->txp[i]); ++ case IOVT_VOID: ++ if (!set) { ++ /* Cannot return nil... */ ++ bcmerror = BCME_UNSUPPORTED; ++ } else if (len) { ++ /* Set is an action w/o parameters */ ++ bcmerror = BCME_BUFTOOLONG; ++ } ++ break; + -+ W_SM(&di->txd32[i].addr, 0xdeadbeef); -+ txp = di->txp[i]; -+ di->txp[i] = NULL; ++ default: ++ /* unknown type for length check in iovar info */ ++ ASSERT(0); ++ bcmerror = BCME_UNSUPPORTED; + } + -+ di->txin = i; -+ -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ return bcmerror; ++} + -+ return (txp); ++#define CRC_INNER_LOOP(n, c, x) \ ++ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] + -+bogus: -+/* -+ DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", -+ start, end, di->txout, forceall)); -+*/ -+ return (NULL); -+} ++static uint32 crc32_table[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 void * -+dma32_getnextrxp(dma_info_t *di, bool forceall) ++uint32 ++hndcrc32( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint32 crc /* either CRC32_INIT_VALUE or previous return value */ ++) +{ -+ uint i; -+ void *rxp; ++ uint8 *pend; ++#ifdef __mips__ ++ uint8 tmp[4]; ++ ulong *tptr = (ulong *)tmp; + -+ /* if forcing, dma engine must be disabled */ -+ ASSERT(!forceall || !dma_rxenabled(di)); ++ /* in case the beginning of the buffer isn't aligned */ ++ pend = (uint8 *)((uint)(pdata + 3) & 0xfffffffc); ++ nbytes -= (pend - pdata); ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); + -+ i = di->rxin; ++ /* handle bulk of data as 32-bit words */ ++ pend = pdata + (nbytes & 0xfffffffc); ++ while (pdata < pend) { ++ *tptr = *(ulong *)pdata; ++ pdata += sizeof(ulong *); ++ CRC_INNER_LOOP(32, crc, tmp[0]); ++ CRC_INNER_LOOP(32, crc, tmp[1]); ++ CRC_INNER_LOOP(32, crc, tmp[2]); ++ CRC_INNER_LOOP(32, crc, tmp[3]); ++ } + -+ /* return if no packets posted */ -+ if (i == di->rxout) -+ return (NULL); ++ /* 1-3 bytes at end of buffer */ ++ pend = pdata + (nbytes & 0x03); ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++#else ++ pend = pdata + nbytes; ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++#endif /* __mips__ */ + -+ /* ignore curr if forceall */ -+ if (!forceall && (i == B2I(R_REG(&di->d32rxregs->status) & RS_CD_MASK, dma32dd_t))) -+ return (NULL); ++ return crc; ++} + -+ /* get the packet pointer that corresponds to the rx descriptor */ -+ rxp = di->rxp[i]; -+ ASSERT(rxp); -+ di->rxp[i] = NULL; + -+ /* clear this packet from the descriptor ring */ -+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) - di->dataoffsetlow), -+ di->rxbufsize, DMA_RX, rxp); -+ W_SM(&di->rxd32[i].addr, 0xdeadbeef); ++/* ++ * Advance from the current 1-byte tag/1-byte length/variable-length value ++ * triple, to the next, returning a pointer to the next. ++ * If the current or next TLV is invalid (does not fit in given buffer length), ++ * NULL is returned. ++ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented ++ * by the TLV paramter's length if it is valid. ++ */ ++bcm_tlv_t * ++bcm_next_tlv(bcm_tlv_t *elt, int *buflen) ++{ ++ int len; ++ ++ /* validate current elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; + -+ di->rxin = NEXTRXD(i); ++ /* advance to next elt */ ++ len = elt->len; ++ elt = (bcm_tlv_t*)(elt->data + len); ++ *buflen -= (2 + len); + -+ return (rxp); ++ /* validate next elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; ++ ++ return elt; +} + -+static void -+dma32_txrotate(di_t *di) ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag ++ */ ++bcm_tlv_t * ++bcm_parse_tlvs(void *buf, int buflen, uint key) +{ -+ uint ad; -+ uint nactive; -+ uint rot; -+ uint old, new; -+ uint32 w; -+ uint first, last; ++ bcm_tlv_t *elt; ++ int totlen; + -+ ASSERT(dma_txsuspendedidle(di)); ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; + -+ nactive = dma_txactive(di); -+ ad = B2I(((R_REG(&di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t); -+ rot = TXD(ad - di->txin); ++ /* find tagged parameter */ ++ while (totlen >= 2) { ++ int len = elt->len; + -+ ASSERT(rot < di->ntxd); ++ /* validate remaining totlen */ ++ if ((elt->id == key) && (totlen >= (len + 2))) ++ return (elt); + -+ /* full-ring case is a lot harder - don't worry about this */ -+ if (rot >= (di->ntxd - nactive)) { -+ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); -+ return; ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); ++ totlen -= (len + 2); + } + -+ first = di->txin; -+ last = PREVTXD(di->txout); ++ return NULL; ++} + -+ /* move entries starting at last and moving backwards to first */ -+ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { -+ new = TXD(old + rot); ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag. Stop parsing when we see an element whose ID is greater ++ * than the target key. ++ */ ++bcm_tlv_t * ++bcm_parse_ordered_tlvs(void *buf, int buflen, uint key) ++{ ++ bcm_tlv_t *elt; ++ int totlen; + -+ /* -+ * Move the tx dma descriptor. -+ * EOT is set only in the last entry in the ring. -+ */ -+ w = R_SM(&di->txd32[old].ctrl) & ~CTRL_EOT; -+ if (new == (di->ntxd - 1)) -+ w |= CTRL_EOT; -+ W_SM(&di->txd32[new].ctrl, w); -+ W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr)); ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; + -+ /* zap the old tx dma descriptor address field */ -+ W_SM(&di->txd32[old].addr, 0xdeadbeef); ++ /* find tagged parameter */ ++ while (totlen >= 2) { ++ uint id = elt->id; ++ int len = elt->len; + -+ /* move the corresponding txp[] entry */ -+ ASSERT(di->txp[new] == NULL); -+ di->txp[new] = di->txp[old]; -+ di->txp[old] = NULL; -+ } ++ /* Punt if we start seeing IDs > than target key */ ++ if (id > key) ++ return (NULL); + -+ /* update txin and txout */ -+ di->txin = ad; -+ di->txout = TXD(di->txout + rot); -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ /* validate remaining totlen */ ++ if ((id == key) && (totlen >= (len + 2))) ++ return (elt); + -+ /* kick the chip */ -+ W_REG(&di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); ++ totlen -= (len + 2); ++ } ++ return NULL; +} + -+/*** 64 bits DMA non-inline functions ***/ -+ -+#ifdef BCMDMA64 + -+static bool -+dma64_alloc(dma_info_t *di, uint direction) ++/* Initialization of bcmstrbuf structure */ ++void ++bcm_binit(struct bcmstrbuf *b, char *buf, uint size) +{ -+ uint size; -+ uint ddlen; -+ uint32 alignbytes; -+ void *va; -+ -+ ddlen = sizeof (dma64dd_t); -+ -+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); -+ -+ alignbytes = di->dma64align; -+ -+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, alignbytes)) -+ size += alignbytes; ++ b->origsize = b->size = size; ++ b->origbuf = b->buf = buf; ++} + ++/* Buffer sprintf wrapper to guard against buffer overflow */ ++int ++bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) ++{ ++ va_list ap; ++ int r; + -+ if (direction == DMA_TX) { -+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->txdpa)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name)); -+ return FALSE; -+ } ++ va_start(ap, fmt); ++ r = vsnprintf(b->buf, b->size, fmt, ap); + -+ di->txd64 = (dma64dd_t*) ROUNDUP((uintptr)va, alignbytes); -+ di->txdalign = (uint)((int8*)di->txd64 - (int8*)va); -+ di->txdpa += di->txdalign; -+ di->txdalloc = size; -+ ASSERT(ISALIGNED((uintptr)di->txd64, alignbytes)); -+ } else { -+ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->rxdpa)) == NULL) { -+ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name)); -+ return FALSE; -+ } -+ di->rxd64 = (dma64dd_t*) ROUNDUP((uintptr)va, alignbytes); -+ di->rxdalign = (uint)((int8*)di->rxd64 - (int8*)va); -+ di->rxdpa += di->rxdalign; -+ di->rxdalloc = size; -+ ASSERT(ISALIGNED((uintptr)di->rxd64, alignbytes)); ++ /* Non Ansi C99 compliant returns -1, ++ * Ansi compliant return r >= b->size, ++ * bcmstdlib returns 0, handle all ++ */ ++ if ((r == -1) || (r >= (int)b->size) || (r == 0)) ++ { ++ b->size = 0; ++ } ++ else ++ { ++ b->size -= r; ++ b->buf += r; + } + -+ return TRUE; ++ va_end(ap); ++ ++ return r; +} +diff -urN linux.old/drivers/net/wl/hnddma.c linux.dev/drivers/net/wl/hnddma.c +--- linux.old/drivers/net/wl/hnddma.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/hnddma.c 2006-05-02 17:42:13.000000000 +0200 +@@ -0,0 +1,1157 @@ ++/* ++ * Generic Broadcom Home Networking Division (HND) DMA module. ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id: hnddma.c,v 1.11 2006/04/08 07:12:42 honor Exp $ ++ */ + -+static void -+dma64_txreset(dma_info_t *di) -+{ -+ uint32 status; ++#include ++#include ++#include ++#include "linux_osl.h" ++#include ++#include ++#include ++#include ++#include + -+ /* suspend tx DMA first */ -+ W_REG(&di->d64txregs->control, D64_XC_SE); -+ SPINWAIT((status = (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED && -+ status != D64_XS0_XS_IDLE && -+ status != D64_XS0_XS_STOPPED, -+ 10000); -+ -+ W_REG(&di->d64txregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED, -+ 10000); -+ -+ if (status != D64_XS0_XS_DISABLED) { -+ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); -+ } ++#include "sbhnddma.h" ++#include "hnddma.h" + -+ /* wait for the last transaction to complete */ -+ OSL_DELAY(300); -+} ++/* debug/trace */ ++#define DMA_ERROR(args) ++#define DMA_TRACE(args) + -+static void -+dma64_rxreset(dma_info_t *di) -+{ -+ uint32 status; ++/* default dma message level (if input msg_level pointer is null in dma_attach()) */ ++static uint dma_msg_level = ++ 0; + -+ W_REG(&di->d64rxregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED, -+ 10000); ++#define MAXNAMEL 8 /* 8 char names */ + -+ if (status != D64_RS0_RS_DISABLED) { -+ DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name)); -+ } -+} ++#define DI_INFO(dmah) (dma_info_t *)dmah + -+static bool -+dma64_txsuspendedidle(dma_info_t *di) -+{ ++/* dma engine software state */ ++typedef struct dma_info { ++ struct hnddma_pub hnddma; /* exported structure, don't use hnddma_t, ++ * which could be const ++ */ ++ uint *msg_level; /* message level pointer */ ++ char name[MAXNAMEL]; /* callers name for diag msgs */ + -+ if (!(R_REG(&di->d64txregs->control) & D64_XC_SE)) -+ return 0; -+ -+ if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_IDLE) -+ return 1; ++ void *osh; /* os handle */ ++ sb_t *sbh; /* sb handle */ + -+ return 0; -+} ++ bool dma64; /* dma64 enabled */ ++ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ + -+/* -+ * supports full 32bit dma engine buffer addressing so -+ * dma buffers can cross 4 Kbyte page boundaries. -+ */ -+static int -+dma64_txfast(dma_info_t *di, void *p0, uint32 coreflags) -+{ -+ void *p, *next; -+ uchar *data; -+ uint len; -+ uint txout; -+ uint32 flags; -+ uint32 pa; ++ dma32regs_t *d32txregs; /* 32 bits dma tx engine registers */ ++ dma32regs_t *d32rxregs; /* 32 bits dma rx engine registers */ ++ dma64regs_t *d64txregs; /* 64 bits dma tx engine registers */ ++ dma64regs_t *d64rxregs; /* 64 bits dma rx engine registers */ + -+ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ uint32 dma64align; /* either 8k or 4k depends on number of dd */ ++ dma32dd_t *txd32; /* pointer to dma32 tx descriptor ring */ ++ dma64dd_t *txd64; /* pointer to dma64 tx descriptor ring */ ++ uint ntxd; /* # tx descriptors tunable */ ++ uint txin; /* index of next descriptor to reclaim */ ++ uint txout; /* index of next descriptor to post */ ++ void **txp; /* pointer to parallel array of pointers to packets */ ++ osldma_t *tx_dmah; /* DMA TX descriptor ring handle */ ++ osldma_t **txp_dmah; /* DMA TX packet data handle */ ++ ulong txdpa; /* physical address of descriptor ring */ ++ uint txdalign; /* #bytes added to alloc'd mem to align txd */ ++ uint txdalloc; /* #bytes allocated for the ring */ + -+ txout = di->txout; -+ flags = 0; ++ dma32dd_t *rxd32; /* pointer to dma32 rx descriptor ring */ ++ dma64dd_t *rxd64; /* pointer to dma64 rx descriptor ring */ ++ uint nrxd; /* # rx descriptors tunable */ ++ uint rxin; /* index of next descriptor to reclaim */ ++ uint rxout; /* index of next descriptor to post */ ++ void **rxp; /* pointer to parallel array of pointers to packets */ ++ osldma_t *rx_dmah; /* DMA RX descriptor ring handle */ ++ osldma_t **rxp_dmah; /* DMA RX packet data handle */ ++ ulong rxdpa; /* physical address of descriptor ring */ ++ uint rxdalign; /* #bytes added to alloc'd mem to align rxd */ ++ uint rxdalloc; /* #bytes allocated for the ring */ + -+ /* -+ * Walk the chain of packet buffers -+ * allocating and initializing transmit descriptor entries. -+ */ -+ for (p = p0; p; p = next) { -+ data = PKTDATA(di->osh, p); -+ len = PKTLEN(di->osh, p); -+ next = PKTNEXT(di->osh, p); ++ /* tunables */ ++ uint rxbufsize; /* rx buffer size in bytes, ++ not including the extra headroom ++ */ ++ uint nrxpost; /* # rx buffers to keep posted */ ++ uint rxoffset; /* rxcontrol offset */ ++ uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */ ++ uint ddoffsethigh; /* high 32 bits */ ++ uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */ ++ uint dataoffsethigh; /* high 32 bits */ ++} dma_info_t; + -+ /* return nonzero if out of tx descriptors */ -+ if (NEXTTXD(txout) == di->txin) -+ goto outoftxd; ++/* descriptor bumping macros */ ++#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */ ++#define TXD(x) XXD((x), di->ntxd) ++#define RXD(x) XXD((x), di->nrxd) ++#define NEXTTXD(i) TXD(i + 1) ++#define PREVTXD(i) TXD(i - 1) ++#define NEXTRXD(i) RXD(i + 1) ++#define NTXDACTIVE(h, t) TXD(t - h) ++#define NRXDACTIVE(h, t) RXD(t - h) + -+ if (len == 0) -+ continue; ++/* macros to convert between byte offsets and indexes */ ++#define B2I(bytes, type) ((bytes) / sizeof(type)) ++#define I2B(index, type) ((index) * sizeof(type)) + -+ /* get physical address of buffer start */ -+ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); ++#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ ++#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ + -+ flags = coreflags; -+ -+ if (p == p0) -+ flags |= D64_CTRL1_SOF; -+ if (next == NULL) -+ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); -+ if (txout == (di->ntxd - 1)) -+ flags |= D64_CTRL1_EOT; + -+ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); ++/* common prototypes */ ++static bool _dma_isaddrext(dma_info_t *di); ++static bool dma32_alloc(dma_info_t *di, uint direction); ++static void _dma_detach(dma_info_t *di); ++static void _dma_ddtable_init(dma_info_t *di, uint direction, ulong pa); ++static void _dma_rxinit(dma_info_t *di); ++static void *_dma_rx(dma_info_t *di); ++static void _dma_rxfill(dma_info_t *di); ++static void _dma_rxreclaim(dma_info_t *di); ++static void _dma_rxenable(dma_info_t *di); ++static void * _dma_getnextrxp(dma_info_t *di, bool forceall); ++ ++static void _dma_txblock(dma_info_t *di); ++static void _dma_txunblock(dma_info_t *di); ++static uint _dma_txactive(dma_info_t *di); ++ ++static void* _dma_peeknexttxp(dma_info_t *di); ++static uintptr _dma_getvar(dma_info_t *di, char *name); ++static void _dma_counterreset(dma_info_t *di); ++static void _dma_fifoloopbackenable(dma_info_t *di); ++ ++/* ** 32 bit DMA prototypes */ ++static bool dma32_alloc(dma_info_t *di, uint direction); ++static bool dma32_txreset(dma_info_t *di); ++static bool dma32_rxreset(dma_info_t *di); ++static bool dma32_txsuspendedidle(dma_info_t *di); ++static int dma32_txfast(dma_info_t *di, void *p0, bool commit); ++static void *dma32_getnexttxp(dma_info_t *di, bool forceall); ++static void *dma32_getnextrxp(dma_info_t *di, bool forceall); ++static void dma32_txrotate(dma_info_t *di); ++static bool dma32_rxidle(dma_info_t *di); ++static void dma32_txinit(dma_info_t *di); ++static bool dma32_txenabled(dma_info_t *di); ++static void dma32_txsuspend(dma_info_t *di); ++static void dma32_txresume(dma_info_t *di); ++static bool dma32_txsuspended(dma_info_t *di); ++static void dma32_txreclaim(dma_info_t *di, bool forceall); ++static bool dma32_txstopped(dma_info_t *di); ++static bool dma32_rxstopped(dma_info_t *di); ++static bool dma32_rxenabled(dma_info_t *di); ++static bool _dma32_addrext(osl_t *osh, dma32regs_t *dma32regs); ++ ++ ++static di_fcn_t dma32proc = { ++ (di_detach_t)_dma_detach, ++ (di_txinit_t)dma32_txinit, ++ (di_txreset_t)dma32_txreset, ++ (di_txenabled_t)dma32_txenabled, ++ (di_txsuspend_t)dma32_txsuspend, ++ (di_txresume_t)dma32_txresume, ++ (di_txsuspended_t)dma32_txsuspended, ++ (di_txsuspendedidle_t)dma32_txsuspendedidle, ++ (di_txfast_t)dma32_txfast, ++ (di_txstopped_t)dma32_txstopped, ++ (di_txreclaim_t)dma32_txreclaim, ++ (di_getnexttxp_t)dma32_getnexttxp, ++ (di_peeknexttxp_t)_dma_peeknexttxp, ++ (di_txblock_t)_dma_txblock, ++ (di_txunblock_t)_dma_txunblock, ++ (di_txactive_t)_dma_txactive, ++ (di_txrotate_t)dma32_txrotate, ++ ++ (di_rxinit_t)_dma_rxinit, ++ (di_rxreset_t)dma32_rxreset, ++ (di_rxidle_t)dma32_rxidle, ++ (di_rxstopped_t)dma32_rxstopped, ++ (di_rxenable_t)_dma_rxenable, ++ (di_rxenabled_t)dma32_rxenabled, ++ (di_rx_t)_dma_rx, ++ (di_rxfill_t)_dma_rxfill, ++ (di_rxreclaim_t)_dma_rxreclaim, ++ (di_getnextrxp_t)_dma_getnextrxp, ++ ++ (di_fifoloopbackenable_t)_dma_fifoloopbackenable, ++ (di_getvar_t)_dma_getvar, ++ (di_counterreset_t)_dma_counterreset, ++ ++ NULL, ++ NULL, ++ NULL, ++ 34 ++}; + -+ ASSERT(di->txp[txout] == NULL); ++hnddma_t * ++dma_attach(osl_t *osh, char *name, sb_t *sbh, void *dmaregstx, void *dmaregsrx, ++ uint ntxd, uint nrxd, uint rxbufsize, uint nrxpost, uint rxoffset, uint *msg_level) ++{ ++ dma_info_t *di; ++ uint size; + -+ txout = NEXTTXD(txout); ++ /* allocate private info structure */ ++ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { ++ return (NULL); + } ++ bzero((char *)di, sizeof(dma_info_t)); + -+ /* if last txd eof not set, fix it */ -+ if (!(flags & D64_CTRL1_EOF)) -+ W_SM(&di->txd64[PREVTXD(txout)].ctrl1, BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF)); -+ -+ /* save the packet */ -+ di->txp[PREVTXD(txout)] = p0; ++ di->msg_level = msg_level ? msg_level : &dma_msg_level; + -+ /* bump the tx descriptor index */ -+ di->txout = txout; ++ /* old chips w/o sb is no longer supported */ ++ ASSERT(sbh != NULL); + -+ /* kick the chip */ -+ W_REG(&di->d64txregs->ptr, I2B(txout, dma64dd_t)); ++ /* check arguments */ ++ ASSERT(ISPOWEROF2(ntxd)); ++ ASSERT(ISPOWEROF2(nrxd)); ++ if (nrxd == 0) ++ ASSERT(dmaregsrx == NULL); ++ if (ntxd == 0) ++ ASSERT(dmaregstx == NULL); + -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+ return (0); ++ /* init dma reg pointer */ ++ ASSERT(ntxd <= D32MAXDD); ++ ASSERT(nrxd <= D32MAXDD); ++ di->d32txregs = (dma32regs_t *)dmaregstx; ++ di->d32rxregs = (dma32regs_t *)dmaregsrx; + -+outoftxd: -+ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); -+ PKTFREE(di->osh, p0, TRUE); -+ di->txavail = 0; -+ di->hnddma.txnobuf++; -+ return (-1); -+} ++ DMA_TRACE(("%s: dma_attach: %s osh %p ntxd %d nrxd %d rxbufsize %d nrxpost %d " ++ "rxoffset %d dmaregstx %p dmaregsrx %p\n", ++ name, "DMA32", osh, ntxd, nrxd, rxbufsize, ++ nrxpost, rxoffset, dmaregstx, dmaregsrx)); + -+static void* -+dma64_getnexttxp(dma_info_t *di, bool forceall) -+{ -+ uint start, end, i; -+ void *txp; ++ /* make a private copy of our callers name */ ++ strncpy(di->name, name, MAXNAMEL); ++ di->name[MAXNAMEL-1] = '\0'; + -+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); ++ di->osh = osh; ++ di->sbh = sbh; + -+ txp = NULL; ++ /* save tunables */ ++ di->ntxd = ntxd; ++ di->nrxd = nrxd; + -+ start = di->txin; -+ if (forceall) -+ end = di->txout; ++ /* the actual dma size doesn't include the extra headroom */ ++ if (rxbufsize > BCMEXTRAHDROOM) ++ di->rxbufsize = rxbufsize - BCMEXTRAHDROOM; + else -+ end = B2I(R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK, dma64dd_t); ++ di->rxbufsize = rxbufsize; + -+ if ((start == 0) && (end > di->txout)) -+ goto bogus; ++ di->nrxpost = nrxpost; ++ di->rxoffset = rxoffset; + -+ for (i = start; i != end && !txp; i = NEXTTXD(i)) { -+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) - di->dataoffsetlow), -+ (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) & D64_CTRL2_BC_MASK), DMA_TX, di->txp[i]); ++ /* ++ * figure out the DMA physical address offset for dd and data ++ * for old chips w/o sb, use zero ++ * for new chips w sb, ++ * PCI/PCIE: they map silicon backplace address to zero based memory, need offset ++ * Other bus: use zero ++ * SB_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor ++ */ ++ di->ddoffsetlow = 0; ++ di->dataoffsetlow = 0; ++ /* for pci bus, add offset */ ++ if (sbh->bustype == PCI_BUS) { ++ di->ddoffsetlow = SB_PCI_DMA; ++ di->ddoffsethigh = 0; ++ di->dataoffsetlow = di->ddoffsetlow; ++ di->dataoffsethigh = di->ddoffsethigh; ++ } + -+ W_SM(&di->txd64[i].addrlow, 0xdeadbeef); -+ W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); ++#if defined(__mips__) && defined(IL_BIGENDIAN) ++ di->dataoffsetlow = di->dataoffsetlow + SB_SDRAM_SWAPPED; ++#endif + -+ txp = di->txp[i]; -+ di->txp[i] = NULL; -+ } ++ di->addrext = _dma_isaddrext(di); + -+ di->txin = i; ++ /* allocate tx packet pointer vector */ ++ if (ntxd) { ++ size = ntxd * sizeof(void *); ++ if ((di->txp = MALLOC(osh, size)) == NULL) { ++ DMA_ERROR(("%s: dma_attach: out of tx memory, malloced %d bytes\n", ++ di->name, MALLOCED(osh))); ++ goto fail; ++ } ++ bzero((char *)di->txp, size); ++ } + -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ /* allocate rx packet pointer vector */ ++ if (nrxd) { ++ size = nrxd * sizeof(void *); ++ if ((di->rxp = MALLOC(osh, size)) == NULL) { ++ DMA_ERROR(("%s: dma_attach: out of rx memory, malloced %d bytes\n", ++ di->name, MALLOCED(osh))); ++ goto fail; ++ } ++ bzero((char *)di->rxp, size); ++ } + -+ return (txp); ++ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ ++ if (ntxd) { ++ if (!dma32_alloc(di, DMA_TX)) ++ goto fail; ++ } + -+bogus: -+/* -+ DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", -+ start, end, di->txout, forceall)); -+*/ -+ return (NULL); -+} ++ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ ++ if (nrxd) { ++ if (!dma32_alloc(di, DMA_RX)) ++ goto fail; ++ } + -+static void * -+dma64_getnextrxp(dma_info_t *di, bool forceall) -+{ -+ uint i; -+ void *rxp; ++ if ((di->ddoffsetlow == SB_PCI_DMA) && (di->txdpa > SB_PCI_DMA_SZ) && !di->addrext) { ++ DMA_ERROR(("%s: dma_attach: txdpa 0x%lx: addrext not supported\n", ++ di->name, di->txdpa)); ++ goto fail; ++ } ++ if ((di->ddoffsetlow == SB_PCI_DMA) && (di->rxdpa > SB_PCI_DMA_SZ) && !di->addrext) { ++ DMA_ERROR(("%s: dma_attach: rxdpa 0x%lx: addrext not supported\n", ++ di->name, di->rxdpa)); ++ goto fail; ++ } + -+ /* if forcing, dma engine must be disabled */ -+ ASSERT(!forceall || !dma_rxenabled(di)); ++ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " ++ "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, ++ di->dataoffsethigh, di->addrext)); + -+ i = di->rxin; ++ /* allocate tx packet pointer vector and DMA mapping vectors */ ++ if (ntxd) { + -+ /* return if no packets posted */ -+ if (i == di->rxout) -+ return (NULL); ++ size = ntxd * sizeof(osldma_t **); ++ if ((di->txp_dmah = (osldma_t **)MALLOC(osh, size)) == NULL) ++ goto fail; ++ bzero((char*)di->txp_dmah, size); ++ }else ++ di->txp_dmah = NULL; + -+ /* ignore curr if forceall */ -+ if (!forceall && (i == B2I(R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK, dma64dd_t))) -+ return (NULL); ++ /* allocate rx packet pointer vector and DMA mapping vectors */ ++ if (nrxd) { + -+ /* get the packet pointer that corresponds to the rx descriptor */ -+ rxp = di->rxp[i]; -+ ASSERT(rxp); -+ di->rxp[i] = NULL; ++ size = nrxd * sizeof(osldma_t **); ++ if ((di->rxp_dmah = (osldma_t **)MALLOC(osh, size)) == NULL) ++ goto fail; ++ bzero((char*)di->rxp_dmah, size); + -+ /* clear this packet from the descriptor ring */ -+ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) - di->dataoffsetlow), -+ di->rxbufsize, DMA_RX, rxp); ++ } else ++ di->rxp_dmah = NULL; + -+ W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); -+ W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); ++ /* initialize opsvec of function pointers */ ++ di->hnddma.di_fn = dma32proc; + -+ di->rxin = NEXTRXD(i); ++ return ((hnddma_t *)di); + -+ return (rxp); ++fail: ++ _dma_detach(di); ++ return (NULL); +} + -+static void -+dma64_txrotate(di_t *di) ++/* init the tx or rx descriptor */ ++static INLINE void ++dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, ulong pa, uint outidx, uint32 *flags, ++ uint32 bufcount) +{ -+ uint ad; -+ uint nactive; -+ uint rot; -+ uint old, new; -+ uint32 w; -+ uint first, last; ++ /* dma32 uses 32 bits control to fit both flags and bufcounter */ ++ *flags = *flags | (bufcount & CTRL_BC_MASK); + -+ ASSERT(dma_txsuspendedidle(di)); -+ -+ nactive = dma_txactive(di); -+ ad = B2I((R_REG(&di->d64txregs->status1) & D64_XS1_AD_MASK), dma64dd_t); -+ rot = TXD(ad - di->txin); -+ -+ ASSERT(rot < di->ntxd); ++ if ((di->dataoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { ++ W_SM(&ddring[outidx].addr, BUS_SWAP32(pa + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); ++ } else { ++ /* address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ pa &= ~PCI32ADDR_HIGH; + -+ /* full-ring case is a lot harder - don't worry about this */ -+ if (rot >= (di->ntxd - nactive)) { -+ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); -+ return; ++ *flags |= (ae << CTRL_AE_SHIFT); ++ W_SM(&ddring[outidx].addr, BUS_SWAP32(pa + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); + } ++} + -+ first = di->txin; -+ last = PREVTXD(di->txout); ++static bool ++_dma32_addrext(osl_t *osh, dma32regs_t *dma32regs) ++{ ++ uint32 w; + -+ /* move entries starting at last and moving backwards to first */ -+ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { -+ new = TXD(old + rot); ++ OR_REG(osh, &dma32regs->control, XC_AE); ++ w = R_REG(osh, &dma32regs->control); ++ AND_REG(osh, &dma32regs->control, ~XC_AE); ++ return ((w & XC_AE) == XC_AE); ++} + -+ /* -+ * Move the tx dma descriptor. -+ * EOT is set only in the last entry in the ring. -+ */ -+ w = R_SM(&di->txd64[old].ctrl1) & ~D64_CTRL1_EOT; -+ if (new == (di->ntxd - 1)) -+ w |= D64_CTRL1_EOT; -+ W_SM(&di->txd64[new].ctrl1, w); ++/* !! may be called with core in reset */ ++static void ++_dma_detach(dma_info_t *di) ++{ ++ if (di == NULL) ++ return; + -+ w = R_SM(&di->txd64[old].ctrl2); -+ W_SM(&di->txd64[new].ctrl2, w); ++ DMA_TRACE(("%s: dma_detach\n", di->name)); + -+ W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); -+ W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); ++ /* shouldn't be here if descriptors are unreclaimed */ ++ ASSERT(di->txin == di->txout); ++ ASSERT(di->rxin == di->rxout); + -+ /* zap the old tx dma descriptor address field */ -+ W_SM(&di->txd64[old].addrlow, 0xdeadbeef); -+ W_SM(&di->txd64[old].addrhigh, 0xdeadbeef); ++ /* free dma descriptor rings */ ++ if (di->txd32) ++ DMA_FREE_CONSISTENT(di->osh, ((int8*)di->txd32 - di->txdalign), ++ di->txdalloc, (di->txdpa - di->txdalign), &di->tx_dmah); ++ if (di->rxd32) ++ DMA_FREE_CONSISTENT(di->osh, ((int8*)di->rxd32 - di->rxdalign), ++ di->rxdalloc, (di->rxdpa - di->rxdalign), &di->rx_dmah); + -+ /* move the corresponding txp[] entry */ -+ ASSERT(di->txp[new] == NULL); -+ di->txp[new] = di->txp[old]; -+ di->txp[old] = NULL; -+ } ++ /* free packet pointer vectors */ ++ if (di->txp) ++ MFREE(di->osh, (void *)di->txp, (di->ntxd * sizeof(void *))); ++ if (di->rxp) ++ MFREE(di->osh, (void *)di->rxp, (di->nrxd * sizeof(void *))); + -+ /* update txin and txout */ -+ di->txin = ad; -+ di->txout = TXD(di->txout + rot); -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ /* free tx packet DMA handles */ ++ if (di->txp_dmah) ++ MFREE(di->osh, (void *)di->txp_dmah, di->ntxd * sizeof(osldma_t **)); + -+ /* kick the chip */ -+ W_REG(&di->d64txregs->ptr, I2B(di->txout, dma64dd_t)); -+} ++ /* free rx packet DMA handles */ ++ if (di->rxp_dmah) ++ MFREE(di->osh, (void *)di->rxp_dmah, di->nrxd * sizeof(osldma_t **)); + -+#endif ++ /* free our private info structure */ ++ MFREE(di->osh, (void *)di, sizeof(dma_info_t)); + -diff -Naur linux.old/drivers/net/wl2/hnddma.h linux.dev/drivers/net/wl2/hnddma.h ---- linux.old/drivers/net/wl2/hnddma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl2/hnddma.h 2006-04-06 16:32:44.000000000 +0200 -@@ -0,0 +1,71 @@ -+/* -+ * Generic Broadcom Home Networking Division (HND) DMA engine SW interface -+ * This supports the following chips: BCM42xx, 44xx, 47xx . -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ ++} + -+#ifndef _hnddma_h_ -+#define _hnddma_h_ ++/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ ++static bool ++_dma_isaddrext(dma_info_t *di) ++{ ++ if (di->d32txregs) ++ return (_dma32_addrext(di->osh, di->d32txregs)); ++ else if (di->d32rxregs) ++ return (_dma32_addrext(di->osh, di->d32rxregs)); ++ return FALSE; ++} + -+/* export structure */ -+typedef volatile struct { -+ /* rx error counters */ -+ uint rxgiants; /* rx giant frames */ -+ uint rxnobuf; /* rx out of dma descriptors */ -+ /* tx error counters */ -+ uint txnobuf; /* tx out of dma descriptors */ -+} hnddma_t; ++/* initialize descriptor table base address */ ++static void ++_dma_ddtable_init(dma_info_t *di, uint direction, ulong pa) ++{ ++ if ((di->ddoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { ++ if (direction == DMA_TX) ++ W_REG(di->osh, &di->d32txregs->addr, (pa + di->ddoffsetlow)); ++ else ++ W_REG(di->osh, &di->d32rxregs->addr, (pa + di->ddoffsetlow)); ++ } else { ++ /* dma32 address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); + -+#ifndef di_t -+#define di_t void -+#endif ++ /* shift the high bit(s) from pa to ae */ ++ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ pa &= ~PCI32ADDR_HIGH; + -+#ifndef osl_t -+#define osl_t void -+#endif ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d32txregs->addr, (pa + di->ddoffsetlow)); ++ SET_REG(di->osh, &di->d32txregs->control, XC_AE, ae <osh, &di->d32rxregs->addr, (pa + di->ddoffsetlow)); ++ SET_REG(di->osh, &di->d32rxregs->control, RC_AE, ae <name)); ++ OR_REG(di->osh, &di->d32txregs->control, XC_LE); ++} + ++static void ++_dma_rxinit(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxinit\n", di->name)); + -+#endif /* _hnddma_h_ */ -diff -Naur linux.old/drivers/net/wl2/pktq.h linux.dev/drivers/net/wl2/pktq.h ---- linux.old/drivers/net/wl2/pktq.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl2/pktq.h 2006-04-06 17:33:02.000000000 +0200 -@@ -0,0 +1,83 @@ -+/* -+ * Misc useful os-independent macros and functions. -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ ++ if (di->nrxd == 0) ++ return; + -+#ifndef _pktq_h_ -+#define _pktq_h_ ++ di->rxin = di->rxout = 0; + -+/*** driver-only section ***/ -+#ifdef BCMDRIVER ++ /* clear rx descriptor ring */ ++ BZERO_SM((void *)di->rxd32, (di->nrxd * sizeof(dma32dd_t))); ++ _dma_rxenable(di); ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++} + -+/* osl packet chain functions */ -+extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); -+extern uint pkttotlen(osl_t *osh, void *); ++static void ++_dma_rxenable(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxenable\n", di->name)); + -+#define pktenq(pq, p) pktq_penq((pq), 0, (p)) /* legacy */ -+#define pktdeq(pq) pktq_pdeq((pq), 0) /* legacy */ ++ W_REG(di->osh, &di->d32rxregs->control, ((di->rxoffset << RC_RO_SHIFT) | RC_RE)); ++} + -+/* osl multi-precedence packet queue */ ++/* !! rx entry routine, returns a pointer to the next frame received, ++ * or NULL if there are no more ++ */ ++static void * ++_dma_rx(dma_info_t *di) ++{ ++ void *p; ++ uint len; ++ int skiplen = 0; + -+#define PKTQ_LEN_DEFAULT 128 -+#define PKTQ_MAX_PREC 8 -+struct pktq_prec { -+ void *head; /* first packet to dequeue */ -+ void *tail; /* last packet to dequeue */ -+ uint16 len; /* number of queued packets */ -+ uint16 max; /* maximum number of queued packets */ -+}; ++ while ((p = _dma_getnextrxp(di, FALSE))) { ++ /* skip giant packets which span multiple rx descriptors */ ++ if (skiplen > 0) { ++ skiplen -= di->rxbufsize; ++ if (skiplen < 0) ++ skiplen = 0; ++ PKTFREE(di->osh, p, FALSE); ++ continue; ++ } + -+struct pktq { -+ struct pktq_prec q[PKTQ_MAX_PREC]; -+ uint16 num_prec; /* number of precedences in use */ -+ uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ -+ uint16 max; /* total max packets */ -+ uint16 len; /* total number of packets */ -+}; ++ len = ltoh16(*(uint16*)(PKTDATA(di->osh, p))); ++ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); + -+/* operations on a specific precedence in packet queue */ ++ /* bad frame length check */ ++ if (len > (di->rxbufsize - di->rxoffset)) { ++ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len)); ++ if (len > 0) ++ skiplen = len - (di->rxbufsize - di->rxoffset); ++ PKTFREE(di->osh, p, FALSE); ++ di->hnddma.rxgiants++; ++ continue; ++ } + -+#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) -+#define pktq_plen(pq, prec) ((pq)->q[prec].len) -+#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) -+#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) -+#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) ++ /* set actual length */ ++ PKTSETLEN(di->osh, p, (di->rxoffset + len)); + -+#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) -+#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) ++ break; ++ } + -+extern void *pktq_penq(struct pktq *pq, int prec, void *p); -+extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); -+extern void *pktq_pdeq(struct pktq *pq, int prec); -+extern void *pktq_pdeq_tail(struct pktq *pq, int prec); ++ return (p); ++} + -+/* operations on packet queue as a whole */ ++/* post receive buffers */ ++static void ++_dma_rxfill(dma_info_t *di) ++{ ++ void *p; ++ uint rxin, rxout; ++ uint32 flags = 0; ++ uint n; ++ uint i; ++ uint32 pa; ++ uint extra_offset = 0; + -+extern void pktq_init(struct pktq *pq, int num_prec, int max); ++ /* ++ * Determine how many receive buffers we're lacking ++ * from the full complement, allocate, initialize, ++ * and post them, then update the chip rx lastdscr. ++ */ + -+#define pktq_len(pq) ((int)(pq)->len) -+#define pktq_max(pq) ((int)(pq)->max) -+#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) -+#define pktq_full(pq) ((pq)->len >= (pq)->max) -+#define pktq_empty(pq) ((pq)->len == 0) ++ rxin = di->rxin; ++ rxout = di->rxout; + -+extern void *pktq_deq(struct pktq *pq, int *prec_out); -+extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); -+extern void *pktq_peek(struct pktq *pq, int *prec_out); -+extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); ++ n = di->nrxpost - NRXDACTIVE(rxin, rxout); + -+extern int pktq_mlen(struct pktq *pq, uint prec_bmp); -+extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); ++ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); + -+#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) ++ if (di->rxbufsize > BCMEXTRAHDROOM) ++ extra_offset = BCMEXTRAHDROOM; + -+#endif -+#endif /* _pktq_h_ */ -diff -Naur linux.old/drivers/net/wl2/sbhnddma.h linux.dev/drivers/net/wl2/sbhnddma.h ---- linux.old/drivers/net/wl2/sbhnddma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/net/wl2/sbhnddma.h 2006-04-06 16:32:44.000000000 +0200 -@@ -0,0 +1,312 @@ -+/* -+ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface -+ * This supports the following chips: BCM42xx, 44xx, 47xx . -+ * -+ * Copyright 2005, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * $Id$ -+ */ ++ for (i = 0; i < n; i++) { ++ /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the ++ size to be allocated ++ */ ++ if ((p = PKTGET(di->osh, di->rxbufsize + extra_offset, ++ FALSE)) == NULL) { ++ DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", di->name)); ++ di->hnddma.rxnobuf++; ++ break; ++ } ++ /* reserve an extra headroom, if applicable */ ++ if (extra_offset) ++ PKTPULL(di->osh, p, extra_offset); + -+#ifndef _sbhnddma_h_ -+#define _sbhnddma_h_ ++ /* Do a cached write instead of uncached write since DMA_MAP ++ * will flush the cache. ++ */ ++ *(uint32*)(PKTDATA(di->osh, p)) = 0; + -+ -+/* 2byte-wide pio register set per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint16 fifocontrol; -+ uint16 fifodata; -+ uint16 fifofree; /* only valid in xmt channel, not in rcv channel */ -+ uint16 PAD; -+} pio2regs_t; ++ pa = (uint32) DMA_MAP(di->osh, PKTDATA(di->osh, p), ++ di->rxbufsize, DMA_RX, p); + -+/* a pair of pio channels(tx and rx) */ -+typedef volatile struct { -+ pio2regs_t tx; -+ pio2regs_t rx; -+} pio2regp_t; ++ ASSERT(ISALIGNED(pa, 4)); + -+/* 4byte-wide pio register set per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint32 fifocontrol; -+ uint32 fifodata; -+} pio4regs_t; ++ /* save the free packet pointer */ ++ ASSERT(di->rxp[rxout] == NULL); ++ di->rxp[rxout] = p; + -+/* a pair of pio channels(tx and rx) */ -+typedef volatile struct { -+ pio4regs_t tx; -+ pio4regs_t rx; -+} pio4regp_t; ++ /* reset flags for each descriptor */ ++ flags = 0; ++ if (rxout == (di->nrxd - 1)) ++ flags = CTRL_EOT; ++ dma32_dd_upd(di, di->rxd32, pa, rxout, &flags, di->rxbufsize); ++ rxout = NEXTRXD(rxout); ++ } + ++ di->rxout = rxout; + ++ /* update the chip lastdscr pointer */ ++ W_REG(di->osh, &di->d32rxregs->ptr, I2B(rxout, dma32dd_t)); ++} + -+/* DMA structure: -+ * support two DMA engines: 32 bits address or 64 bit addressing -+ * basic DMA register set is per channel(transmit or receive) -+ * a pair of channels is defined for convenience -+ */ ++/* like getnexttxp but no reclaim */ ++static void * ++_dma_peeknexttxp(dma_info_t *di) ++{ ++ uint end, i; + ++ if (di->ntxd == 0) ++ return (NULL); + -+/*** 32 bits addressing ***/ ++ end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); + -+/* dma registers per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint32 control; /* enable, et al */ -+ uint32 addr; /* descriptor ring base address (4K aligned) */ -+ uint32 ptr; /* last descriptor posted to chip */ -+ uint32 status; /* current active descriptor, et al */ -+} dma32regs_t; ++ for (i = di->txin; i != end; i = NEXTTXD(i)) ++ if (di->txp[i]) ++ return (di->txp[i]); + -+typedef volatile struct { -+ dma32regs_t xmt; /* dma tx channel */ -+ dma32regs_t rcv; /* dma rx channel */ -+} dma32regp_t; ++ return (NULL); ++} + -+typedef volatile struct { /* diag access */ -+ uint32 fifoaddr; /* diag address */ -+ uint32 fifodatalow; /* low 32bits of data */ -+ uint32 fifodatahigh; /* high 32bits of data */ -+ uint32 pad; /* reserved */ -+} dma32diag_t; ++static void ++_dma_rxreclaim(dma_info_t *di) ++{ ++ void *p; + -+/* -+ * DMA Descriptor -+ * Descriptors are only read by the hardware, never written back. -+ */ -+typedef volatile struct { -+ uint32 ctrl; /* misc control bits & bufcount */ -+ uint32 addr; /* data buffer address */ -+} dma32dd_t; ++ /* "unused local" warning suppression for OSLs that ++ * define PKTFREE() without using the di->osh arg ++ */ ++ di = di; + -+/* -+ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. -+ */ -+#define D32MAXRINGSZ 4096 -+#define D32RINGALIGN 4096 -+#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) ++ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); + -+/* transmit channel control */ -+#define XC_XE ((uint32)1 << 0) /* transmit enable */ -+#define XC_SE ((uint32)1 << 1) /* transmit suspend request */ -+#define XC_LE ((uint32)1 << 2) /* loopback enable */ -+#define XC_FL ((uint32)1 << 4) /* flush request */ -+#define XC_AE ((uint32)3 << 16) /* address extension bits */ -+#define XC_AE_SHIFT 16 ++ while ((p = _dma_getnextrxp(di, TRUE))) ++ PKTFREE(di->osh, p, FALSE); ++} + -+/* transmit descriptor table pointer */ -+#define XP_LD_MASK 0xfff /* last valid descriptor */ ++static void * ++_dma_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ if (di->nrxd == 0) ++ return (NULL); + -+/* transmit channel status */ -+#define XS_CD_MASK 0x0fff /* current descriptor pointer */ -+#define XS_XS_MASK 0xf000 /* transmit state */ -+#define XS_XS_SHIFT 12 -+#define XS_XS_DISABLED 0x0000 /* disabled */ -+#define XS_XS_ACTIVE 0x1000 /* active */ -+#define XS_XS_IDLE 0x2000 /* idle wait */ -+#define XS_XS_STOPPED 0x3000 /* stopped */ -+#define XS_XS_SUSP 0x4000 /* suspend pending */ -+#define XS_XE_MASK 0xf0000 /* transmit errors */ -+#define XS_XE_SHIFT 16 -+#define XS_XE_NOERR 0x00000 /* no error */ -+#define XS_XE_DPE 0x10000 /* descriptor protocol error */ -+#define XS_XE_DFU 0x20000 /* data fifo underrun */ -+#define XS_XE_BEBR 0x30000 /* bus error on buffer read */ -+#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */ -+#define XS_AD_MASK 0xfff00000 /* active descriptor */ -+#define XS_AD_SHIFT 20 ++ return dma32_getnextrxp(di, forceall); ++} + -+/* receive channel control */ -+#define RC_RE ((uint32)1 << 0) /* receive enable */ -+#define RC_RO_MASK 0xfe /* receive frame offset */ -+#define RC_RO_SHIFT 1 -+#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */ -+#define RC_AE ((uint32)3 << 16) /* address extension bits */ -+#define RC_AE_SHIFT 16 ++static void ++_dma_txblock(dma_info_t *di) ++{ ++ di->hnddma.txavail = 0; ++} + -+/* receive descriptor table pointer */ -+#define RP_LD_MASK 0xfff /* last valid descriptor */ ++static void ++_dma_txunblock(dma_info_t *di) ++{ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++} + -+/* receive channel status */ -+#define RS_CD_MASK 0x0fff /* current descriptor pointer */ -+#define RS_RS_MASK 0xf000 /* receive state */ -+#define RS_RS_SHIFT 12 -+#define RS_RS_DISABLED 0x0000 /* disabled */ -+#define RS_RS_ACTIVE 0x1000 /* active */ -+#define RS_RS_IDLE 0x2000 /* idle wait */ -+#define RS_RS_STOPPED 0x3000 /* reserved */ -+#define RS_RE_MASK 0xf0000 /* receive errors */ -+#define RS_RE_SHIFT 16 -+#define RS_RE_NOERR 0x00000 /* no error */ -+#define RS_RE_DPE 0x10000 /* descriptor protocol error */ -+#define RS_RE_DFO 0x20000 /* data fifo overflow */ -+#define RS_RE_BEBW 0x30000 /* bus error on buffer write */ -+#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */ -+#define RS_AD_MASK 0xfff00000 /* active descriptor */ -+#define RS_AD_SHIFT 20 ++static uint ++_dma_txactive(dma_info_t *di) ++{ ++ return (NTXDACTIVE(di->txin, di->txout)); ++} ++ ++static void ++_dma_counterreset(dma_info_t *di) ++{ ++ /* reset all software counter */ ++ di->hnddma.rxgiants = 0; ++ di->hnddma.rxnobuf = 0; ++ di->hnddma.txnobuf = 0; ++} ++ ++/* get the address of the var in order to change later */ ++static uintptr ++_dma_getvar(dma_info_t *di, char *name) ++{ ++ if (!strcmp(name, "&txavail")) ++ return ((uintptr) &(di->hnddma.txavail)); ++ else { ++ ASSERT(0); ++ } ++ return (0); ++} + -+/* fifoaddr */ -+#define FA_OFF_MASK 0xffff /* offset */ -+#define FA_SEL_MASK 0xf0000 /* select */ -+#define FA_SEL_SHIFT 16 -+#define FA_SEL_XDD 0x00000 /* transmit dma data */ -+#define FA_SEL_XDP 0x10000 /* transmit dma pointers */ -+#define FA_SEL_RDD 0x40000 /* receive dma data */ -+#define FA_SEL_RDP 0x50000 /* receive dma pointers */ -+#define FA_SEL_XFD 0x80000 /* transmit fifo data */ -+#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */ -+#define FA_SEL_RFD 0xc0000 /* receive fifo data */ -+#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */ -+#define FA_SEL_RSD 0xe0000 /* receive frame status data */ -+#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++void ++dma_txpioloopback(osl_t *osh, dma32regs_t *regs) ++{ ++ OR_REG(osh, ®s->control, XC_LE); ++} + -+/* descriptor control flags */ -+#define CTRL_BC_MASK 0x1fff /* buffer byte count */ -+#define CTRL_AE ((uint32)3 << 16) /* address extension bits */ -+#define CTRL_AE_SHIFT 16 -+#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */ -+#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */ -+#define CTRL_EOF ((uint32)1 << 30) /* end of frame */ -+#define CTRL_SOF ((uint32)1 << 31) /* start of frame */ + -+/* control flags in the range [27:20] are core-specific and not defined here */ -+#define CTRL_CORE_MASK 0x0ff00000 + -+/*** 64 bits addressing ***/ ++/* 32 bits DMA functions */ ++static void ++dma32_txinit(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); + -+/* dma registers per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint32 control; /* enable, et al */ -+ uint32 ptr; /* last descriptor posted to chip */ -+ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ -+ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ -+ uint32 status0; /* current descriptor, xmt state */ -+ uint32 status1; /* active descriptor, xmt error */ -+} dma64regs_t; ++ if (di->ntxd == 0) ++ return; + -+typedef volatile struct { -+ dma64regs_t tx; /* dma64 tx channel */ -+ dma64regs_t rx; /* dma64 rx channel */ -+} dma64regp_t; ++ di->txin = di->txout = 0; ++ di->hnddma.txavail = di->ntxd - 1; + -+typedef volatile struct { /* diag access */ -+ uint32 fifoaddr; /* diag address */ -+ uint32 fifodatalow; /* low 32bits of data */ -+ uint32 fifodatahigh; /* high 32bits of data */ -+ uint32 pad; /* reserved */ -+} dma64diag_t; ++ /* clear tx descriptor ring */ ++ BZERO_SM((void *)di->txd32, (di->ntxd * sizeof(dma32dd_t))); ++ W_REG(di->osh, &di->d32txregs->control, XC_XE); ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++} + -+/* -+ * DMA Descriptor -+ * Descriptors are only read by the hardware, never written back. -+ */ -+typedef volatile struct { -+ uint32 ctrl1; /* misc control bits & bufcount */ -+ uint32 ctrl2; /* buffer count and address extension */ -+ uint32 addrlow; /* memory address of the first byte of the date buffer, bits 31:0 */ -+ uint32 addrhigh; /* memory address of the first byte of the date buffer, bits 63:32 */ -+} dma64dd_t; ++static bool ++dma32_txenabled(dma_info_t *di) ++{ ++ uint32 xc; + -+/* -+ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. -+ */ -+#define D64MAXRINGSZ 8192 -+#define D64RINGALIGN 8192 -+#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) ++ /* If the chip is dead, it is not enabled :-) */ ++ xc = R_REG(di->osh, &di->d32txregs->control); ++ return ((xc != 0xffffffff) && (xc & XC_XE)); ++} + -+/* transmit channel control */ -+#define D64_XC_XE 0x00000001 /* transmit enable */ -+#define D64_XC_SE 0x00000002 /* transmit suspend request */ -+#define D64_XC_LE 0x00000004 /* loopback enable */ -+#define D64_XC_FL 0x00000010 /* flush request */ -+#define D64_XC_AE 0x00110000 /* address extension bits */ -+#define D64_XC_AE_SHIFT 16 ++static void ++dma32_txsuspend(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); + -+/* transmit descriptor table pointer */ -+#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ ++ if (di->ntxd == 0) ++ return; + -+/* transmit channel status */ -+#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ -+#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ -+#define D64_XS0_XS_SHIFT 28 -+#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ -+#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ -+#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ -+#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ -+#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ ++ OR_REG(di->osh, &di->d32txregs->control, XC_SE); ++} + -+#define D64_XS1_AD_MASK 0x0001ffff /* active descriptor */ -+#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ -+#define D64_XS1_XE_SHIFT 28 -+#define D64_XS1_XE_NOERR 0x00000000 /* no error */ -+#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ -+#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ -+#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ -+#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ -+#define D64_XS1_XE_COREE 0x50000000 /* core error */ ++static void ++dma32_txresume(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txresume\n", di->name)); + -+/* receive channel control */ -+#define D64_RC_RE 0x00000001 /* receive enable */ -+#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ -+#define D64_RC_RO_SHIFT 1 -+#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ -+#define D64_RC_AE 0x00110000 /* address extension bits */ -+#define D64_RC_AE_SHIFT 16 ++ if (di->ntxd == 0) ++ return; + -+/* receive descriptor table pointer */ -+#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ ++ AND_REG(di->osh, &di->d32txregs->control, ~XC_SE); ++} + -+/* receive channel status */ -+#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ -+#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ -+#define D64_RS0_RS_SHIFT 28 -+#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ -+#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ -+#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ -+#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ -+#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ ++static bool ++dma32_txsuspended(dma_info_t *di) ++{ ++ return (di->ntxd == 0) || ((R_REG(di->osh, &di->d32txregs->control) & XC_SE) == XC_SE); ++} + -+#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ -+#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ -+#define D64_RS1_RE_SHIFT 28 -+#define D64_RS1_RE_NOERR 0x00000000 /* no error */ -+#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ -+#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ -+#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ -+#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ -+#define D64_RS1_RE_COREE 0x50000000 /* core error */ ++static void ++dma32_txreclaim(dma_info_t *di, bool forceall) ++{ ++ void *p; + -+/* fifoaddr */ -+#define D64_FA_OFF_MASK 0xffff /* offset */ -+#define D64_FA_SEL_MASK 0xf0000 /* select */ -+#define D64_FA_SEL_SHIFT 16 -+#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ -+#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ -+#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ -+#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ -+#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ -+#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ -+#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ -+#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ -+#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ -+#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); + -+/* descriptor control flags 1 */ -+#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */ -+#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */ -+#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */ -+#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */ ++ while ((p = dma32_getnexttxp(di, forceall))) ++ PKTFREE(di->osh, p, TRUE); ++} + -+/* descriptor control flags 2 */ -+#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count mask */ -+#define D64_CTRL2_AE 0x00110000 /* address extension bits */ -+#define D64_CTRL2_AE_SHIFT 16 ++static bool ++dma32_txstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED); ++} + -+/* control flags in the range [27:20] are core-specific and not defined here */ -+#define D64_CTRL_CORE_MASK 0x0ff00000 ++static bool ++dma32_rxstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED); ++} + ++static bool ++dma32_alloc(dma_info_t *di, uint direction) ++{ ++ uint size; ++ uint ddlen; ++ void *va; + -+#endif /* _sbhnddma_h_ */ -diff -Naur linux.old/drivers/parport/Config.in linux.dev/drivers/parport/Config.in ---- linux.old/drivers/parport/Config.in 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/drivers/parport/Config.in 2006-04-06 15:34:15.000000000 +0200 -@@ -11,6 +11,7 @@ - tristate 'Parallel port support' CONFIG_PARPORT - if [ "$CONFIG_PARPORT" != "n" ]; then - dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT -+ dep_tristate ' Asus WL500g parallel port' CONFIG_PARPORT_SPLINK $CONFIG_PARPORT - if [ "$CONFIG_PARPORT_PC" != "n" -a "$CONFIG_SERIAL" != "n" ]; then - if [ "$CONFIG_SERIAL" = "m" ]; then - define_tristate CONFIG_PARPORT_PC_CML1 m -diff -Naur linux.old/drivers/parport/Makefile linux.dev/drivers/parport/Makefile ---- linux.old/drivers/parport/Makefile 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/drivers/parport/Makefile 2006-04-06 15:34:15.000000000 +0200 -@@ -22,6 +22,7 @@ - - obj-$(CONFIG_PARPORT) += parport.o - obj-$(CONFIG_PARPORT_PC) += parport_pc.o -+obj-$(CONFIG_PARPORT_SPLINK) += parport_splink.o - obj-$(CONFIG_PARPORT_PC_PCMCIA) += parport_cs.o - obj-$(CONFIG_PARPORT_AMIGA) += parport_amiga.o - obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o -diff -Naur linux.old/drivers/parport/parport_splink.c linux.dev/drivers/parport/parport_splink.c ---- linux.old/drivers/parport/parport_splink.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/parport/parport_splink.c 2006-04-06 15:34:15.000000000 +0200 -@@ -0,0 +1,345 @@ -+/* Low-level parallel port routines for the ASUS WL-500g built-in port -+ * -+ * Author: Nuno Grilo -+ * Based on parport_pc source -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++ ddlen = sizeof(dma32dd_t); + -+#define SPLINK_ADDRESS 0xBF800010 ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); + -+#undef DEBUG ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, D32RINGALIGN)) ++ size += D32RINGALIGN; + -+#ifdef DEBUG -+#define DPRINTK printk -+#else -+#define DPRINTK(stuff...) -+#endif + ++ if (direction == DMA_TX) { ++ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->txdpa, &di->tx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(ntxd) failed\n", ++ di->name)); ++ return FALSE; ++ } + -+/* __parport_splink_frob_control differs from parport_splink_frob_control in that -+ * it doesn't do any extra masking. */ -+static __inline__ unsigned char __parport_splink_frob_control (struct parport *p, -+ unsigned char mask, -+ unsigned char val) -+{ -+ struct parport_pc_private *priv = p->physport->private_data; -+ unsigned char *io = (unsigned char *) p->base; -+ unsigned char ctr = priv->ctr; -+#ifdef DEBUG_PARPORT -+ printk (KERN_DEBUG -+ "__parport_splink_frob_control(%02x,%02x): %02x -> %02x\n", -+ mask, val, ctr, ((ctr & ~mask) ^ val) & priv->ctr_writable); -+#endif -+ ctr = (ctr & ~mask) ^ val; -+ ctr &= priv->ctr_writable; /* only write writable bits. */ -+ *(io+2) = ctr; -+ priv->ctr = ctr; /* Update soft copy */ -+ return ctr; ++ di->txd32 = (dma32dd_t *) ROUNDUP((uintptr)va, D32RINGALIGN); ++ di->txdalign = (uint)((int8*)di->txd32 - (int8*)va); ++ di->txdpa += di->txdalign; ++ di->txdalloc = size; ++ ASSERT(ISALIGNED((uintptr)di->txd32, D32RINGALIGN)); ++ } else { ++ if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->rxdpa, &di->rx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(nrxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ di->rxd32 = (dma32dd_t *) ROUNDUP((uintptr)va, D32RINGALIGN); ++ di->rxdalign = (uint)((int8*)di->rxd32 - (int8*)va); ++ di->rxdpa += di->rxdalign; ++ di->rxdalloc = size; ++ ASSERT(ISALIGNED((uintptr)di->rxd32, D32RINGALIGN)); ++ } ++ ++ return TRUE; +} + ++static bool ++dma32_txreset(dma_info_t *di) ++{ ++ uint32 status; + ++ if (di->ntxd == 0) ++ return TRUE; + -+static void parport_splink_data_forward (struct parport *p) -+{ -+ DPRINTK(KERN_DEBUG "parport_splink: parport_data_forward called\n"); -+ __parport_splink_frob_control (p, 0x20, 0); -+} ++ /* suspend tx DMA first */ ++ W_REG(di->osh, &di->d32txregs->control, XC_SE); ++ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) ++ != XS_XS_DISABLED) && ++ (status != XS_XS_IDLE) && ++ (status != XS_XS_STOPPED), ++ (10000)); ++ ++ W_REG(di->osh, &di->d32txregs->control, 0); ++ SPINWAIT(((status = (R_REG(di->osh, ++ &di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED), ++ 10000); + -+static void parport_splink_data_reverse (struct parport *p) -+{ -+ DPRINTK(KERN_DEBUG "parport_splink: parport_data_forward called\n"); -+ __parport_splink_frob_control (p, 0x20, 0x20); -+} ++ /* wait for the last transaction to complete */ ++ OSL_DELAY(300); + -+/* -+static void parport_splink_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ DPRINTK(KERN_DEBUG "parport_splink: IRQ handler called\n"); -+ parport_generic_irq(irq, (struct parport *) dev_id, regs); ++ return (status == XS_XS_DISABLED); +} -+*/ + -+static void parport_splink_enable_irq(struct parport *p) ++static bool ++dma32_rxidle(dma_info_t *di) +{ -+ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_enable_irq called\n"); -+ __parport_splink_frob_control (p, 0x10, 0x10); ++ DMA_TRACE(("%s: dma_rxidle\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK) == ++ R_REG(di->osh, &di->d32rxregs->ptr)); +} + -+static void parport_splink_disable_irq(struct parport *p) ++static bool ++dma32_rxreset(dma_info_t *di) +{ -+ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_disable_irq called\n"); -+ __parport_splink_frob_control (p, 0x10, 0); ++ uint32 status; ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ W_REG(di->osh, &di->d32rxregs->control, 0); ++ SPINWAIT(((status = (R_REG(di->osh, ++ &di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED), ++ 10000); ++ ++ return (status == RS_RS_DISABLED); +} + -+static void parport_splink_init_state(struct pardevice *dev, struct parport_state *s) ++static bool ++dma32_rxenabled(dma_info_t *di) +{ -+ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_init_state called\n"); -+ s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0); -+ if (dev->irq_func && -+ dev->port->irq != PARPORT_IRQ_NONE) -+ /* Set ackIntEn */ -+ s->u.pc.ctr |= 0x10; ++ uint32 rc; ++ ++ rc = R_REG(di->osh, &di->d32rxregs->control); ++ return ((rc != 0xffffffff) && (rc & RC_RE)); +} + -+static void parport_splink_save_state(struct parport *p, struct parport_state *s) ++static bool ++dma32_txsuspendedidle(dma_info_t *di) +{ -+ const struct parport_pc_private *priv = p->physport->private_data; -+ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_save_state called\n"); -+ s->u.pc.ctr = priv->ctr; ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ if (!(R_REG(di->osh, &di->d32txregs->control) & XC_SE)) ++ return 0; ++ ++ if ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) ++ return 0; ++ ++ OSL_DELAY(2); ++ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); +} + -+static void parport_splink_restore_state(struct parport *p, struct parport_state *s) ++/* !! tx entry routine ++ * supports full 32bit dma engine buffer addressing so ++ * dma buffers can cross 4 Kbyte page boundaries. ++ */ ++static int ++dma32_txfast(dma_info_t *di, void *p0, bool commit) +{ -+ struct parport_pc_private *priv = p->physport->private_data; -+ unsigned char *io = (unsigned char *) p->base; -+ unsigned char ctr = s->u.pc.ctr; ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint txout; ++ uint32 flags = 0; ++ uint32 pa; + -+ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_restore_state called\n"); -+ *(io+2) = ctr; -+ priv->ctr = ctr; -+} ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); + -+static void parport_splink_setup_interrupt(void) { -+ return; -+} ++ txout = di->txout; + -+static void parport_splink_write_data(struct parport *p, unsigned char d) { -+ DPRINTK(KERN_DEBUG "parport_splink: write data called\n"); -+ unsigned char *io = (unsigned char *) p->base; -+ *io = d; -+} ++ /* ++ * Walk the chain of packet buffers ++ * allocating and initializing transmit descriptor entries. ++ */ ++ for (p = p0; p; p = next) { ++ data = PKTDATA(di->osh, p); ++ len = PKTLEN(di->osh, p); ++ next = PKTNEXT(di->osh, p); + -+static unsigned char parport_splink_read_data(struct parport *p) { -+ DPRINTK(KERN_DEBUG "parport_splink: read data called\n"); -+ unsigned char *io = (unsigned char *) p->base; -+ return *io; -+} ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; + -+static void parport_splink_write_control(struct parport *p, unsigned char d) -+{ -+ const unsigned char wm = (PARPORT_CONTROL_STROBE | -+ PARPORT_CONTROL_AUTOFD | -+ PARPORT_CONTROL_INIT | -+ PARPORT_CONTROL_SELECT); ++ if (len == 0) ++ continue; + -+ DPRINTK(KERN_DEBUG "parport_splink: write control called\n"); -+ /* Take this out when drivers have adapted to the newer interface. */ -+ if (d & 0x20) { -+ printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n", -+ p->name, p->cad->name); -+ parport_splink_data_reverse (p); ++ /* get physical address of buffer start */ ++ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); ++ ++ flags = 0; ++ if (p == p0) ++ flags |= CTRL_SOF; ++ if (next == NULL) ++ flags |= (CTRL_IOC | CTRL_EOF); ++ if (txout == (di->ntxd - 1)) ++ flags |= CTRL_EOT; ++ ++ dma32_dd_upd(di, di->txd32, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ txout = NEXTTXD(txout); + } + -+ __parport_splink_frob_control (p, wm, d & wm); -+} ++ /* if last txd eof not set, fix it */ ++ if (!(flags & CTRL_EOF)) ++ W_SM(&di->txd32[PREVTXD(txout)].ctrl, BUS_SWAP32(flags | CTRL_IOC | CTRL_EOF)); + -+static unsigned char parport_splink_read_control(struct parport *p) -+{ -+ const unsigned char wm = (PARPORT_CONTROL_STROBE | -+ PARPORT_CONTROL_AUTOFD | -+ PARPORT_CONTROL_INIT | -+ PARPORT_CONTROL_SELECT); -+ DPRINTK(KERN_DEBUG "parport_splink: read control called\n"); -+ const struct parport_pc_private *priv = p->physport->private_data; -+ return priv->ctr & wm; /* Use soft copy */ ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; ++ ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* kick the chip */ ++ if (commit) ++ W_REG(di->osh, &di->d32txregs->ptr, I2B(txout, dma32dd_t)); ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); ++ PKTFREE(di->osh, p0, TRUE); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ return (-1); +} + -+static unsigned char parport_splink_frob_control (struct parport *p, unsigned char mask, -+ unsigned char val) ++/* ++ * Reclaim next completed txd (txds if using chained buffers) and ++ * return associated packet. ++ * If 'force' is true, reclaim txd(s) and return associated packet ++ * regardless of the value of the hardware "curr" pointer. ++ */ ++static void * ++dma32_getnexttxp(dma_info_t *di, bool forceall) +{ -+ const unsigned char wm = (PARPORT_CONTROL_STROBE | -+ PARPORT_CONTROL_AUTOFD | -+ PARPORT_CONTROL_INIT | -+ PARPORT_CONTROL_SELECT); ++ uint start, end, i; ++ void *txp; + -+ DPRINTK(KERN_DEBUG "parport_splink: frob control called\n"); -+ /* Take this out when drivers have adapted to the newer interface. */ -+ if (mask & 0x20) { -+ printk (KERN_DEBUG "%s (%s): use data_%s for this!\n", -+ p->name, p->cad->name, -+ (val & 0x20) ? "reverse" : "forward"); -+ if (val & 0x20) -+ parport_splink_data_reverse (p); -+ else -+ parport_splink_data_forward (p); ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ txp = NULL; ++ ++ start = di->txin; ++ if (forceall) ++ end = di->txout; ++ else ++ end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; ++ ++ for (i = start; i != end && !txp; i = NEXTTXD(i)) { ++ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->txd32[i].addr)) - di->dataoffsetlow), ++ (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) & CTRL_BC_MASK), ++ DMA_TX, di->txp[i]); ++ ++ W_SM(&di->txd32[i].addr, 0xdeadbeef); ++ txp = di->txp[i]; ++ di->txp[i] = NULL; + } + -+ /* Restrict mask and val to control lines. */ -+ mask &= wm; -+ val &= wm; ++ di->txin = i; + -+ return __parport_splink_frob_control (p, mask, val); -+} ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+static unsigned char parport_splink_read_status(struct parport *p) -+{ -+ DPRINTK(KERN_DEBUG "parport_splink: read status called\n"); -+ unsigned char *io = (unsigned char *) p->base; -+ return *(io+1); ++ return (txp); ++ ++bogus: ++/* ++ DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", ++ start, end, di->txout, forceall)); ++*/ ++ return (NULL); +} + -+static void parport_splink_inc_use_count(void) ++static void * ++dma32_getnextrxp(dma_info_t *di, bool forceall) +{ -+#ifdef MODULE -+ MOD_INC_USE_COUNT; -+#endif -+} ++ uint i; ++ void *rxp; ++ ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma32_rxenabled(di)); ++ ++ i = di->rxin; ++ ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); ++ ++ /* ignore curr if forceall */ ++ if (!forceall && (i == B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t))) ++ return (NULL); ++ ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; ++ ++ /* clear this packet from the descriptor ring */ ++ DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) - di->dataoffsetlow), ++ di->rxbufsize, DMA_RX, rxp); ++ ++ W_SM(&di->rxd32[i].addr, 0xdeadbeef); ++ ++ di->rxin = NEXTRXD(i); + -+static void parport_splink_dec_use_count(void) -+{ -+#ifdef MODULE -+ MOD_DEC_USE_COUNT; -+#endif ++ return (rxp); +} + -+static struct parport_operations parport_splink_ops = ++/* ++ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). ++ */ ++static void ++dma32_txrotate(dma_info_t *di) +{ -+ parport_splink_write_data, -+ parport_splink_read_data, -+ -+ parport_splink_write_control, -+ parport_splink_read_control, -+ parport_splink_frob_control, ++ uint ad; ++ uint nactive; ++ uint rot; ++ uint old, new; ++ uint32 w; ++ uint first, last; + -+ parport_splink_read_status, ++ ASSERT(dma32_txsuspendedidle(di)); + -+ parport_splink_enable_irq, -+ parport_splink_disable_irq, ++ nactive = _dma_txactive(di); ++ ad = B2I(((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t); ++ rot = TXD(ad - di->txin); + -+ parport_splink_data_forward, -+ parport_splink_data_reverse, ++ ASSERT(rot < di->ntxd); + -+ parport_splink_init_state, -+ parport_splink_save_state, -+ parport_splink_restore_state, ++ /* full-ring case is a lot harder - don't worry about this */ ++ if (rot >= (di->ntxd - nactive)) { ++ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); ++ return; ++ } + -+ parport_splink_inc_use_count, -+ parport_splink_dec_use_count, ++ first = di->txin; ++ last = PREVTXD(di->txout); + -+ parport_ieee1284_epp_write_data, -+ parport_ieee1284_epp_read_data, -+ parport_ieee1284_epp_write_addr, -+ parport_ieee1284_epp_read_addr, ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); + -+ parport_ieee1284_ecp_write_data, -+ parport_ieee1284_ecp_read_data, -+ parport_ieee1284_ecp_write_addr, ++ /* ++ * Move the tx dma descriptor. ++ * EOT is set only in the last entry in the ring. ++ */ ++ w = BUS_SWAP32(R_SM(&di->txd32[old].ctrl)) & ~CTRL_EOT; ++ if (new == (di->ntxd - 1)) ++ w |= CTRL_EOT; ++ W_SM(&di->txd32[new].ctrl, BUS_SWAP32(w)); ++ W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr)); + -+ parport_ieee1284_write_compat, -+ parport_ieee1284_read_nibble, -+ parport_ieee1284_read_byte, -+}; ++ /* zap the old tx dma descriptor address field */ ++ W_SM(&di->txd32[old].addr, BUS_SWAP32(0xdeadbeef)); + -+/* --- Initialisation code -------------------------------- */ ++ /* move the corresponding txp[] entry */ ++ ASSERT(di->txp[new] == NULL); ++ di->txp[new] = di->txp[old]; ++ di->txp[old] = NULL; ++ } + -+static struct parport *parport_splink_probe_port (unsigned long int base) -+{ -+ struct parport_pc_private *priv; -+ struct parport_operations *ops; -+ struct parport *p; ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+ if (check_mem_region(base, 3)) { -+ printk (KERN_DEBUG "parport (0x%lx): iomem region not available\n", base); -+ return NULL; -+ } -+ priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL); -+ if (!priv) { -+ printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); -+ return NULL; -+ } -+ ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); -+ if (!ops) { -+ printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n", -+ base); -+ kfree (priv); -+ return NULL; -+ } -+ memcpy (ops, &parport_splink_ops, sizeof (struct parport_operations)); -+ priv->ctr = 0xc; -+ priv->ctr_writable = 0xff; ++ /* kick the chip */ ++ W_REG(di->osh, &di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); ++} + -+ if (!(p = parport_register_port(base, PARPORT_IRQ_NONE, -+ PARPORT_DMA_NONE, ops))) { -+ printk (KERN_DEBUG "parport (0x%lx): registration failed!\n", -+ base); -+ kfree (priv); -+ kfree (ops); -+ return NULL; -+ } + -+ p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; -+ p->size = (p->modes & PARPORT_MODE_EPP)?8:3; -+ p->private_data = priv; ++uint ++dma_addrwidth(sb_t *sbh, void *dmaregs) ++{ ++ dma32regs_t *dma32regs; ++ osl_t *osh; + -+ parport_proc_register(p); -+ request_mem_region (p->base, 3, p->name); ++ osh = sb_osh(sbh); + -+ /* Done probing. Now put the port into a sensible start-up state. */ -+ parport_splink_write_data(p, 0); -+ parport_splink_data_forward (p); ++ /* Start checking for 32-bit / 30-bit addressing */ ++ dma32regs = (dma32regs_t *)dmaregs; + -+ /* Now that we've told the sharing engine about the port, and -+ found out its characteristics, let the high-level drivers -+ know about it. */ -+ parport_announce_port (p); ++ /* For System Backplane, PCIE bus or addrext feature, 32-bits ok */ ++ if ((BUSTYPE(sbh->bustype) == SB_BUS) || ++ ((BUSTYPE(sbh->bustype) == PCI_BUS) && sbh->buscoretype == SB_PCIE) || ++ (_dma32_addrext(osh, dma32regs))) ++ return (DMADDRWIDTH_32); + -+ DPRINTK(KERN_DEBUG "parport (0x%lx): init ok!\n", -+ base); -+ return p; ++ /* Fallthru */ ++ return (DMADDRWIDTH_30); +} +diff -urN linux.old/drivers/net/wl/hnddma.h linux.dev/drivers/net/wl/hnddma.h +--- linux.old/drivers/net/wl/hnddma.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/hnddma.h 2006-04-28 02:20:44.000000000 +0200 +@@ -0,0 +1,156 @@ ++/* ++ * Generic Broadcom Home Networking Division (HND) DMA engine SW interface ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * $Id: hnddma.h,v 1.1.1.13 2006/04/08 06:13:39 honor Exp $ ++ */ + -+static void parport_splink_unregister_port(struct parport *p) { -+ struct parport_pc_private *priv = p->private_data; -+ struct parport_operations *ops = p->ops; ++#ifndef _hnddma_h_ ++#define _hnddma_h_ + -+ if (p->irq != PARPORT_IRQ_NONE) -+ free_irq(p->irq, p); -+ release_mem_region(p->base, 3); -+ parport_proc_unregister(p); -+ kfree (priv); -+ parport_unregister_port(p); -+ kfree (ops); -+} ++typedef const struct hnddma_pub hnddma_t; ++ ++/* dma function type */ ++typedef void (*di_detach_t)(hnddma_t *dmah); ++typedef bool (*di_txreset_t)(hnddma_t *dmah); ++typedef bool (*di_rxreset_t)(hnddma_t *dmah); ++typedef bool (*di_rxidle_t)(hnddma_t *dmah); ++typedef void (*di_txinit_t)(hnddma_t *dmah); ++typedef bool (*di_txenabled_t)(hnddma_t *dmah); ++typedef void (*di_rxinit_t)(hnddma_t *dmah); ++typedef void (*di_txsuspend_t)(hnddma_t *dmah); ++typedef void (*di_txresume_t)(hnddma_t *dmah); ++typedef bool (*di_txsuspended_t)(hnddma_t *dmah); ++typedef bool (*di_txsuspendedidle_t)(hnddma_t *dmah); ++typedef int (*di_txfast_t)(hnddma_t *dmah, void *p, bool commit); ++typedef void (*di_fifoloopbackenable_t)(hnddma_t *dmah); ++typedef bool (*di_txstopped_t)(hnddma_t *dmah); ++typedef bool (*di_rxstopped_t)(hnddma_t *dmah); ++typedef bool (*di_rxenable_t)(hnddma_t *dmah); ++typedef bool (*di_rxenabled_t)(hnddma_t *dmah); ++typedef void* (*di_rx_t)(hnddma_t *dmah); ++typedef void (*di_rxfill_t)(hnddma_t *dmah); ++typedef void (*di_txreclaim_t)(hnddma_t *dmah, bool forceall); ++typedef void (*di_rxreclaim_t)(hnddma_t *dmah); ++typedef uintptr (*di_getvar_t)(hnddma_t *dmah, char *name); ++typedef void* (*di_getnexttxp_t)(hnddma_t *dmah, bool forceall); ++typedef void* (*di_getnextrxp_t)(hnddma_t *dmah, bool forceall); ++typedef void* (*di_peeknexttxp_t)(hnddma_t *dmah); ++typedef void (*di_txblock_t)(hnddma_t *dmah); ++typedef void (*di_txunblock_t)(hnddma_t *dmah); ++typedef uint (*di_txactive_t)(hnddma_t *dmah); ++typedef void (*di_txrotate_t)(hnddma_t *dmah); ++typedef void (*di_counterreset_t)(hnddma_t *dmah); ++typedef char* (*di_dump_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef char* (*di_dumptx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef char* (*di_dumprx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++ ++/* dma opsvec */ ++typedef struct di_fcn_s { ++ di_detach_t detach; ++ di_txinit_t txinit; ++ di_txreset_t txreset; ++ di_txenabled_t txenabled; ++ di_txsuspend_t txsuspend; ++ di_txresume_t txresume; ++ di_txsuspended_t txsuspended; ++ di_txsuspendedidle_t txsuspendedidle; ++ di_txfast_t txfast; ++ di_txstopped_t txstopped; ++ di_txreclaim_t txreclaim; ++ di_getnexttxp_t getnexttxp; ++ di_peeknexttxp_t peeknexttxp; ++ di_txblock_t txblock; ++ di_txunblock_t txunblock; ++ di_txactive_t txactive; ++ di_txrotate_t txrotate; ++ ++ di_rxinit_t rxinit; ++ di_rxreset_t rxreset; ++ di_rxidle_t rxidle; ++ di_rxstopped_t rxstopped; ++ di_rxenable_t rxenable; ++ di_rxenabled_t rxenabled; ++ di_rx_t rx; ++ di_rxfill_t rxfill; ++ di_rxreclaim_t rxreclaim; ++ di_getnextrxp_t getnextrxp; ++ ++ di_fifoloopbackenable_t fifoloopbackenable; ++ di_getvar_t d_getvar; ++ di_counterreset_t counterreset; ++ di_dump_t dump; ++ di_dumptx_t dumptx; ++ di_dumprx_t dumprx; ++ uint endnum; ++} di_fcn_t; + ++/* ++ * Exported data structure (read-only) ++ */ ++/* export structure */ ++struct hnddma_pub { ++ di_fcn_t di_fn; /* DMA function pointers */ ++ uint txavail; /* # free tx descriptors */ + -+int parport_splink_init(void) -+{ -+ int ret; -+ -+ DPRINTK(KERN_DEBUG "parport_splink init called\n"); -+ parport_splink_setup_interrupt(); -+ ret = !parport_splink_probe_port(SPLINK_ADDRESS); -+ -+ return ret; -+} ++ /* rx error counters */ ++ uint rxgiants; /* rx giant frames */ ++ uint rxnobuf; /* rx out of dma descriptors */ ++ /* tx error counters */ ++ uint txnobuf; /* tx out of dma descriptors */ ++}; + -+void parport_splink_cleanup(void) { -+ struct parport *p = parport_enumerate(), *tmp; -+ DPRINTK(KERN_DEBUG "parport_splink cleanup called\n"); -+ if (p->size) { -+ if (p->modes & PARPORT_MODE_PCSPP) { -+ while(p) { -+ tmp = p->next; -+ parport_splink_unregister_port(p); -+ p = tmp; -+ } -+ } -+ } -+} + -+MODULE_AUTHOR("Nuno Grilo "); -+MODULE_DESCRIPTION("Parport Driver for ASUS WL-500g router builtin Port"); -+MODULE_SUPPORTED_DEVICE("ASUS WL-500g builtin Parallel Port"); -+MODULE_LICENSE("GPL"); ++extern hnddma_t * dma_attach(osl_t *osh, char *name, sb_t *sbh, void *dmaregstx, void *dmaregsrx, ++ uint ntxd, uint nrxd, uint rxbufsize, uint nrxpost, uint rxoffset, ++ uint *msg_level); ++#define dma_detach(di) ((di)->di_fn.detach(di)) ++#define dma_txreset(di) ((di)->di_fn.txreset(di)) ++#define dma_rxreset(di) ((di)->di_fn.rxreset(di)) ++#define dma_rxidle(di) ((di)->di_fn.rxidle(di)) ++#define dma_txinit(di) ((di)->di_fn.txinit(di)) ++#define dma_txenabled(di) ((di)->di_fn.txenabled(di)) ++#define dma_rxinit(di) ((di)->di_fn.rxinit(di)) ++#define dma_txsuspend(di) ((di)->di_fn.txsuspend(di)) ++#define dma_txresume(di) ((di)->di_fn.txresume(di)) ++#define dma_txsuspended(di) ((di)->di_fn.txsuspended(di)) ++#define dma_txsuspendedidle(di) ((di)->di_fn.txsuspendedidle(di)) ++#define dma_txfast(di, p, commit) ((di)->di_fn.txfast(di, p, commit)) ++#define dma_fifoloopbackenable(di) ((di)->di_fn.fifoloopbackenable(di)) ++#define dma_txstopped(di) ((di)->di_fn.txstopped(di)) ++#define dma_rxstopped(di) ((di)->di_fn.rxstopped(di)) ++#define dma_rxenable(di) ((di)->di_fn.rxenable(di)) ++#define dma_rxenabled(di) ((di)->di_fn.rxenabled(di)) ++#define dma_rx(di) ((di)->di_fn.rx(di)) ++#define dma_rxfill(di) ((di)->di_fn.rxfill(di)) ++#define dma_txreclaim(di, forceall) ((di)->di_fn.txreclaim(di, forceall)) ++#define dma_rxreclaim(di) ((di)->di_fn.rxreclaim(di)) ++#define dma_getvar(di, name) ((di)->di_fn.d_getvar(di, name)) ++#define dma_getnexttxp(di, forceall) ((di)->di_fn.getnexttxp(di, forceall)) ++#define dma_getnextrxp(di, forceall) ((di)->di_fn.getnextrxp(di, forceall)) ++#define dma_peeknexttxp(di) ((di)->di_fn.peeknexttxp(di)) ++#define dma_txblock(di) ((di)->di_fn.txblock(di)) ++#define dma_txunblock(di) ((di)->di_fn.txunblock(di)) ++#define dma_txactive(di) ((di)->di_fn.txactive(di)) ++#define dma_txrotate(di) ((di)->di_fn.txrotate(di)) ++#define dma_counterreset(di) ((di)->di_fn.counterreset(di)) ++ ++#define DMA_DUMP_SIZE 2048 ++/* return addresswidth allowed ++ * This needs to be done after SB attach but before dma attach. ++ * SB attach provides ability to probe backplane and dma core capabilities ++ * This info is needed by DMA_ALLOC_CONSISTENT in dma attach ++ */ ++extern uint dma_addrwidth(sb_t *sbh, void *dmaregs); + -+module_init(parport_splink_init) -+module_exit(parport_splink_cleanup) ++/* pio helpers */ ++void dma_txpioloopback(osl_t *osh, dma32regs_t *); + -diff -Naur linux.old/drivers/pcmcia/Makefile linux.dev/drivers/pcmcia/Makefile ---- linux.old/drivers/pcmcia/Makefile 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/drivers/pcmcia/Makefile 2006-04-06 15:34:15.000000000 +0200 -@@ -74,6 +74,10 @@ - au1000_ss-objs-$(CONFIG_MIPS_HYDROGEN3) += au1000_hydrogen3.o - au1000_ss-objs-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o - -+obj-$(CONFIG_PCMCIA_BCM4710) += bcm4710_ss.o -+bcm4710_ss-objs := bcm4710_generic.o -+bcm4710_ss-objs += bcm4710_pcmcia.o -+ - obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o - obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o - obj-$(CONFIG_PCMCIA_SIBYTE) += sibyte_generic.o -@@ -112,5 +116,8 @@ - au1x00_ss.o: $(au1000_ss-objs-y) - $(LD) -r -o $@ $(au1000_ss-objs-y) - -+bcm4710_ss.o: $(bcm4710_ss-objs) -+ $(LD) -r -o $@ $(bcm4710_ss-objs) -+ - yenta_socket.o: $(yenta_socket-objs) - $(LD) $(LD_RFLAG) -r -o $@ $(yenta_socket-objs) -diff -Naur linux.old/drivers/pcmcia/bcm4710_generic.c linux.dev/drivers/pcmcia/bcm4710_generic.c ---- linux.old/drivers/pcmcia/bcm4710_generic.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/pcmcia/bcm4710_generic.c 2006-04-06 15:34:15.000000000 +0200 -@@ -0,0 +1,912 @@ ++#endif /* _hnddma_h_ */ +diff -urN linux.old/drivers/net/wl/linux_osl.c linux.dev/drivers/net/wl/linux_osl.c +--- linux.old/drivers/net/wl/linux_osl.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/linux_osl.c 2006-04-28 02:29:46.000000000 +0200 +@@ -0,0 +1,269 @@ +/* ++ * Linux OS Independent Layer + * -+ * bcm47xx pcmcia driver -+ * -+ * Copyright 2004, Broadcom Corporation ++ * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -20623,1301 +18719,1202 @@ diff -Naur linux.old/drivers/pcmcia/bcm4710_generic.c linux.dev/drivers/pcmcia/b + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * Based on sa1100_generic.c from www.handhelds.org, -+ * and au1000_generic.c from oss.sgi.com. -+ * -+ * $Id: bcm4710_generic.c,v 1.1 2005/03/16 13:50:00 wbx Exp $ ++ * $Id: linux_osl.c,v 1.1.1.14 2006/04/08 06:13:39 honor Exp $ + */ ++ ++#define LINUX_OSL ++ ++#include ++#include +#include -+#include -+#include ++#include ++#include ++#include ++#include "linux_osl.h" ++#include +#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#ifdef mips ++#include ++#endif /* mips */ ++#include + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "cs_internal.h" ++#define PCI_CFG_RETRY 10 ++ ++#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognise osh */ ++#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */ ++ ++typedef struct bcm_mem_link { ++ struct bcm_mem_link *prev; ++ struct bcm_mem_link *next; ++ uint size; ++ int line; ++ char file[BCM_MEM_FILENAME_LEN]; ++} bcm_mem_link_t; ++ ++static int16 linuxbcmerrormap[] = \ ++{ 0, /* 0 */ ++ -EINVAL, /* BCME_ERROR */ ++ -EINVAL, /* BCME_BADARG */ ++ -EINVAL, /* BCME_BADOPTION */ ++ -EINVAL, /* BCME_NOTUP */ ++ -EINVAL, /* BCME_NOTDOWN */ ++ -EINVAL, /* BCME_NOTAP */ ++ -EINVAL, /* BCME_NOTSTA */ ++ -EINVAL, /* BCME_BADKEYIDX */ ++ -EINVAL, /* BCME_RADIOOFF */ ++ -EINVAL, /* BCME_NOTBANDLOCKED */ ++ -EINVAL, /* BCME_NOCLK */ ++ -EINVAL, /* BCME_BADRATESET */ ++ -EINVAL, /* BCME_BADBAND */ ++ -E2BIG, /* BCME_BUFTOOSHORT */ ++ -E2BIG, /* BCME_BUFTOOLONG */ ++ -EBUSY, /* BCME_BUSY */ ++ -EINVAL, /* BCME_NOTASSOCIATED */ ++ -EINVAL, /* BCME_BADSSIDLEN */ ++ -EINVAL, /* BCME_OUTOFRANGECHAN */ ++ -EINVAL, /* BCME_BADCHAN */ ++ -EFAULT, /* BCME_BADADDR */ ++ -ENOMEM, /* BCME_NORESOURCE */ ++ -EOPNOTSUPP, /* BCME_UNSUPPORTED */ ++ -EMSGSIZE, /* BCME_BADLENGTH */ ++ -EINVAL, /* BCME_NOTREADY */ ++ -EPERM, /* BCME_NOTPERMITTED */ ++ -ENOMEM, /* BCME_NOMEM */ ++ -EINVAL, /* BCME_ASSOCIATED */ ++ -ERANGE, /* BCME_RANGE */ ++ -EINVAL, /* BCME_NOTFOUND */ ++ -EINVAL, /* BCME_WME_NOT_ENABLED */ ++ -EINVAL, /* BCME_TSPEC_NOTFOUND */ ++ -EINVAL, /* BCME_ACM_NOTSUPPORTED */ ++ -EINVAL, /* BCME_NOT_WME_ASSOCIATION */ ++ -EIO, /* BCME_SDIO_ERROR */ ++ -ENODEV /* BCME_DONGLE_DOWN */ ++}; + -+#include -+#include -+#include ++/* translate bcmerrors into linux errors */ ++int ++osl_error(int bcmerror) ++{ ++ int abs_bcmerror; ++ int array_size = ARRAYSIZE(linuxbcmerrormap); + -+#include -+#include -+#include ++ abs_bcmerror = ABS(bcmerror); + -+#include "bcm4710pcmcia.h" ++ if (bcmerror > 0) ++ abs_bcmerror = 0; + -+#ifdef PCMCIA_DEBUG -+static int pc_debug = PCMCIA_DEBUG; -+#endif ++ else if (abs_bcmerror >= array_size) ++ abs_bcmerror = BCME_ERROR; + -+MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm47xx Socket Controller"); ++ return linuxbcmerrormap[abs_bcmerror]; ++} + -+/* This structure maintains housekeeping state for each socket, such -+ * as the last known values of the card detect pins, or the Card Services -+ * callback value associated with the socket: -+ */ -+static struct bcm47xx_pcmcia_socket *pcmcia_socket; -+static int socket_count; ++osl_t * ++osl_attach(void *pdev, bool pkttag) ++{ ++ osl_t *osh; + ++ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); ++ ASSERT(osh); + -+/* Returned by the low-level PCMCIA interface: */ -+static struct pcmcia_low_level *pcmcia_low_level; ++ bzero(osh, sizeof(osl_t)); + -+/* Event poll timer structure */ -+static struct timer_list poll_timer; ++ /* ++ * check the cases where ++ * 1.Error code Added to bcmerror table, but forgot to add it to the OS ++ * dependent error code ++ * 2. Error code is added to the bcmerror table, but forgot to add the ++ * corresponding errorstring(dummy call to bcmerrorstr) ++ */ ++ bcmerrorstr(0); ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); + ++ osh->magic = OS_HANDLE_MAGIC; ++ osh->malloced = 0; ++ osh->failed = 0; ++ osh->dbgmem_list = NULL; ++ osh->pdev = pdev; ++ osh->pub.pkttag = pkttag; + -+/* Prototypes for routines which are used internally: */ ++ return osh; ++} + -+static int bcm47xx_pcmcia_driver_init(void); -+static void bcm47xx_pcmcia_driver_shutdown(void); -+static void bcm47xx_pcmcia_task_handler(void *data); -+static void bcm47xx_pcmcia_poll_event(unsigned long data); -+static void bcm47xx_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs); -+static struct tq_struct bcm47xx_pcmcia_task; ++void ++osl_detach(osl_t *osh) ++{ ++ if (osh == NULL) ++ return; + -+#ifdef CONFIG_PROC_FS -+static int bcm47xx_pcmcia_proc_status(char *buf, char **start, -+ off_t pos, int count, int *eof, void *data); -+#endif ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ kfree(osh); ++} + ++/* Return a new packet. zero out pkttag */ ++void* ++osl_pktget(osl_t *osh, uint len, bool send) ++{ ++ struct sk_buff *skb; + -+/* Prototypes for operations which are exported to the -+ * in-kernel PCMCIA core: -+ */ ++ if ((skb = dev_alloc_skb(len))) { ++ skb_put(skb, len); ++ skb->priority = 0; + -+static int bcm47xx_pcmcia_init(unsigned int sock); -+static int bcm47xx_pcmcia_suspend(unsigned int sock); -+static int bcm47xx_pcmcia_register_callback(unsigned int sock, -+ void (*handler)(void *, unsigned int), void *info); -+static int bcm47xx_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap); -+static int bcm47xx_pcmcia_get_status(unsigned int sock, u_int *value); -+static int bcm47xx_pcmcia_get_socket(unsigned int sock, socket_state_t *state); -+static int bcm47xx_pcmcia_set_socket(unsigned int sock, socket_state_t *state); -+static int bcm47xx_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *io); -+static int bcm47xx_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *io); -+static int bcm47xx_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *mem); -+static int bcm47xx_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *mem); -+#ifdef CONFIG_PROC_FS -+static void bcm47xx_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base); -+#endif ++#ifdef BCMDBG_PKT ++ pktlist_add(&(osh->pktlist), (void *) skb); ++#endif /* BCMDBG_PKT */ + -+static struct pccard_operations bcm47xx_pcmcia_operations = { -+ bcm47xx_pcmcia_init, -+ bcm47xx_pcmcia_suspend, -+ bcm47xx_pcmcia_register_callback, -+ bcm47xx_pcmcia_inquire_socket, -+ bcm47xx_pcmcia_get_status, -+ bcm47xx_pcmcia_get_socket, -+ bcm47xx_pcmcia_set_socket, -+ bcm47xx_pcmcia_get_io_map, -+ bcm47xx_pcmcia_set_io_map, -+ bcm47xx_pcmcia_get_mem_map, -+ bcm47xx_pcmcia_set_mem_map, -+#ifdef CONFIG_PROC_FS -+ bcm47xx_pcmcia_proc_setup -+#endif -+}; ++ osh->pub.pktalloced++; ++ } + ++ return ((void*) skb); ++} + -+/* -+ * bcm47xx_pcmcia_driver_init() -+ * -+ * This routine performs a basic sanity check to ensure that this -+ * kernel has been built with the appropriate board-specific low-level -+ * PCMCIA support, performs low-level PCMCIA initialization, registers -+ * this socket driver with Card Services, and then spawns the daemon -+ * thread which is the real workhorse of the socket driver. -+ * -+ * Please see linux/Documentation/arm/SA1100/PCMCIA for more information -+ * on the low-level kernel interface. -+ * -+ * Returns: 0 on success, -1 on error -+ */ -+static int __init bcm47xx_pcmcia_driver_init(void) ++/* Free the driver packet. Free the tag if present */ ++void ++osl_pktfree(osl_t *osh, void *p) +{ -+ servinfo_t info; -+ struct pcmcia_init pcmcia_init; -+ struct pcmcia_state state; -+ unsigned int i; -+ unsigned long tmp; -+ -+ -+ printk("\nBCM47XX PCMCIA (CS release %s)\n", CS_RELEASE); ++ struct sk_buff *skb, *nskb; + -+ CardServices(GetCardServicesInfo, &info); ++ skb = (struct sk_buff*) p; + -+ if (info.Revision != CS_RELEASE_CODE) { -+ printk(KERN_ERR "Card Services release codes do not match\n"); -+ return -1; -+ } ++ /* perversion: we use skb->next to chain multi-skb packets */ ++ while (skb) { ++ nskb = skb->next; ++ skb->next = NULL; + -+#ifdef CONFIG_BCM4710 -+ pcmcia_low_level=&bcm4710_pcmcia_ops; -+#else -+#error Unsupported Broadcom BCM47XX board. -+#endif ++#ifdef BCMDBG_PKT ++ pktlist_remove(&(osh->pktlist), (void *) skb); ++#endif /* BCMDBG_PKT */ + -+ pcmcia_init.handler=bcm47xx_pcmcia_interrupt; ++ if (skb->destructor) { ++ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if destructor exists ++ */ ++ dev_kfree_skb_any(skb); ++ } else { ++ /* can free immediately (even in_irq()) if destructor does not exist */ ++ dev_kfree_skb(skb); ++ } + -+ if ((socket_count = pcmcia_low_level->init(&pcmcia_init)) < 0) { -+ printk(KERN_ERR "Unable to initialize PCMCIA service.\n"); -+ return -EIO; -+ } else { -+ printk("\t%d PCMCIA sockets initialized.\n", socket_count); -+ } ++ osh->pub.pktalloced--; + -+ pcmcia_socket = -+ kmalloc(sizeof(struct bcm47xx_pcmcia_socket) * socket_count, -+ GFP_KERNEL); -+ memset(pcmcia_socket, 0, -+ sizeof(struct bcm47xx_pcmcia_socket) * socket_count); -+ if (!pcmcia_socket) { -+ printk(KERN_ERR "Card Services can't get memory \n"); -+ return -1; -+ } -+ -+ for (i = 0; i < socket_count; i++) { -+ if (pcmcia_low_level->socket_state(i, &state) < 0) { -+ printk(KERN_ERR "Unable to get PCMCIA status\n"); -+ return -EIO; -+ } -+ pcmcia_socket[i].k_state = state; -+ pcmcia_socket[i].cs_state.csc_mask = SS_DETECT; -+ -+ if (i == 0) { -+ pcmcia_socket[i].virt_io = -+ (unsigned long)ioremap_nocache(EXTIF_PCMCIA_IOBASE(BCM4710_EXTIF), 0x1000); -+ /* Substract ioport base which gets added by in/out */ -+ pcmcia_socket[i].virt_io -= mips_io_port_base; -+ pcmcia_socket[i].phys_attr = -+ (unsigned long)EXTIF_PCMCIA_CFGBASE(BCM4710_EXTIF); -+ pcmcia_socket[i].phys_mem = -+ (unsigned long)EXTIF_PCMCIA_MEMBASE(BCM4710_EXTIF); -+ } else { -+ printk(KERN_ERR "bcm4710: socket 1 not supported\n"); -+ return 1; -+ } ++ skb = nskb; + } ++} + -+ /* Only advertise as many sockets as we can detect: */ -+ if (register_ss_entry(socket_count, &bcm47xx_pcmcia_operations) < 0) { -+ printk(KERN_ERR "Unable to register socket service routine\n"); -+ return -ENXIO; -+ } ++void* ++osl_malloc(osl_t *osh, uint size) ++{ ++ void *addr; + -+ /* Start the event poll timer. -+ * It will reschedule by itself afterwards. -+ */ -+ bcm47xx_pcmcia_poll_event(0); ++ /* only ASSERT if osh is defined */ ++ if (osh) ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); + -+ DEBUG(1, "bcm4710: initialization complete\n"); -+ return 0; ++ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { ++ if (osh) ++ osh->failed++; ++ return (NULL); ++ } ++ if (osh) ++ osh->malloced += size; + ++ return (addr); +} + -+module_init(bcm47xx_pcmcia_driver_init); -+ -+ -+/* -+ * bcm47xx_pcmcia_driver_shutdown() -+ * -+ * Invokes the low-level kernel service to free IRQs associated with this -+ * socket controller and reset GPIO edge detection. -+ */ -+static void __exit bcm47xx_pcmcia_driver_shutdown(void) ++void ++osl_mfree(osl_t *osh, void *addr, uint size) +{ -+ int i; -+ -+ del_timer_sync(&poll_timer); -+ unregister_ss_entry(&bcm47xx_pcmcia_operations); -+ pcmcia_low_level->shutdown(); -+ flush_scheduled_tasks(); -+ for (i = 0; i < socket_count; i++) { -+ if (pcmcia_socket[i].virt_io) -+ iounmap((void *)pcmcia_socket[i].virt_io); -+ if (pcmcia_socket[i].phys_attr) -+ iounmap((void *)pcmcia_socket[i].phys_attr); -+ if (pcmcia_socket[i].phys_mem) -+ iounmap((void *)pcmcia_socket[i].phys_mem); ++ if (osh) { ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ osh->malloced -= size; + } -+ DEBUG(1, "bcm4710: shutdown complete\n"); ++ kfree(addr); +} + -+module_exit(bcm47xx_pcmcia_driver_shutdown); ++uint ++osl_malloced(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (osh->malloced); ++} + -+/* -+ * bcm47xx_pcmcia_init() -+ * We perform all of the interesting initialization tasks in -+ * bcm47xx_pcmcia_driver_init(). -+ * -+ * Returns: 0 -+ */ -+static int bcm47xx_pcmcia_init(unsigned int sock) ++uint osl_malloc_failed(osl_t *osh) +{ -+ DEBUG(1, "%s(): initializing socket %u\n", __FUNCTION__, sock); ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (osh->failed); ++} + -+ return 0; ++#undef osl_delay ++void ++osl_delay(uint usec) ++{ ++ OSL_DELAY(usec); +} + -+/* -+ * bcm47xx_pcmcia_suspend() -+ * -+ * We don't currently perform any actions on a suspend. -+ * -+ * Returns: 0 ++/* Clone a packet. ++ * The pkttag contents are NOT cloned. + */ -+static int bcm47xx_pcmcia_suspend(unsigned int sock) ++void * ++osl_pktdup(osl_t *osh, void *skb) +{ -+ DEBUG(1, "%s(): suspending socket %u\n", __FUNCTION__, sock); ++ void * p; + -+ return 0; ++ if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) ++ return NULL; ++ ++ /* skb_clone copies skb->cb.. we don't want that */ ++ if (osh->pub.pkttag) ++ bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); ++ ++ /* Increment the packet counter */ ++ osh->pub.pktalloced++; ++ return (p); +} + ++uint ++osl_pktalloced(osl_t *osh) ++{ ++ return (osh->pub.pktalloced); ++} + +diff -urN linux.old/drivers/net/wl/linux_osl.h linux.dev/drivers/net/wl/linux_osl.h +--- linux.old/drivers/net/wl/linux_osl.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/linux_osl.h 2006-05-02 17:44:29.000000000 +0200 +@@ -0,0 +1,171 @@ +/* -+ * bcm47xx_pcmcia_events() ++ * Linux OS Independent Layer + * -+ * Helper routine to generate a Card Services event mask based on -+ * state information obtained from the kernel low-level PCMCIA layer -+ * in a recent (and previous) sampling. Updates `prev_state'. ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * Returns: an event mask for the given socket state. ++ * $Id: linux_osl.h,v 1.1.1.13 2006/04/08 06:13:39 honor Exp $ + */ -+static inline unsigned -+bcm47xx_pcmcia_events(struct pcmcia_state *state, -+ struct pcmcia_state *prev_state, -+ unsigned int mask, unsigned int flags) -+{ -+ unsigned int events=0; + -+ if (state->bvd1 != prev_state->bvd1) { ++#ifndef _linux_osl_h_ ++#define _linux_osl_h_ + -+ DEBUG(3, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1); ++#include ++#include ++#include + -+ events |= mask & (flags & SS_IOCARD) ? SS_STSCHG : SS_BATDEAD; -+ } ++#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ + -+ if (state->bvd2 != prev_state->bvd2) { ++/* osl handle type forward declaration */ ++typedef struct osl_dmainfo osldma_t; + -+ DEBUG(3, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2); ++/* OSL initialization */ ++extern osl_t *osl_attach(void *pdev, bool pkttag); ++extern void osl_detach(osl_t *osh); + -+ events |= mask & (flags & SS_IOCARD) ? 0 : SS_BATWARN; -+ } ++/* host/bus architecture-specific byte swap */ ++#define BUS_SWAP32(v) (v) ++#define MALLOC_FAILED(osh) osl_malloc_failed((osh)) + -+ if (state->detect != prev_state->detect) { ++extern void *osl_malloc(osl_t *osh, uint size); ++extern void osl_mfree(osl_t *osh, void *addr, uint size); ++extern uint osl_malloced(osl_t *osh); ++extern uint osl_malloc_failed(osl_t *osh); + -+ DEBUG(3, "%s(): card detect value %u\n", __FUNCTION__, state->detect); ++/* API for DMA addressing capability */ ++#define DMA_MAP(osh, va, size, direction, p) \ ++ osl_dma_map((osh), (va), (size), (direction)) ++#define DMA_UNMAP(osh, pa, size, direction, p) \ ++ osl_dma_unmap((osh), (pa), (size), (direction)) ++static inline uint ++osl_dma_map(void *osh, void *va, uint size, int direction) ++{ ++ int dir; ++ struct pci_dev *dev; + -+ events |= mask & SS_DETECT; -+ } ++ dev = (osh == NULL ? NULL : ((osl_t *)osh)->pdev); ++ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; ++ return (pci_map_single(dev, va, size, dir)); ++} + ++static inline void ++osl_dma_unmap(void *osh, uint pa, uint size, int direction) ++{ ++ int dir; ++ struct pci_dev *dev; + -+ if (state->ready != prev_state->ready) { ++ dev = (osh == NULL ? NULL : ((osl_t *)osh)->pdev); ++ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; ++ pci_unmap_single(dev, (uint32)pa, size, dir); ++} + -+ DEBUG(3, "%s(): card ready value %u\n", __FUNCTION__, state->ready); ++#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0) ++#define DMA_CONSISTENT_ALIGN PAGE_SIZE ++#define DMA_ALLOC_CONSISTENT(osh, size, pap, dmah) \ ++ osl_dma_alloc_consistent((osh), (size), (pap)) ++#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \ ++ osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) ++static inline void* ++osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap) ++{ ++ return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); ++} + -+ events |= mask & ((flags & SS_IOCARD) ? 0 : SS_READY); -+ } ++static inline void ++osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) ++{ ++ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); ++} + -+ if (events != 0) { -+ DEBUG(2, "events: %s%s%s%s%s\n", -+ (events & SS_DETECT) ? "DETECT " : "", -+ (events & SS_READY) ? "READY " : "", -+ (events & SS_BATDEAD) ? "BATDEAD " : "", -+ (events & SS_BATWARN) ? "BATWARN " : "", -+ (events & SS_STSCHG) ? "STSCHG " : ""); -+ } + -+ *prev_state=*state; -+ return events; -+} ++/* register access macros */ ++#if defined(BCMJTAG) ++#include ++#define R_REG(osh, r) bcmjtag_read(NULL, (uint32)(r), sizeof(*(r))) ++#define W_REG(osh, r, v) bcmjtag_write(NULL, (uint32)(r), (uint32)(v), sizeof(*(r))) ++#endif /* defined(BCMSDIO) */ + ++/* packet primitives */ ++#define PKTGET(osh, len, send) osl_pktget((osh), (len), (send)) ++#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb)) ++#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) ++#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) ++#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) ++#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) ++#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) ++#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) ++#define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len)) ++#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) ++#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) ++#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) ++#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) ++#define PKTALLOCED(osh) osl_pktalloced((osh)) ++#define PKTLIST_DUMP(osh, buf) + -+/* -+ * bcm47xx_pcmcia_task_handler() -+ * -+ * Processes serviceable socket events using the "eventd" thread context. -+ * -+ * Event processing (specifically, the invocation of the Card Services event -+ * callback) occurs in this thread rather than in the actual interrupt -+ * handler due to the use of scheduling operations in the PCMCIA core. ++/* Convert a native(OS) packet to driver packet. ++ * In the process, native packet is destroyed, there is no copying ++ * Also, a packettag is zeroed out + */ -+static void bcm47xx_pcmcia_task_handler(void *data) ++static INLINE void * ++osl_pkt_frmnative(struct osl_pubinfo *osh, struct sk_buff *skb) +{ -+ struct pcmcia_state state; -+ int i, events, irq_status; -+ -+ DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__); ++ struct sk_buff *nskb; + -+ for (i = 0; i < socket_count; i++) { -+ if ((irq_status = pcmcia_low_level->socket_state(i, &state)) < 0) -+ printk(KERN_ERR "Error in kernel low-level PCMCIA service.\n"); ++ if (osh->pkttag) ++ bzero((void*)skb->cb, OSL_PKTTAG_SZ); + -+ events = bcm47xx_pcmcia_events(&state, -+ &pcmcia_socket[i].k_state, -+ pcmcia_socket[i].cs_state.csc_mask, -+ pcmcia_socket[i].cs_state.flags); -+ -+ if (pcmcia_socket[i].handler != NULL) { -+ pcmcia_socket[i].handler(pcmcia_socket[i].handler_info, -+ events); -+ } ++ /* Increment the packet counter */ ++ for (nskb = skb; nskb; nskb = nskb->next) { ++ osh->pktalloced++; + } -+} -+ -+static struct tq_struct bcm47xx_pcmcia_task = { -+ routine: bcm47xx_pcmcia_task_handler -+}; + ++ return (void *)skb; ++} ++#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((struct osl_pubinfo *)osh), \ ++ (struct sk_buff*)(skb)) + -+/* -+ * bcm47xx_pcmcia_poll_event() -+ * -+ * Let's poll for events in addition to IRQs since IRQ only is unreliable... ++/* Convert a driver packet to native(OS) packet ++ * In the process, packettag is zeroed out before sending up ++ * IP code depends on skb->cb to be setup correctly with various options ++ * In our case, that means it should be 0 + */ -+static void bcm47xx_pcmcia_poll_event(unsigned long dummy) ++static INLINE struct sk_buff * ++osl_pkt_tonative(struct osl_pubinfo *osh, void *pkt) +{ -+ DEBUG(4, "%s(): polling for events\n", __FUNCTION__); ++ struct sk_buff *nskb; + -+ poll_timer.function = bcm47xx_pcmcia_poll_event; -+ poll_timer.expires = jiffies + BCM47XX_PCMCIA_POLL_PERIOD; -+ add_timer(&poll_timer); -+ schedule_task(&bcm47xx_pcmcia_task); -+} ++ if (osh->pkttag) ++ bzero(((struct sk_buff*)pkt)->cb, OSL_PKTTAG_SZ); + ++ /* Decrement the packet counter */ ++ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { ++ osh->pktalloced--; ++ } + -+/* -+ * bcm47xx_pcmcia_interrupt() -+ * -+ * Service routine for socket driver interrupts (requested by the -+ * low-level PCMCIA init() operation via bcm47xx_pcmcia_thread()). -+ * -+ * The actual interrupt-servicing work is performed by -+ * bcm47xx_pcmcia_task(), largely because the Card Services event- -+ * handling code performs scheduling operations which cannot be -+ * executed from within an interrupt context. -+ */ -+static void -+bcm47xx_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) -+{ -+ DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq); -+ schedule_task(&bcm47xx_pcmcia_task); ++ return (struct sk_buff *)pkt; +} ++#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((struct osl_pubinfo *)(osh), (pkt)) ++ ++#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) ++#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) ++#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) ++#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) ++#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) + ++extern void *osl_pktget(osl_t *osh, uint len, bool send); ++extern void osl_pktfree(osl_t *osh, void *skb); ++extern void *osl_pktdup(osl_t *osh, void *skb); ++extern uint osl_pktalloced(osl_t *osh); + -+/* -+ * bcm47xx_pcmcia_register_callback() -+ * -+ * Implements the register_callback() operation for the in-kernel -+ * PCMCIA service (formerly SS_RegisterCallback in Card Services). If -+ * the function pointer `handler' is not NULL, remember the callback -+ * location in the state for `sock', and increment the usage counter -+ * for the driver module. (The callback is invoked from the interrupt -+ * service routine, bcm47xx_pcmcia_interrupt(), to notify Card Services -+ * of interesting events.) Otherwise, clear the callback pointer in the -+ * socket state and decrement the module usage count. -+ * -+ * Returns: 0 -+ */ -+static int -+bcm47xx_pcmcia_register_callback(unsigned int sock, -+ void (*handler)(void *, unsigned int), void *info) -+{ -+ if (handler == NULL) { -+ pcmcia_socket[sock].handler = NULL; -+ MOD_DEC_USE_COUNT; -+ } else { -+ MOD_INC_USE_COUNT; -+ pcmcia_socket[sock].handler = handler; -+ pcmcia_socket[sock].handler_info = info; -+ } -+ return 0; -+} ++#define OSL_ERROR(bcmerror) osl_error(bcmerror) ++extern int osl_error(int bcmerror); + ++/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ ++#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */ + ++#endif /* _linux_osl_h_ */ +diff -urN linux.old/drivers/net/wl/pktq.h linux.dev/drivers/net/wl/pktq.h +--- linux.old/drivers/net/wl/pktq.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/pktq.h 2006-04-28 02:11:49.000000000 +0200 +@@ -0,0 +1,97 @@ +/* -+ * bcm47xx_pcmcia_inquire_socket() -+ * -+ * Implements the inquire_socket() operation for the in-kernel PCMCIA -+ * service (formerly SS_InquireSocket in Card Services). Of note is -+ * the setting of the SS_CAP_PAGE_REGS bit in the `features' field of -+ * `cap' to "trick" Card Services into tolerating large "I/O memory" -+ * addresses. Also set is SS_CAP_STATIC_MAP, which disables the memory -+ * resource database check. (Mapped memory is set up within the socket -+ * driver itself.) -+ * -+ * In conjunction with the STATIC_MAP capability is a new field, -+ * `io_offset', recommended by David Hinds. Rather than go through -+ * the SetIOMap interface (which is not quite suited for communicating -+ * window locations up from the socket driver), we just pass up -+ * an offset which is applied to client-requested base I/O addresses -+ * in alloc_io_space(). ++ * Misc useful os-independent macros and functions. + * -+ * Returns: 0 on success, -1 if no pin has been configured for `sock' ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * $Id: bcmutils.h,v 1.1.1.16 2006/04/08 06:13:39 honor Exp $ + */ -+static int -+bcm47xx_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap) -+{ -+ struct pcmcia_irq_info irq_info; + -+ if (sock >= socket_count) { -+ printk(KERN_ERR "bcm47xx: socket %u not configured\n", sock); -+ return -1; -+ } -+ -+ /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the -+ * force_low argument to validate_mem() in rsrc_mgr.c -- since in -+ * general, the mapped * addresses of the PCMCIA memory regions -+ * will not be within 0xffff, setting force_low would be -+ * undesirable. -+ * -+ * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory -+ * resource database; we instead pass up physical address ranges -+ * and allow other parts of Card Services to deal with remapping. -+ * -+ * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but -+ * not 32-bit CardBus devices. -+ */ -+ cap->features = (SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD); ++#ifndef _pktq_h_ ++#define _pktq_h_ ++#include + -+ irq_info.sock = sock; -+ irq_info.irq = -1; ++/* osl multi-precedence packet queue */ + -+ if (pcmcia_low_level->get_irq_info(&irq_info) < 0) { -+ printk(KERN_ERR "Error obtaining IRQ info socket %u\n", sock); -+ return -1; -+ } ++#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ ++#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ + -+ cap->irq_mask = 0; -+ cap->map_size = PAGE_SIZE; -+ cap->pci_irq = irq_info.irq; -+ cap->io_offset = pcmcia_socket[sock].virt_io; ++struct pktq { ++ struct pktq_prec { ++ void *head; /* first packet to dequeue */ ++ void *tail; /* last packet to dequeue */ ++ uint16 len; /* number of queued packets */ ++ uint16 max; /* maximum number of queued packets */ ++ } q[PKTQ_MAX_PREC]; ++ uint16 num_prec; /* number of precedences in use */ ++ uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ ++ uint16 max; /* total max packets */ ++ uint16 len; /* total number of packets */ ++}; + -+ return 0; -+} ++#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) + ++/* forward definition of ether_addr structure used by some function prototypes */ + -+/* -+ * bcm47xx_pcmcia_get_status() -+ * -+ * Implements the get_status() operation for the in-kernel PCMCIA -+ * service (formerly SS_GetStatus in Card Services). Essentially just -+ * fills in bits in `status' according to internal driver state or -+ * the value of the voltage detect chipselect register. -+ * -+ * As a debugging note, during card startup, the PCMCIA core issues -+ * three set_socket() commands in a row the first with RESET deasserted, -+ * the second with RESET asserted, and the last with RESET deasserted -+ * again. Following the third set_socket(), a get_status() command will -+ * be issued. The kernel is looking for the SS_READY flag (see -+ * setup_socket(), reset_socket(), and unreset_socket() in cs.c). -+ * -+ * Returns: 0 -+ */ -+static int -+bcm47xx_pcmcia_get_status(unsigned int sock, unsigned int *status) -+{ -+ struct pcmcia_state state; ++struct ether_addr; + ++/* operations on a specific precedence in packet queue */ + -+ if ((pcmcia_low_level->socket_state(sock, &state)) < 0) { -+ printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n"); -+ return -1; -+ } ++#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) ++#define pktq_plen(pq, prec) ((pq)->q[prec].len) ++#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) ++#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) ++#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) + -+ pcmcia_socket[sock].k_state = state; ++#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) ++#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) + -+ *status = state.detect ? SS_DETECT : 0; ++extern void *pktq_penq(struct pktq *pq, int prec, void *p); ++extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); ++extern void *pktq_pdeq(struct pktq *pq, int prec); ++extern void *pktq_pdeq_tail(struct pktq *pq, int prec); ++/* Empty the queue at particular precedence level */ ++extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir); ++/* Remove a specified packet from its queue */ ++extern bool pktq_pdel(struct pktq *pq, void *p, int prec); + -+ *status |= state.ready ? SS_READY : 0; ++/* operations on a set of precedences in packet queue */ + -+ /* The power status of individual sockets is not available -+ * explicitly from the hardware, so we just remember the state -+ * and regurgitate it upon request: -+ */ -+ *status |= pcmcia_socket[sock].cs_state.Vcc ? SS_POWERON : 0; ++extern int pktq_mlen(struct pktq *pq, uint prec_bmp); ++extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); + -+ if (pcmcia_socket[sock].cs_state.flags & SS_IOCARD) -+ *status |= state.bvd1 ? SS_STSCHG : 0; -+ else { -+ if (state.bvd1 == 0) -+ *status |= SS_BATDEAD; -+ else if (state.bvd2 == 0) -+ *status |= SS_BATWARN; -+ } ++/* operations on packet queue as a whole */ + -+ *status |= state.vs_3v ? SS_3VCARD : 0; ++#define pktq_len(pq) ((int)(pq)->len) ++#define pktq_max(pq) ((int)(pq)->max) ++#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) ++#define pktq_full(pq) ((pq)->len >= (pq)->max) ++#define pktq_empty(pq) ((pq)->len == 0) + -+ *status |= state.vs_Xv ? SS_XVCARD : 0; ++/* operations for single precedence queues */ ++#define pktenq(pq, p) pktq_penq((pq), 0, (p)) ++#define pktenq_head(pq, p) pktq_penq_head((pq), 0, (p)) ++#define pktdeq(pq) pktq_pdeq((pq), 0) ++#define pktdeq_tail(pq) pktq_pdeq_tail((pq), 0) + -+ DEBUG(2, "\tstatus: %s%s%s%s%s%s%s%s\n", -+ (*status&SS_DETECT)?"DETECT ":"", -+ (*status&SS_READY)?"READY ":"", -+ (*status&SS_BATDEAD)?"BATDEAD ":"", -+ (*status&SS_BATWARN)?"BATWARN ":"", -+ (*status&SS_POWERON)?"POWERON ":"", -+ (*status&SS_STSCHG)?"STSCHG ":"", -+ (*status&SS_3VCARD)?"3VCARD ":"", -+ (*status&SS_XVCARD)?"XVCARD ":""); ++extern void pktq_init(struct pktq *pq, int num_prec, int max_len); ++/* prec_out may be NULL if caller is not interested in return value */ ++extern void *pktq_deq(struct pktq *pq, int *prec_out); ++extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); ++extern void *pktq_peek(struct pktq *pq, int *prec_out); ++extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); ++extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir); /* Empty the entire queue */ + -+ return 0; -+} ++/* externs */ ++/* packet */ ++extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); ++extern uint pkttotlen(osl_t *osh, void *p); ++extern void *pktlast(osl_t *osh, void *p); + ++extern void pktsetprio(void *pkt, bool update_vtag); + ++#endif /* _pktq_h_ */ +diff -urN linux.old/drivers/net/wl/sbhnddma.h linux.dev/drivers/net/wl/sbhnddma.h +--- linux.old/drivers/net/wl/sbhnddma.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/net/wl/sbhnddma.h 2006-04-28 02:20:47.000000000 +0200 +@@ -0,0 +1,284 @@ +/* -+ * bcm47xx_pcmcia_get_socket() ++ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface ++ * This supports the following chips: BCM42xx, 44xx, 47xx . + * -+ * Implements the get_socket() operation for the in-kernel PCMCIA -+ * service (formerly SS_GetSocket in Card Services). Not a very -+ * exciting routine. ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * -+ * Returns: 0 ++ * $Id: sbhnddma.h,v 1.1.1.2 2006/02/27 03:43:16 honor Exp $ + */ -+static int -+bcm47xx_pcmcia_get_socket(unsigned int sock, socket_state_t *state) -+{ -+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); -+ -+ /* This information was given to us in an earlier call to set_socket(), -+ * so we're just regurgitating it here: -+ */ -+ *state = pcmcia_socket[sock].cs_state; -+ return 0; -+} + ++#ifndef _sbhnddma_h_ ++#define _sbhnddma_h_ + -+/* -+ * bcm47xx_pcmcia_set_socket() -+ * -+ * Implements the set_socket() operation for the in-kernel PCMCIA -+ * service (formerly SS_SetSocket in Card Services). We more or -+ * less punt all of this work and let the kernel handle the details -+ * of power configuration, reset, &c. We also record the value of -+ * `state' in order to regurgitate it to the PCMCIA core later. -+ * -+ * Returns: 0 ++/* DMA structure: ++ * support two DMA engines: 32 bits address or 64 bit addressing ++ * basic DMA register set is per channel(transmit or receive) ++ * a pair of channels is defined for convenience + */ -+static int -+bcm47xx_pcmcia_set_socket(unsigned int sock, socket_state_t *state) -+{ -+ struct pcmcia_configure configure; -+ -+ DEBUG(2, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n" -+ "\tVcc %d Vpp %d irq %d\n", -+ (state->csc_mask == 0) ? "" : "", -+ (state->csc_mask & SS_DETECT) ? "DETECT " : "", -+ (state->csc_mask & SS_READY) ? "READY " : "", -+ (state->csc_mask & SS_BATDEAD) ? "BATDEAD " : "", -+ (state->csc_mask & SS_BATWARN) ? "BATWARN " : "", -+ (state->csc_mask & SS_STSCHG) ? "STSCHG " : "", -+ (state->flags == 0) ? "" : "", -+ (state->flags & SS_PWR_AUTO) ? "PWR_AUTO " : "", -+ (state->flags & SS_IOCARD) ? "IOCARD " : "", -+ (state->flags & SS_RESET) ? "RESET " : "", -+ (state->flags & SS_SPKR_ENA) ? "SPKR_ENA " : "", -+ (state->flags & SS_OUTPUT_ENA) ? "OUTPUT_ENA " : "", -+ state->Vcc, state->Vpp, state->io_irq); -+ -+ configure.sock = sock; -+ configure.vcc = state->Vcc; -+ configure.vpp = state->Vpp; -+ configure.output = (state->flags & SS_OUTPUT_ENA) ? 1 : 0; -+ configure.speaker = (state->flags & SS_SPKR_ENA) ? 1 : 0; -+ configure.reset = (state->flags & SS_RESET) ? 1 : 0; -+ -+ if (pcmcia_low_level->configure_socket(&configure) < 0) { -+ printk(KERN_ERR "Unable to configure socket %u\n", sock); -+ return -1; -+ } + -+ pcmcia_socket[sock].cs_state = *state; -+ return 0; -+} + ++/* 32 bits addressing */ + -+/* -+ * bcm47xx_pcmcia_get_io_map() -+ * -+ * Implements the get_io_map() operation for the in-kernel PCMCIA -+ * service (formerly SS_GetIOMap in Card Services). Just returns an -+ * I/O map descriptor which was assigned earlier by a set_io_map(). -+ * -+ * Returns: 0 on success, -1 if the map index was out of range -+ */ -+static int -+bcm47xx_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *map) -+{ -+ DEBUG(2, "bcm47xx_pcmcia_get_io_map: sock %d\n", sock); ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 addr; /* descriptor ring base address (4K aligned) */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 status; /* current active descriptor, et al */ ++} dma32regs_t; + -+ if (map->map >= MAX_IO_WIN) { -+ printk(KERN_ERR "%s(): map (%d) out of range\n", -+ __FUNCTION__, map->map); -+ return -1; -+ } ++typedef volatile struct { ++ dma32regs_t xmt; /* dma tx channel */ ++ dma32regs_t rcv; /* dma rx channel */ ++} dma32regp_t; + -+ *map = pcmcia_socket[sock].io_map[map->map]; -+ return 0; -+} ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma32diag_t; + ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++typedef volatile struct { ++ uint32 ctrl; /* misc control bits & bufcount */ ++ uint32 addr; /* data buffer address */ ++} dma32dd_t; + +/* -+ * bcm47xx_pcmcia_set_io_map() -+ * -+ * Implements the set_io_map() operation for the in-kernel PCMCIA -+ * service (formerly SS_SetIOMap in Card Services). We configure -+ * the map speed as requested, but override the address ranges -+ * supplied by Card Services. -+ * -+ * Returns: 0 on success, -1 on error ++ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. + */ -+int -+bcm47xx_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map) -+{ -+ unsigned int speed; -+ unsigned long start; -+ -+ DEBUG(2, "\tmap %u speed %u\n\tstart 0x%08lx stop 0x%08lx\n" -+ "\tflags: %s%s%s%s%s%s%s%s\n", -+ map->map, map->speed, map->start, map->stop, -+ (map->flags == 0) ? "" : "", -+ (map->flags & MAP_ACTIVE) ? "ACTIVE " : "", -+ (map->flags & MAP_16BIT) ? "16BIT " : "", -+ (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "", -+ (map->flags & MAP_0WS) ? "0WS " : "", -+ (map->flags & MAP_WRPROT) ? "WRPROT " : "", -+ (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "", -+ (map->flags & MAP_PREFETCH) ? "PREFETCH " : ""); -+ -+ if (map->map >= MAX_IO_WIN) { -+ printk(KERN_ERR "%s(): map (%d) out of range\n", -+ __FUNCTION__, map->map); -+ return -1; -+ } ++#define D32MAXRINGSZ 4096 ++#define D32RINGALIGN 4096 ++#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) + -+ if (map->flags & MAP_ACTIVE) { -+ speed = (map->speed > 0) ? map->speed : BCM47XX_PCMCIA_IO_SPEED; -+ pcmcia_socket[sock].speed_io = speed; -+ } ++/* transmit channel control */ ++#define XC_XE ((uint32)1 << 0) /* transmit enable */ ++#define XC_SE ((uint32)1 << 1) /* transmit suspend request */ ++#define XC_LE ((uint32)1 << 2) /* loopback enable */ ++#define XC_FL ((uint32)1 << 4) /* flush request */ ++#define XC_AE ((uint32)3 << 16) /* address extension bits */ ++#define XC_AE_SHIFT 16 + -+ start = map->start; ++/* transmit descriptor table pointer */ ++#define XP_LD_MASK 0xfff /* last valid descriptor */ + -+ if (map->stop == 1) { -+ map->stop = PAGE_SIZE - 1; -+ } ++/* transmit channel status */ ++#define XS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define XS_XS_MASK 0xf000 /* transmit state */ ++#define XS_XS_SHIFT 12 ++#define XS_XS_DISABLED 0x0000 /* disabled */ ++#define XS_XS_ACTIVE 0x1000 /* active */ ++#define XS_XS_IDLE 0x2000 /* idle wait */ ++#define XS_XS_STOPPED 0x3000 /* stopped */ ++#define XS_XS_SUSP 0x4000 /* suspend pending */ ++#define XS_XE_MASK 0xf0000 /* transmit errors */ ++#define XS_XE_SHIFT 16 ++#define XS_XE_NOERR 0x00000 /* no error */ ++#define XS_XE_DPE 0x10000 /* descriptor protocol error */ ++#define XS_XE_DFU 0x20000 /* data fifo underrun */ ++#define XS_XE_BEBR 0x30000 /* bus error on buffer read */ ++#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */ ++#define XS_AD_MASK 0xfff00000 /* active descriptor */ ++#define XS_AD_SHIFT 20 + -+ map->start = pcmcia_socket[sock].virt_io; -+ map->stop = map->start + (map->stop - start); -+ pcmcia_socket[sock].io_map[map->map] = *map; -+ DEBUG(2, "set_io_map %d start %x stop %x\n", -+ map->map, map->start, map->stop); -+ return 0; -+} ++/* receive channel control */ ++#define RC_RE ((uint32)1 << 0) /* receive enable */ ++#define RC_RO_MASK 0xfe /* receive frame offset */ ++#define RC_RO_SHIFT 1 ++#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */ ++#define RC_AE ((uint32)3 << 16) /* address extension bits */ ++#define RC_AE_SHIFT 16 ++ ++/* receive descriptor table pointer */ ++#define RP_LD_MASK 0xfff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define RS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define RS_RS_MASK 0xf000 /* receive state */ ++#define RS_RS_SHIFT 12 ++#define RS_RS_DISABLED 0x0000 /* disabled */ ++#define RS_RS_ACTIVE 0x1000 /* active */ ++#define RS_RS_IDLE 0x2000 /* idle wait */ ++#define RS_RS_STOPPED 0x3000 /* reserved */ ++#define RS_RE_MASK 0xf0000 /* receive errors */ ++#define RS_RE_SHIFT 16 ++#define RS_RE_NOERR 0x00000 /* no error */ ++#define RS_RE_DPE 0x10000 /* descriptor protocol error */ ++#define RS_RE_DFO 0x20000 /* data fifo overflow */ ++#define RS_RE_BEBW 0x30000 /* bus error on buffer write */ ++#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */ ++#define RS_AD_MASK 0xfff00000 /* active descriptor */ ++#define RS_AD_SHIFT 20 ++ ++/* fifoaddr */ ++#define FA_OFF_MASK 0xffff /* offset */ ++#define FA_SEL_MASK 0xf0000 /* select */ ++#define FA_SEL_SHIFT 16 ++#define FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define FA_SEL_RDD 0x40000 /* receive dma data */ ++#define FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags */ ++#define CTRL_BC_MASK 0x1fff /* buffer byte count */ ++#define CTRL_AE ((uint32)3 << 16) /* address extension bits */ ++#define CTRL_AE_SHIFT 16 ++#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define CTRL_EOF ((uint32)1 << 30) /* end of frame */ ++#define CTRL_SOF ((uint32)1 << 31) /* start of frame */ ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define CTRL_CORE_MASK 0x0ff00000 ++ ++/* 64 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ ++ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ ++ uint32 status0; /* current descriptor, xmt state */ ++ uint32 status1; /* active descriptor, xmt error */ ++} dma64regs_t; ++ ++typedef volatile struct { ++ dma64regs_t tx; /* dma64 tx channel */ ++ dma64regs_t rx; /* dma64 rx channel */ ++} dma64regp_t; + ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma64diag_t; + +/* -+ * bcm47xx_pcmcia_get_mem_map() -+ * -+ * Implements the get_mem_map() operation for the in-kernel PCMCIA -+ * service (formerly SS_GetMemMap in Card Services). Just returns a -+ * memory map descriptor which was assigned earlier by a -+ * set_mem_map() request. -+ * -+ * Returns: 0 on success, -1 if the map index was out of range ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. + */ -+static int -+bcm47xx_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *map) -+{ -+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); -+ -+ if (map->map >= MAX_WIN) { -+ printk(KERN_ERR "%s(): map (%d) out of range\n", -+ __FUNCTION__, map->map); -+ return -1; -+ } -+ -+ *map = pcmcia_socket[sock].mem_map[map->map]; -+ return 0; -+} -+ ++typedef volatile struct { ++ uint32 ctrl1; /* misc control bits & bufcount */ ++ uint32 ctrl2; /* buffer count and address extension */ ++ uint32 addrlow; /* memory address of the date buffer, bits 31:0 */ ++ uint32 addrhigh; /* memory address of the date buffer, bits 63:32 */ ++} dma64dd_t; + +/* -+ * bcm47xx_pcmcia_set_mem_map() -+ * -+ * Implements the set_mem_map() operation for the in-kernel PCMCIA -+ * service (formerly SS_SetMemMap in Card Services). We configure -+ * the map speed as requested, but override the address ranges -+ * supplied by Card Services. -+ * -+ * Returns: 0 on success, -1 on error ++ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. + */ -+static int -+bcm47xx_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) -+{ -+ unsigned int speed; -+ unsigned long start; -+ u_long flags; ++#define D64MAXRINGSZ 8192 ++#define D64RINGALIGN 8192 ++#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) + -+ if (map->map >= MAX_WIN) { -+ printk(KERN_ERR "%s(): map (%d) out of range\n", -+ __FUNCTION__, map->map); -+ return -1; -+ } ++/* transmit channel control */ ++#define D64_XC_XE 0x00000001 /* transmit enable */ ++#define D64_XC_SE 0x00000002 /* transmit suspend request */ ++#define D64_XC_LE 0x00000004 /* loopback enable */ ++#define D64_XC_FL 0x00000010 /* flush request */ ++#define D64_XC_AE 0x00030000 /* address extension bits */ ++#define D64_XC_AE_SHIFT 16 + -+ DEBUG(2, "\tmap %u speed %u\n\tsys_start %#lx\n" -+ "\tsys_stop %#lx\n\tcard_start %#x\n" -+ "\tflags: %s%s%s%s%s%s%s%s\n", -+ map->map, map->speed, map->sys_start, map->sys_stop, -+ map->card_start, (map->flags == 0) ? "" : "", -+ (map->flags & MAP_ACTIVE) ? "ACTIVE " : "", -+ (map->flags & MAP_16BIT) ? "16BIT " : "", -+ (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "", -+ (map->flags & MAP_0WS) ? "0WS " : "", -+ (map->flags & MAP_WRPROT) ? "WRPROT " : "", -+ (map->flags & MAP_ATTRIB) ? "ATTRIB " : "", -+ (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : ""); -+ -+ if (map->flags & MAP_ACTIVE) { -+ /* When clients issue RequestMap, the access speed is not always -+ * properly configured: -+ */ -+ speed = (map->speed > 0) ? map->speed : BCM47XX_PCMCIA_MEM_SPEED; ++/* transmit descriptor table pointer */ ++#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ + -+ /* TBD */ -+ if (map->flags & MAP_ATTRIB) { -+ pcmcia_socket[sock].speed_attr = speed; -+ } else { -+ pcmcia_socket[sock].speed_mem = speed; -+ } -+ } ++/* transmit channel status */ ++#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ ++#define D64_XS0_XS_SHIFT 28 ++#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ ++#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ ++#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ ++#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ ++#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ + -+ save_flags(flags); -+ cli(); -+ start = map->sys_start; ++#define D64_XS1_AD_MASK 0x0001ffff /* active descriptor */ ++#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ ++#define D64_XS1_XE_SHIFT 28 ++#define D64_XS1_XE_NOERR 0x00000000 /* no error */ ++#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ ++#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ ++#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ ++#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_XS1_XE_COREE 0x50000000 /* core error */ + -+ if (map->sys_stop == 0) -+ map->sys_stop = PAGE_SIZE - 1; ++/* receive channel control */ ++#define D64_RC_RE 0x00000001 /* receive enable */ ++#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ ++#define D64_RC_RO_SHIFT 1 ++#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ ++#define D64_RC_AE 0x00030000 /* address extension bits */ ++#define D64_RC_AE_SHIFT 16 + -+ if (map->flags & MAP_ATTRIB) { -+ map->sys_start = pcmcia_socket[sock].phys_attr + -+ map->card_start; -+ } else { -+ map->sys_start = pcmcia_socket[sock].phys_mem + -+ map->card_start; -+ } ++/* receive descriptor table pointer */ ++#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ + -+ map->sys_stop = map->sys_start + (map->sys_stop - start); -+ pcmcia_socket[sock].mem_map[map->map] = *map; -+ restore_flags(flags); -+ DEBUG(2, "set_mem_map %d start %x stop %x card_start %x\n", -+ map->map, map->sys_start, map->sys_stop, -+ map->card_start); -+ return 0; -+} ++/* receive channel status */ ++#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ ++#define D64_RS0_RS_SHIFT 28 ++#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ ++#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ ++#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ ++#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ ++#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ + ++#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ ++#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ ++#define D64_RS1_RE_SHIFT 28 ++#define D64_RS1_RE_NOERR 0x00000000 /* no error */ ++#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ ++#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ ++#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ ++#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_RS1_RE_COREE 0x50000000 /* core error */ + -+#if defined(CONFIG_PROC_FS) ++/* fifoaddr */ ++#define D64_FA_OFF_MASK 0xffff /* offset */ ++#define D64_FA_SEL_MASK 0xf0000 /* select */ ++#define D64_FA_SEL_SHIFT 16 ++#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ ++#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ + -+/* -+ * bcm47xx_pcmcia_proc_setup() -+ * -+ * Implements the proc_setup() operation for the in-kernel PCMCIA -+ * service (formerly SS_ProcSetup in Card Services). -+ * -+ * Returns: 0 on success, -1 on error -+ */ -+static void -+bcm47xx_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base) -+{ -+ struct proc_dir_entry *entry; ++/* descriptor control flags 1 */ ++#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */ ++#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */ + -+ if ((entry = create_proc_entry("status", 0, base)) == NULL) { -+ printk(KERN_ERR "Unable to install \"status\" procfs entry\n"); -+ return; -+ } ++/* descriptor control flags 2 */ ++#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count mask */ ++#define D64_CTRL2_AE 0x00030000 /* address extension bits */ ++#define D64_CTRL2_AE_SHIFT 16 + -+ entry->read_proc = bcm47xx_pcmcia_proc_status; -+ entry->data = (void *)sock; -+} ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define D64_CTRL_CORE_MASK 0x0ff00000 + + -+/* -+ * bcm47xx_pcmcia_proc_status() -+ * -+ * Implements the /proc/bus/pccard/??/status file. -+ * -+ * Returns: the number of characters added to the buffer -+ */ -+static int -+bcm47xx_pcmcia_proc_status(char *buf, char **start, off_t pos, -+ int count, int *eof, void *data) -+{ -+ char *p = buf; -+ unsigned int sock = (unsigned int)data; -+ -+ p += sprintf(p, "k_flags : %s%s%s%s%s%s%s\n", -+ pcmcia_socket[sock].k_state.detect ? "detect " : "", -+ pcmcia_socket[sock].k_state.ready ? "ready " : "", -+ pcmcia_socket[sock].k_state.bvd1 ? "bvd1 " : "", -+ pcmcia_socket[sock].k_state.bvd2 ? "bvd2 " : "", -+ pcmcia_socket[sock].k_state.wrprot ? "wrprot " : "", -+ pcmcia_socket[sock].k_state.vs_3v ? "vs_3v " : "", -+ pcmcia_socket[sock].k_state.vs_Xv ? "vs_Xv " : ""); -+ -+ p += sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n", -+ pcmcia_socket[sock].k_state.detect ? "SS_DETECT " : "", -+ pcmcia_socket[sock].k_state.ready ? "SS_READY " : "", -+ pcmcia_socket[sock].cs_state.Vcc ? "SS_POWERON " : "", -+ pcmcia_socket[sock].cs_state.flags & SS_IOCARD ? "SS_IOCARD " : "", -+ (pcmcia_socket[sock].cs_state.flags & SS_IOCARD && -+ pcmcia_socket[sock].k_state.bvd1) ? "SS_STSCHG " : "", -+ ((pcmcia_socket[sock].cs_state.flags & SS_IOCARD) == 0 && -+ (pcmcia_socket[sock].k_state.bvd1 == 0)) ? "SS_BATDEAD " : "", -+ ((pcmcia_socket[sock].cs_state.flags & SS_IOCARD) == 0 && -+ (pcmcia_socket[sock].k_state.bvd2 == 0)) ? "SS_BATWARN " : "", -+ pcmcia_socket[sock].k_state.vs_3v ? "SS_3VCARD " : "", -+ pcmcia_socket[sock].k_state.vs_Xv ? "SS_XVCARD " : ""); -+ -+ p += sprintf(p, "mask : %s%s%s%s%s\n", -+ pcmcia_socket[sock].cs_state.csc_mask & SS_DETECT ? "SS_DETECT " : "", -+ pcmcia_socket[sock].cs_state.csc_mask & SS_READY ? "SS_READY " : "", -+ pcmcia_socket[sock].cs_state.csc_mask & SS_BATDEAD ? "SS_BATDEAD " : "", -+ pcmcia_socket[sock].cs_state.csc_mask & SS_BATWARN ? "SS_BATWARN " : "", -+ pcmcia_socket[sock].cs_state.csc_mask & SS_STSCHG ? "SS_STSCHG " : ""); -+ -+ p += sprintf(p, "cs_flags : %s%s%s%s%s\n", -+ pcmcia_socket[sock].cs_state.flags & SS_PWR_AUTO ? -+ "SS_PWR_AUTO " : "", -+ pcmcia_socket[sock].cs_state.flags & SS_IOCARD ? -+ "SS_IOCARD " : "", -+ pcmcia_socket[sock].cs_state.flags & SS_RESET ? -+ "SS_RESET " : "", -+ pcmcia_socket[sock].cs_state.flags & SS_SPKR_ENA ? -+ "SS_SPKR_ENA " : "", -+ pcmcia_socket[sock].cs_state.flags & SS_OUTPUT_ENA ? -+ "SS_OUTPUT_ENA " : ""); -+ -+ p += sprintf(p, "Vcc : %d\n", pcmcia_socket[sock].cs_state.Vcc); -+ p += sprintf(p, "Vpp : %d\n", pcmcia_socket[sock].cs_state.Vpp); -+ p += sprintf(p, "irq : %d\n", pcmcia_socket[sock].cs_state.io_irq); -+ p += sprintf(p, "I/O : %u\n", pcmcia_socket[sock].speed_io); -+ p += sprintf(p, "attribute: %u\n", pcmcia_socket[sock].speed_attr); -+ p += sprintf(p, "common : %u\n", pcmcia_socket[sock].speed_mem); -+ return p-buf; -+} -+ -+ -+#endif /* defined(CONFIG_PROC_FS) */ -diff -Naur linux.old/drivers/pcmcia/bcm4710_pcmcia.c linux.dev/drivers/pcmcia/bcm4710_pcmcia.c ---- linux.old/drivers/pcmcia/bcm4710_pcmcia.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/pcmcia/bcm4710_pcmcia.c 2006-04-06 15:34:15.000000000 +0200 -@@ -0,0 +1,266 @@ -+/* -+ * BCM4710 specific pcmcia routines. -+ * -+ * Copyright 2004, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++#endif /* _sbhnddma_h_ */ +diff -urN linux.old/drivers/parport/Config.in linux.dev/drivers/parport/Config.in +--- linux.old/drivers/parport/Config.in 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/drivers/parport/Config.in 2006-04-27 19:24:19.000000000 +0200 +@@ -11,6 +11,7 @@ + tristate 'Parallel port support' CONFIG_PARPORT + if [ "$CONFIG_PARPORT" != "n" ]; then + dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT ++ dep_tristate ' Asus WL500g parallel port' CONFIG_PARPORT_SPLINK $CONFIG_PARPORT + if [ "$CONFIG_PARPORT_PC" != "n" -a "$CONFIG_SERIAL" != "n" ]; then + if [ "$CONFIG_SERIAL" = "m" ]; then + define_tristate CONFIG_PARPORT_PC_CML1 m +diff -urN linux.old/drivers/parport/Makefile linux.dev/drivers/parport/Makefile +--- linux.old/drivers/parport/Makefile 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/drivers/parport/Makefile 2006-04-27 19:24:19.000000000 +0200 +@@ -22,6 +22,7 @@ + + obj-$(CONFIG_PARPORT) += parport.o + obj-$(CONFIG_PARPORT_PC) += parport_pc.o ++obj-$(CONFIG_PARPORT_SPLINK) += parport_splink.o + obj-$(CONFIG_PARPORT_PC_PCMCIA) += parport_cs.o + obj-$(CONFIG_PARPORT_AMIGA) += parport_amiga.o + obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o +diff -urN linux.old/drivers/parport/parport_splink.c linux.dev/drivers/parport/parport_splink.c +--- linux.old/drivers/parport/parport_splink.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/parport/parport_splink.c 2006-04-27 19:24:19.000000000 +0200 +@@ -0,0 +1,345 @@ ++/* Low-level parallel port routines for the ASUS WL-500g built-in port + * -+ * $Id: bcm4710_pcmcia.c,v 1.1 2005/03/16 13:50:00 wbx Exp $ ++ * Author: Nuno Grilo ++ * Based on parport_pc source + */ ++ ++#include +#include +#include -+#include -+#include +#include +#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#include ++#include ++#include + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "cs_internal.h" ++#define SPLINK_ADDRESS 0xBF800010 + -+#include -+#include -+#include ++#undef DEBUG ++ ++#ifdef DEBUG ++#define DPRINTK printk ++#else ++#define DPRINTK(stuff...) ++#endif + + -+#include -+#include -+#include -+#include -+#include ++/* __parport_splink_frob_control differs from parport_splink_frob_control in that ++ * it doesn't do any extra masking. */ ++static __inline__ unsigned char __parport_splink_frob_control (struct parport *p, ++ unsigned char mask, ++ unsigned char val) ++{ ++ struct parport_pc_private *priv = p->physport->private_data; ++ unsigned char *io = (unsigned char *) p->base; ++ unsigned char ctr = priv->ctr; ++#ifdef DEBUG_PARPORT ++ printk (KERN_DEBUG ++ "__parport_splink_frob_control(%02x,%02x): %02x -> %02x\n", ++ mask, val, ctr, ((ctr & ~mask) ^ val) & priv->ctr_writable); ++#endif ++ ctr = (ctr & ~mask) ^ val; ++ ctr &= priv->ctr_writable; /* only write writable bits. */ ++ *(io+2) = ctr; ++ priv->ctr = ctr; /* Update soft copy */ ++ return ctr; ++} + -+#include "bcm4710pcmcia.h" + -+/* Use a static var for irq dev_id */ -+static int bcm47xx_pcmcia_dev_id; + -+/* Do we think we have a card or not? */ -+static int bcm47xx_pcmcia_present = 0; ++static void parport_splink_data_forward (struct parport *p) ++{ ++ DPRINTK(KERN_DEBUG "parport_splink: parport_data_forward called\n"); ++ __parport_splink_frob_control (p, 0x20, 0); ++} + ++static void parport_splink_data_reverse (struct parport *p) ++{ ++ DPRINTK(KERN_DEBUG "parport_splink: parport_data_forward called\n"); ++ __parport_splink_frob_control (p, 0x20, 0x20); ++} + -+static void bcm4710_pcmcia_reset(void) ++/* ++static void parport_splink_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ -+ extifregs_t *eir; -+ unsigned long s; -+ uint32 out0, out1, outen; ++ DPRINTK(KERN_DEBUG "parport_splink: IRQ handler called\n"); ++ parport_generic_irq(irq, (struct parport *) dev_id, regs); ++} ++*/ ++ ++static void parport_splink_enable_irq(struct parport *p) ++{ ++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_enable_irq called\n"); ++ __parport_splink_frob_control (p, 0x10, 0x10); ++} + ++static void parport_splink_disable_irq(struct parport *p) ++{ ++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_disable_irq called\n"); ++ __parport_splink_frob_control (p, 0x10, 0); ++} ++ ++static void parport_splink_init_state(struct pardevice *dev, struct parport_state *s) ++{ ++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_init_state called\n"); ++ s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0); ++ if (dev->irq_func && ++ dev->port->irq != PARPORT_IRQ_NONE) ++ /* Set ackIntEn */ ++ s->u.pc.ctr |= 0x10; ++} + -+ eir = (extifregs_t *) ioremap_nocache(BCM4710_REG_EXTIF, sizeof(extifregs_t)); ++static void parport_splink_save_state(struct parport *p, struct parport_state *s) ++{ ++ const struct parport_pc_private *priv = p->physport->private_data; ++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_save_state called\n"); ++ s->u.pc.ctr = priv->ctr; ++} + -+ save_and_cli(s); ++static void parport_splink_restore_state(struct parport *p, struct parport_state *s) ++{ ++ struct parport_pc_private *priv = p->physport->private_data; ++ unsigned char *io = (unsigned char *) p->base; ++ unsigned char ctr = s->u.pc.ctr; + -+ /* Use gpio7 to reset the pcmcia slot */ -+ outen = readl(&eir->gpio[0].outen); -+ outen |= BCM47XX_PCMCIA_RESET; -+ out0 = readl(&eir->gpio[0].out); -+ out0 &= ~(BCM47XX_PCMCIA_RESET); -+ out1 = out0 | BCM47XX_PCMCIA_RESET; ++ DPRINTK(KERN_DEBUG "parport_splink: parport_splink_restore_state called\n"); ++ *(io+2) = ctr; ++ priv->ctr = ctr; ++} + -+ writel(out0, &eir->gpio[0].out); -+ writel(outen, &eir->gpio[0].outen); -+ mdelay(1); -+ writel(out1, &eir->gpio[0].out); -+ mdelay(1); -+ writel(out0, &eir->gpio[0].out); ++static void parport_splink_setup_interrupt(void) { ++ return; ++} + -+ restore_flags(s); ++static void parport_splink_write_data(struct parport *p, unsigned char d) { ++ DPRINTK(KERN_DEBUG "parport_splink: write data called\n"); ++ unsigned char *io = (unsigned char *) p->base; ++ *io = d; +} + ++static unsigned char parport_splink_read_data(struct parport *p) { ++ DPRINTK(KERN_DEBUG "parport_splink: read data called\n"); ++ unsigned char *io = (unsigned char *) p->base; ++ return *io; ++} + -+static int bcm4710_pcmcia_init(struct pcmcia_init *init) ++static void parport_splink_write_control(struct parport *p, unsigned char d) +{ -+ struct pci_dev *pdev; -+ extifregs_t *eir; -+ uint32 outen, intp, intm, tmp; -+ uint16 *attrsp; -+ int rc = 0, i; -+ extern unsigned long bcm4710_cpu_cycle; -+ -+ -+ if (!(pdev = pci_find_device(VENDOR_BROADCOM, SB_EXTIF, NULL))) { -+ printk(KERN_ERR "bcm4710_pcmcia: extif not found\n"); -+ return -ENODEV; -+ } -+ eir = (extifregs_t *) ioremap_nocache(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); -+ -+ /* Initialize the pcmcia i/f: 16bit no swap */ -+ writel(CF_EM_PCMCIA | CF_DS | CF_EN, &eir->pcmcia_config); -+ -+#ifdef notYet -+ -+ /* Set the timing for memory accesses */ -+ tmp = (19 / bcm4710_cpu_cycle) << 24; /* W3 = 10nS */ -+ tmp = tmp | ((29 / bcm4710_cpu_cycle) << 16); /* W2 = 20nS */ -+ tmp = tmp | ((109 / bcm4710_cpu_cycle) << 8); /* W1 = 100nS */ -+ tmp = tmp | (129 / bcm4710_cpu_cycle); /* W0 = 120nS */ -+ writel(tmp, &eir->pcmcia_memwait); /* 0x01020a0c for a 100Mhz clock */ -+ -+ /* Set the timing for I/O accesses */ -+ tmp = (19 / bcm4710_cpu_cycle) << 24; /* W3 = 10nS */ -+ tmp = tmp | ((29 / bcm4710_cpu_cycle) << 16); /* W2 = 20nS */ -+ tmp = tmp | ((109 / bcm4710_cpu_cycle) << 8); /* W1 = 100nS */ -+ tmp = tmp | (129 / bcm4710_cpu_cycle); /* W0 = 120nS */ -+ writel(tmp, &eir->pcmcia_iowait); /* 0x01020a0c for a 100Mhz clock */ -+ -+ /* Set the timing for attribute accesses */ -+ tmp = (19 / bcm4710_cpu_cycle) << 24; /* W3 = 10nS */ -+ tmp = tmp | ((29 / bcm4710_cpu_cycle) << 16); /* W2 = 20nS */ -+ tmp = tmp | ((109 / bcm4710_cpu_cycle) << 8); /* W1 = 100nS */ -+ tmp = tmp | (129 / bcm4710_cpu_cycle); /* W0 = 120nS */ -+ writel(tmp, &eir->pcmcia_attrwait); /* 0x01020a0c for a 100Mhz clock */ -+ -+#endif -+ /* Make sure gpio0 and gpio5 are inputs */ -+ outen = readl(&eir->gpio[0].outen); -+ outen &= ~(BCM47XX_PCMCIA_WP | BCM47XX_PCMCIA_STSCHG | BCM47XX_PCMCIA_RESET); -+ writel(outen, &eir->gpio[0].outen); -+ -+ /* Issue a reset to the pcmcia socket */ -+ bcm4710_pcmcia_reset(); -+ -+#ifdef DO_BCM47XX_PCMCIA_INTERRUPTS -+ /* Setup gpio5 to be the STSCHG interrupt */ -+ intp = readl(&eir->gpiointpolarity); -+ writel(intp | BCM47XX_PCMCIA_STSCHG, &eir->gpiointpolarity); /* Active low */ -+ intm = readl(&eir->gpiointmask); -+ writel(intm | BCM47XX_PCMCIA_STSCHG, &eir->gpiointmask); /* Enable it */ -+#endif -+ -+ DEBUG(2, "bcm4710_pcmcia after reset:\n"); -+ DEBUG(2, "\textstatus\t= 0x%08x:\n", readl(&eir->extstatus)); -+ DEBUG(2, "\tpcmcia_config\t= 0x%08x:\n", readl(&eir->pcmcia_config)); -+ DEBUG(2, "\tpcmcia_memwait\t= 0x%08x:\n", readl(&eir->pcmcia_memwait)); -+ DEBUG(2, "\tpcmcia_attrwait\t= 0x%08x:\n", readl(&eir->pcmcia_attrwait)); -+ DEBUG(2, "\tpcmcia_iowait\t= 0x%08x:\n", readl(&eir->pcmcia_iowait)); -+ DEBUG(2, "\tgpioin\t\t= 0x%08x:\n", readl(&eir->gpioin)); -+ DEBUG(2, "\tgpio_outen0\t= 0x%08x:\n", readl(&eir->gpio[0].outen)); -+ DEBUG(2, "\tgpio_out0\t= 0x%08x:\n", readl(&eir->gpio[0].out)); -+ DEBUG(2, "\tgpiointpolarity\t= 0x%08x:\n", readl(&eir->gpiointpolarity)); -+ DEBUG(2, "\tgpiointmask\t= 0x%08x:\n", readl(&eir->gpiointmask)); -+ -+#ifdef DO_BCM47XX_PCMCIA_INTERRUPTS -+ /* Request pcmcia interrupt */ -+ rc = request_irq(BCM47XX_PCMCIA_IRQ, init->handler, SA_INTERRUPT, -+ "PCMCIA Interrupt", &bcm47xx_pcmcia_dev_id); -+#endif ++ const unsigned char wm = (PARPORT_CONTROL_STROBE | ++ PARPORT_CONTROL_AUTOFD | ++ PARPORT_CONTROL_INIT | ++ PARPORT_CONTROL_SELECT); + -+ attrsp = (uint16 *)ioremap_nocache(EXTIF_PCMCIA_CFGBASE(BCM4710_EXTIF), 0x1000); -+ tmp = readw(&attrsp[0]); -+ DEBUG(2, "\tattr[0] = 0x%04x\n", tmp); -+ if ((tmp == 0x7fff) || (tmp == 0x7f00)) { -+ bcm47xx_pcmcia_present = 0; -+ } else { -+ bcm47xx_pcmcia_present = 1; ++ DPRINTK(KERN_DEBUG "parport_splink: write control called\n"); ++ /* Take this out when drivers have adapted to the newer interface. */ ++ if (d & 0x20) { ++ printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n", ++ p->name, p->cad->name); ++ parport_splink_data_reverse (p); + } + -+ /* There's only one socket */ -+ return 1; ++ __parport_splink_frob_control (p, wm, d & wm); +} + -+static int bcm4710_pcmcia_shutdown(void) ++static unsigned char parport_splink_read_control(struct parport *p) +{ -+ extifregs_t *eir; -+ uint32 intm; -+ -+ eir = (extifregs_t *) ioremap_nocache(BCM4710_REG_EXTIF, sizeof(extifregs_t)); -+ -+ /* Disable the pcmcia i/f */ -+ writel(0, &eir->pcmcia_config); -+ -+ /* Reset gpio's */ -+ intm = readl(&eir->gpiointmask); -+ writel(intm & ~BCM47XX_PCMCIA_STSCHG, &eir->gpiointmask); /* Disable it */ -+ -+ free_irq(BCM47XX_PCMCIA_IRQ, &bcm47xx_pcmcia_dev_id); -+ -+ return 0; ++ const unsigned char wm = (PARPORT_CONTROL_STROBE | ++ PARPORT_CONTROL_AUTOFD | ++ PARPORT_CONTROL_INIT | ++ PARPORT_CONTROL_SELECT); ++ DPRINTK(KERN_DEBUG "parport_splink: read control called\n"); ++ const struct parport_pc_private *priv = p->physport->private_data; ++ return priv->ctr & wm; /* Use soft copy */ +} + -+static int -+bcm4710_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state) ++static unsigned char parport_splink_frob_control (struct parport *p, unsigned char mask, ++ unsigned char val) +{ -+ extifregs_t *eir; -+ -+ eir = (extifregs_t *) ioremap_nocache(BCM4710_REG_EXTIF, sizeof(extifregs_t)); -+ ++ const unsigned char wm = (PARPORT_CONTROL_STROBE | ++ PARPORT_CONTROL_AUTOFD | ++ PARPORT_CONTROL_INIT | ++ PARPORT_CONTROL_SELECT); + -+ if (sock != 0) { -+ printk(KERN_ERR "bcm4710 socket_state bad sock %d\n", sock); -+ return -1; ++ DPRINTK(KERN_DEBUG "parport_splink: frob control called\n"); ++ /* Take this out when drivers have adapted to the newer interface. */ ++ if (mask & 0x20) { ++ printk (KERN_DEBUG "%s (%s): use data_%s for this!\n", ++ p->name, p->cad->name, ++ (val & 0x20) ? "reverse" : "forward"); ++ if (val & 0x20) ++ parport_splink_data_reverse (p); ++ else ++ parport_splink_data_forward (p); + } + -+ if (bcm47xx_pcmcia_present) { -+ state->detect = 1; -+ state->ready = 1; -+ state->bvd1 = 1; -+ state->bvd2 = 1; -+ state->wrprot = (readl(&eir->gpioin) & BCM47XX_PCMCIA_WP) == BCM47XX_PCMCIA_WP; -+ state->vs_3v = 0; -+ state->vs_Xv = 0; -+ } else { -+ state->detect = 0; -+ state->ready = 0; -+ } ++ /* Restrict mask and val to control lines. */ ++ mask &= wm; ++ val &= wm; + -+ return 1; ++ return __parport_splink_frob_control (p, mask, val); +} + -+ -+static int bcm4710_pcmcia_get_irq_info(struct pcmcia_irq_info *info) ++static unsigned char parport_splink_read_status(struct parport *p) +{ -+ if (info->sock >= BCM47XX_PCMCIA_MAX_SOCK) return -1; -+ -+ info->irq = BCM47XX_PCMCIA_IRQ; -+ -+ return 0; ++ DPRINTK(KERN_DEBUG "parport_splink: read status called\n"); ++ unsigned char *io = (unsigned char *) p->base; ++ return *(io+1); +} + -+ -+static int -+bcm4710_pcmcia_configure_socket(const struct pcmcia_configure *configure) ++static void parport_splink_inc_use_count(void) +{ -+ if (configure->sock >= BCM47XX_PCMCIA_MAX_SOCK) return -1; -+ ++#ifdef MODULE ++ MOD_INC_USE_COUNT; ++#endif ++} + -+ DEBUG(2, "Vcc %dV Vpp %dV output %d speaker %d reset %d\n", configure->vcc, -+ configure->vpp, configure->output, configure->speaker, configure->reset); ++static void parport_splink_dec_use_count(void) ++{ ++#ifdef MODULE ++ MOD_DEC_USE_COUNT; ++#endif ++} + -+ if ((configure->vcc != 50) || (configure->vpp != 50)) { -+ printk("%s: bad Vcc/Vpp (%d:%d)\n", __FUNCTION__, configure->vcc, -+ configure->vpp); -+ } ++static struct parport_operations parport_splink_ops = ++{ ++ parport_splink_write_data, ++ parport_splink_read_data, + -+ if (configure->reset) { -+ /* Issue a reset to the pcmcia socket */ -+ DEBUG(1, "%s: Reseting socket\n", __FUNCTION__); -+ bcm4710_pcmcia_reset(); -+ } ++ parport_splink_write_control, ++ parport_splink_read_control, ++ parport_splink_frob_control, + ++ parport_splink_read_status, + -+ return 0; -+} ++ parport_splink_enable_irq, ++ parport_splink_disable_irq, + -+struct pcmcia_low_level bcm4710_pcmcia_ops = { -+ bcm4710_pcmcia_init, -+ bcm4710_pcmcia_shutdown, -+ bcm4710_pcmcia_socket_state, -+ bcm4710_pcmcia_get_irq_info, -+ bcm4710_pcmcia_configure_socket -+}; ++ parport_splink_data_forward, ++ parport_splink_data_reverse, + -diff -Naur linux.old/drivers/pcmcia/bcm4710pcmcia.h linux.dev/drivers/pcmcia/bcm4710pcmcia.h ---- linux.old/drivers/pcmcia/bcm4710pcmcia.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/drivers/pcmcia/bcm4710pcmcia.h 2006-04-06 15:34:15.000000000 +0200 -@@ -0,0 +1,118 @@ -+/* -+ * -+ * bcm47xx pcmcia driver -+ * -+ * Copyright 2004, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * Based on sa1100.h and include/asm-arm/arch-sa1100/pcmica.h -+ * from www.handhelds.org, -+ * and au1000_generic.c from oss.sgi.com. -+ * -+ * $Id: bcm4710pcmcia.h,v 1.1 2005/03/16 13:50:00 wbx Exp $ -+ */ ++ parport_splink_init_state, ++ parport_splink_save_state, ++ parport_splink_restore_state, + -+#if !defined(_BCM4710PCMCIA_H) -+#define _BCM4710PCMCIA_H ++ parport_splink_inc_use_count, ++ parport_splink_dec_use_count, + -+#include -+#include -+#include -+#include -+#include "cs_internal.h" ++ parport_ieee1284_epp_write_data, ++ parport_ieee1284_epp_read_data, ++ parport_ieee1284_epp_write_addr, ++ parport_ieee1284_epp_read_addr, + ++ parport_ieee1284_ecp_write_data, ++ parport_ieee1284_ecp_read_data, ++ parport_ieee1284_ecp_write_addr, + -+/* The 47xx can only support one socket */ -+#define BCM47XX_PCMCIA_MAX_SOCK 1 ++ parport_ieee1284_write_compat, ++ parport_ieee1284_read_nibble, ++ parport_ieee1284_read_byte, ++}; + -+/* In the bcm947xx gpio's are used for some pcmcia functions */ -+#define BCM47XX_PCMCIA_WP 0x01 /* Bit 0 is WP input */ -+#define BCM47XX_PCMCIA_STSCHG 0x20 /* Bit 5 is STSCHG input/interrupt */ -+#define BCM47XX_PCMCIA_RESET 0x80 /* Bit 7 is RESET */ ++/* --- Initialisation code -------------------------------- */ + -+#define BCM47XX_PCMCIA_IRQ 2 ++static struct parport *parport_splink_probe_port (unsigned long int base) ++{ ++ struct parport_pc_private *priv; ++ struct parport_operations *ops; ++ struct parport *p; + -+/* The socket driver actually works nicely in interrupt-driven form, -+ * so the (relatively infrequent) polling is "just to be sure." -+ */ -+#define BCM47XX_PCMCIA_POLL_PERIOD (2 * HZ) ++ if (check_mem_region(base, 3)) { ++ printk (KERN_DEBUG "parport (0x%lx): iomem region not available\n", base); ++ return NULL; ++ } ++ priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL); ++ if (!priv) { ++ printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); ++ return NULL; ++ } ++ ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); ++ if (!ops) { ++ printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n", ++ base); ++ kfree (priv); ++ return NULL; ++ } ++ memcpy (ops, &parport_splink_ops, sizeof (struct parport_operations)); ++ priv->ctr = 0xc; ++ priv->ctr_writable = 0xff; + -+#define BCM47XX_PCMCIA_IO_SPEED (255) -+#define BCM47XX_PCMCIA_MEM_SPEED (300) ++ if (!(p = parport_register_port(base, PARPORT_IRQ_NONE, ++ PARPORT_DMA_NONE, ops))) { ++ printk (KERN_DEBUG "parport (0x%lx): registration failed!\n", ++ base); ++ kfree (priv); ++ kfree (ops); ++ return NULL; ++ } + ++ p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; ++ p->size = (p->modes & PARPORT_MODE_EPP)?8:3; ++ p->private_data = priv; + -+struct pcmcia_state { -+ unsigned detect: 1, -+ ready: 1, -+ bvd1: 1, -+ bvd2: 1, -+ wrprot: 1, -+ vs_3v: 1, -+ vs_Xv: 1; -+}; ++ parport_proc_register(p); ++ request_mem_region (p->base, 3, p->name); + ++ /* Done probing. Now put the port into a sensible start-up state. */ ++ parport_splink_write_data(p, 0); ++ parport_splink_data_forward (p); + -+struct pcmcia_configure { -+ unsigned sock: 8, -+ vcc: 8, -+ vpp: 8, -+ output: 1, -+ speaker: 1, -+ reset: 1; -+}; ++ /* Now that we've told the sharing engine about the port, and ++ found out its characteristics, let the high-level drivers ++ know about it. */ ++ parport_announce_port (p); + -+struct pcmcia_irq_info { -+ unsigned int sock; -+ unsigned int irq; -+}; ++ DPRINTK(KERN_DEBUG "parport (0x%lx): init ok!\n", ++ base); ++ return p; ++} + -+/* This structure encapsulates per-socket state which we might need to -+ * use when responding to a Card Services query of some kind. -+ */ -+struct bcm47xx_pcmcia_socket { -+ socket_state_t cs_state; -+ struct pcmcia_state k_state; -+ unsigned int irq; -+ void (*handler)(void *, unsigned int); -+ void *handler_info; -+ pccard_io_map io_map[MAX_IO_WIN]; -+ pccard_mem_map mem_map[MAX_WIN]; -+ ioaddr_t virt_io, phys_attr, phys_mem; -+ unsigned short speed_io, speed_attr, speed_mem; -+}; ++static void parport_splink_unregister_port(struct parport *p) { ++ struct parport_pc_private *priv = p->private_data; ++ struct parport_operations *ops = p->ops; + -+struct pcmcia_init { -+ void (*handler)(int irq, void *dev, struct pt_regs *regs); -+}; ++ if (p->irq != PARPORT_IRQ_NONE) ++ free_irq(p->irq, p); ++ release_mem_region(p->base, 3); ++ parport_proc_unregister(p); ++ kfree (priv); ++ parport_unregister_port(p); ++ kfree (ops); ++} + -+struct pcmcia_low_level { -+ int (*init)(struct pcmcia_init *); -+ int (*shutdown)(void); -+ int (*socket_state)(unsigned sock, struct pcmcia_state *); -+ int (*get_irq_info)(struct pcmcia_irq_info *); -+ int (*configure_socket)(const struct pcmcia_configure *); -+}; + -+extern struct pcmcia_low_level bcm47xx_pcmcia_ops; ++int parport_splink_init(void) ++{ ++ int ret; ++ ++ DPRINTK(KERN_DEBUG "parport_splink init called\n"); ++ parport_splink_setup_interrupt(); ++ ret = !parport_splink_probe_port(SPLINK_ADDRESS); ++ ++ return ret; ++} + -+/* I/O pins replacing memory pins -+ * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75) -+ * -+ * These signals change meaning when going from memory-only to -+ * memory-or-I/O interface: -+ */ -+#define iostschg bvd1 -+#define iospkr bvd2 ++void parport_splink_cleanup(void) { ++ struct parport *p = parport_enumerate(), *tmp; ++ DPRINTK(KERN_DEBUG "parport_splink cleanup called\n"); ++ if (p->size) { ++ if (p->modes & PARPORT_MODE_PCSPP) { ++ while(p) { ++ tmp = p->next; ++ parport_splink_unregister_port(p); ++ p = tmp; ++ } ++ } ++ } ++} + ++MODULE_AUTHOR("Nuno Grilo "); ++MODULE_DESCRIPTION("Parport Driver for ASUS WL-500g router builtin Port"); ++MODULE_SUPPORTED_DEVICE("ASUS WL-500g builtin Parallel Port"); ++MODULE_LICENSE("GPL"); + -+/* -+ * Declaration for implementation specific low_level operations. -+ */ -+extern struct pcmcia_low_level bcm4710_pcmcia_ops; ++module_init(parport_splink_init) ++module_exit(parport_splink_cleanup) + -+#endif /* !defined(_BCM4710PCMCIA_H) */ -diff -Naur linux.old/include/asm-mips/bootinfo.h linux.dev/include/asm-mips/bootinfo.h ---- linux.old/include/asm-mips/bootinfo.h 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/include/asm-mips/bootinfo.h 2006-04-06 15:34:15.000000000 +0200 +diff -urN linux.old/include/asm-mips/bootinfo.h linux.dev/include/asm-mips/bootinfo.h +--- linux.old/include/asm-mips/bootinfo.h 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/include/asm-mips/bootinfo.h 2006-04-27 19:24:19.000000000 +0200 @@ -37,6 +37,7 @@ #define MACH_GROUP_HP_LJ 20 /* Hewlett Packard LaserJet */ #define MACH_GROUP_LASAT 21 @@ -21942,9 +19939,9 @@ diff -Naur linux.old/include/asm-mips/bootinfo.h linux.dev/include/asm-mips/boot * Valid machtype for group TITAN */ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */ -diff -Naur linux.old/include/asm-mips/cpu.h linux.dev/include/asm-mips/cpu.h ---- linux.old/include/asm-mips/cpu.h 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/include/asm-mips/cpu.h 2006-04-06 15:34:15.000000000 +0200 +diff -urN linux.old/include/asm-mips/cpu.h linux.dev/include/asm-mips/cpu.h +--- linux.old/include/asm-mips/cpu.h 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/include/asm-mips/cpu.h 2006-04-27 19:24:19.000000000 +0200 @@ -22,6 +22,11 @@ spec. */ @@ -21993,9 +19990,9 @@ diff -Naur linux.old/include/asm-mips/cpu.h linux.dev/include/asm-mips/cpu.h /* * ISA Level encodings -diff -Naur linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kcache.h ---- linux.old/include/asm-mips/r4kcache.h 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/include/asm-mips/r4kcache.h 2006-04-06 15:34:15.000000000 +0200 +diff -urN linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kcache.h +--- linux.old/include/asm-mips/r4kcache.h 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/include/asm-mips/r4kcache.h 2006-04-27 19:24:19.000000000 +0200 @@ -658,4 +658,17 @@ cache128_unroll32(addr|ws,Index_Writeback_Inv_SD); } @@ -22014,9 +20011,9 @@ diff -Naur linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kc +} + #endif /* __ASM_R4KCACHE_H */ -diff -Naur linux.old/include/asm-mips/serial.h linux.dev/include/asm-mips/serial.h ---- linux.old/include/asm-mips/serial.h 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/include/asm-mips/serial.h 2006-04-06 15:34:15.000000000 +0200 +diff -urN linux.old/include/asm-mips/serial.h linux.dev/include/asm-mips/serial.h +--- linux.old/include/asm-mips/serial.h 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/include/asm-mips/serial.h 2006-04-27 19:24:19.000000000 +0200 @@ -223,6 +223,13 @@ #define TXX927_SERIAL_PORT_DEFNS #endif @@ -22039,9 +20036,9 @@ diff -Naur linux.old/include/asm-mips/serial.h linux.dev/include/asm-mips/serial COBALT_SERIAL_PORT_DEFNS \ DDB5477_SERIAL_PORT_DEFNS \ EV96100_SERIAL_PORT_DEFNS \ -diff -Naur linux.old/init/do_mounts.c linux.dev/init/do_mounts.c ---- linux.old/init/do_mounts.c 2006-04-06 15:38:09.000000000 +0200 -+++ linux.dev/init/do_mounts.c 2006-04-06 15:34:15.000000000 +0200 +diff -urN linux.old/init/do_mounts.c linux.dev/init/do_mounts.c +--- linux.old/init/do_mounts.c 2006-04-27 18:04:38.000000000 +0200 ++++ linux.dev/init/do_mounts.c 2006-04-27 19:24:19.000000000 +0200 @@ -254,7 +254,13 @@ { "ftlb", 0x2c08 }, { "ftlc", 0x2c10 }, diff --git a/target/linux/brcm-2.4/patches/009-wrt54g3g_pcmcia.patch b/target/linux/brcm-2.4/patches/009-wrt54g3g_pcmcia.patch new file mode 100644 index 0000000000..0759eeb40e --- /dev/null +++ b/target/linux/brcm-2.4/patches/009-wrt54g3g_pcmcia.patch @@ -0,0 +1,119 @@ +diff -urN linux.old/arch/mips/bcm947xx/pcibios.c linux.dev/arch/mips/bcm947xx/pcibios.c +--- linux.old/arch/mips/bcm947xx/pcibios.c 2006-04-07 21:20:59.000000000 +0200 ++++ linux.dev/arch/mips/bcm947xx/pcibios.c 2006-04-08 03:17:59.000000000 +0200 +@@ -157,6 +157,7 @@ + + static u32 pci_iobase = 0x100; + static u32 pci_membase = SB_PCI_DMA; ++static u32 pcmcia_membase = 0x40004000; + + void __init + pcibios_fixup_bus(struct pci_bus *b) +@@ -188,7 +189,7 @@ + /* Fix up resource bases */ + for (pos = 0; pos < 6; pos++) { + res = &d->resource[pos]; +- base = (res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase; ++ base = (res->flags & IORESOURCE_IO) ? &pci_iobase : ((b->number == 2) ? &pcmcia_membase : &pci_membase); + if (res->end) { + size = res->end - res->start + 1; + if (*base & (size - 1)) +@@ -308,7 +309,12 @@ + where = PCI_BASE_ADDRESS_0 + (resource * 4); + size = res->end - res->start; + pci_read_config_dword(dev, where, ®); +- reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); ++ ++ if (dev->bus->number == 1) ++ reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); ++ else ++ reg = res->start; ++ + pci_write_config_dword(dev, where, reg); + } + +diff -urN linux.old/drivers/pcmcia/yenta.c linux.dev/drivers/pcmcia/yenta.c +--- linux.old/drivers/pcmcia/yenta.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux.dev/drivers/pcmcia/yenta.c 2006-04-11 17:47:45.000000000 +0200 +@@ -543,6 +543,9 @@ + * Probe for usable interrupts using the force + * register to generate bogus card status events. + */ ++ ++#ifndef CONFIG_BCM947XX ++ /* WRT54G3G does not like this */ + cb_writel(socket, CB_SOCKET_EVENT, -1); + cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); + exca_writeb(socket, I365_CSCINT, 0); +@@ -557,7 +560,8 @@ + } + cb_writel(socket, CB_SOCKET_MASK, 0); + exca_writeb(socket, I365_CSCINT, 0); +- ++#endif ++ + mask = probe_irq_mask(val) & 0xffff; + + bridge_ctrl &= ~CB_BRIDGE_INTR; +@@ -578,6 +582,12 @@ + socket->cap.cb_dev = socket->dev; + socket->cap.bus = NULL; + ++#ifdef CONFIG_BCM947XX ++ /* irq mask probing is broken for the WRT54G3G */ ++ if (socket->cap.irq_mask == 0) ++ socket->cap.irq_mask = 0x6f8; ++#endif ++ + printk(KERN_INFO "Yenta ISA IRQ mask 0x%04x, PCI irq %d\n", + socket->cap.irq_mask, socket->cb_irq); + } +@@ -609,6 +619,15 @@ + printk(KERN_INFO "Socket status: %08x\n", + cb_readl(socket, CB_SOCKET_STATE)); + ++ /* Generate an interrupt on card insert/remove */ ++ config_writew(socket, CB_SOCKET_MASK, CB_CSTSMASK | CB_CDMASK); ++ ++ /* Set up Multifunction Routing Status Register */ ++ config_writew(socket, 0x8C, 0x1000 /* MFUNC3 to GPIO3 */ | 0x2 /* MFUNC0 to INTA */); ++ ++ /* Switch interrupts to parallelized */ ++ config_writeb(socket, 0x92, 0x64); ++ + /* Register it with the pcmcia layer.. */ + cardbus_register(socket); + +@@ -731,7 +750,7 @@ + { + struct pci_bus *bus; + struct resource *root, *res; +- u32 start, end; ++ u32 start = 0, end = 0; + u32 align, size, min, max; + unsigned offset; + unsigned mask; +@@ -750,6 +769,15 @@ + res->end = 0; + root = pci_find_parent_resource(socket->dev, res); + ++#ifdef CONFIG_BCM947XX ++ /* default mem resources are completely fscked up on the wrt54g3g */ ++ /* bypass the entire resource allocation stuff below and just set it statically */ ++ if (type & IORESOURCE_MEM) { ++ res->start = 0x40004000; ++ res->end = res->start + 0x3fff; ++ } ++ ++#else + if (!root) + return; + +@@ -794,6 +822,7 @@ + res->start = res->end = 0; + return; + } ++#endif + + config_writel(socket, offset, res->start); + config_writel(socket, offset+4, res->end); diff --git a/target/linux/brcm-2.6/Makefile b/target/linux/brcm-2.6/Makefile index 9f99fbd635..5926e6ebcd 100644 --- a/target/linux/brcm-2.6/Makefile +++ b/target/linux/brcm-2.6/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk -LINUX_VERSION:=2.6.16.4 +LINUX_VERSION:=2.6.16.7 LINUX_RELEASE:=1 -LINUX_KERNEL_MD5SUM:=cb675279c9711237a06ebb8379a4da27 +LINUX_KERNEL_MD5SUM:=9682b2bd6e02f3087982d7c3f5ba824e include ../rules.mk include ./config diff --git a/target/linux/control/kernel.control b/target/linux/control/kernel.control index 5432d21a0f..be5f10940d 100644 --- a/target/linux/control/kernel.control +++ b/target/linux/control/kernel.control @@ -1,6 +1,4 @@ Package: kernel Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Virtual package for the Kernel diff --git a/target/linux/control/kmod-arptables.control b/target/linux/control/kmod-arptables.control index 757db61bb0..6896388e6e 100644 --- a/target/linux/control/kmod-arptables.control +++ b/target/linux/control/kmod-arptables.control @@ -1,6 +1,4 @@ Package: kmod-arptables Priority: optional Section: net -Maintainer: Felix Fietkau -Source: buildroot internal Description: ARP firewalling kernel modules diff --git a/target/linux/control/kmod-atm.control b/target/linux/control/kmod-atm.control index ee78ebaf14..ae07126a6a 100644 --- a/target/linux/control/kmod-atm.control +++ b/target/linux/control/kmod-atm.control @@ -1,6 +1,4 @@ Package: kmod-atm Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: ATM/ADSL support diff --git a/target/linux/control/kmod-ax25.control b/target/linux/control/kmod-ax25.control index c080d45854..18c4cef8fe 100644 --- a/target/linux/control/kmod-ax25.control +++ b/target/linux/control/kmod-ax25.control @@ -1,6 +1,4 @@ Package: kmod-ax25 Priority: optional Section: net -Maintainer: Michael Conrad -Source: buildroot internal Description: Kernel AX25 driver diff --git a/target/linux/control/kmod-bluetooth.control b/target/linux/control/kmod-bluetooth.control index a9bd41ac3b..9f5409a9b7 100644 --- a/target/linux/control/kmod-bluetooth.control +++ b/target/linux/control/kmod-bluetooth.control @@ -1,6 +1,4 @@ Package: kmod-bluetooth Priority: optional Section: sys -Maintainer: Markus Becker -Source: http://bluez.org Description: Bluetooth support diff --git a/target/linux/control/kmod-brcm-et.control b/target/linux/control/kmod-brcm-et.control index a99a79aa90..3e65bc906a 100644 --- a/target/linux/control/kmod-brcm-et.control +++ b/target/linux/control/kmod-brcm-et.control @@ -1,6 +1,4 @@ Package: kmod-brcm-et Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Proprietary driver for Broadcom Ethernet chipsets diff --git a/target/linux/control/kmod-brcm-wl.control b/target/linux/control/kmod-brcm-wl.control index c8ec871226..cf610c3673 100644 --- a/target/linux/control/kmod-brcm-wl.control +++ b/target/linux/control/kmod-brcm-wl.control @@ -1,6 +1,4 @@ Package: kmod-brcm-wl Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Proprietary driver for Broadcom Wireless chipsets diff --git a/target/linux/control/kmod-brcm-wl2.control b/target/linux/control/kmod-brcm-wl2.control index 39f714c0c5..4ae019ddf9 100644 --- a/target/linux/control/kmod-brcm-wl2.control +++ b/target/linux/control/kmod-brcm-wl2.control @@ -1,7 +1,5 @@ Package: kmod-brcm-wl2 Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Proprietary driver for Broadcom Wireless chipsets New version with multi-BSS support diff --git a/target/linux/control/kmod-cpmac.control b/target/linux/control/kmod-cpmac.control index 35d75da0f8..18f8e901b6 100644 --- a/target/linux/control/kmod-cpmac.control +++ b/target/linux/control/kmod-cpmac.control @@ -1,6 +1,4 @@ Package: kmod-cpmac Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: AR7 CPMAC ethernet driver diff --git a/target/linux/control/kmod-crypto.control b/target/linux/control/kmod-crypto.control index 1d95456b33..199d33cd7d 100644 --- a/target/linux/control/kmod-crypto.control +++ b/target/linux/control/kmod-crypto.control @@ -1,6 +1,4 @@ Package: kmod-crypto Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: CryptoAPI kernel modules diff --git a/target/linux/control/kmod-ebtables.control b/target/linux/control/kmod-ebtables.control index 3437759e2d..85c2af9bcc 100644 --- a/target/linux/control/kmod-ebtables.control +++ b/target/linux/control/kmod-ebtables.control @@ -1,6 +1,4 @@ Package: kmod-ebtables Priority: optional Section: net -Maintainer: Felix Fietkau -Source: buildroot internal Description: Ethernet bridge firewalling kernel modules diff --git a/target/linux/control/kmod-gre.control b/target/linux/control/kmod-gre.control index bcf9a62554..42db0cce54 100644 --- a/target/linux/control/kmod-gre.control +++ b/target/linux/control/kmod-gre.control @@ -1,6 +1,4 @@ Package: kmod-gre Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel GRE tunneling support diff --git a/target/linux/control/kmod-ide.control b/target/linux/control/kmod-ide.control index 52cd4747ce..2b02d82257 100644 --- a/target/linux/control/kmod-ide.control +++ b/target/linux/control/kmod-ide.control @@ -1,6 +1,4 @@ Package: kmod-ide Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel modules IDE support diff --git a/target/linux/control/kmod-ip6tables.control b/target/linux/control/kmod-ip6tables.control index 777ab14bc4..6ccf422ffb 100644 --- a/target/linux/control/kmod-ip6tables.control +++ b/target/linux/control/kmod-ip6tables.control @@ -1,6 +1,4 @@ Package: kmod-ip6tables Priority: optional Section: net -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel modules for ip6tables diff --git a/target/linux/control/kmod-ipip.control b/target/linux/control/kmod-ipip.control new file mode 100644 index 0000000000..99bf0ec34b --- /dev/null +++ b/target/linux/control/kmod-ipip.control @@ -0,0 +1,4 @@ +Package: kmod-ipip +Section: sys +Priority: optional +Description: IP in IP encapsulation support diff --git a/target/linux/control/kmod-iptables-extra.control b/target/linux/control/kmod-iptables-extra.control index 2fd67d254b..96a3b1acc0 100644 --- a/target/linux/control/kmod-iptables-extra.control +++ b/target/linux/control/kmod-iptables-extra.control @@ -1,6 +1,4 @@ Package: kmod-iptables-extra Priority: optional Section: net -Maintainer: Felix Fietkau -Source: buildroot internal Description: Extra kernel modules for iptables diff --git a/target/linux/control/kmod-iptables.control b/target/linux/control/kmod-iptables.control index 259f802a4a..7f97cc44b6 100644 --- a/target/linux/control/kmod-iptables.control +++ b/target/linux/control/kmod-iptables.control @@ -1,6 +1,4 @@ Package: kmod-iptables Priority: optional Section: net -Maintainer: OpenWrt Development Team -Source: buildroot internal Description: kernel modules for iptables diff --git a/target/linux/control/kmod-ipv6.control b/target/linux/control/kmod-ipv6.control index b2b74a1202..3a6ccc9920 100644 --- a/target/linux/control/kmod-ipv6.control +++ b/target/linux/control/kmod-ipv6.control @@ -1,6 +1,4 @@ Package: kmod-ipv6 Priority: optional Section: net -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel modules for the IPv6 protocol diff --git a/target/linux/control/kmod-loop.control b/target/linux/control/kmod-loop.control index b84e84da57..48bcb835d6 100644 --- a/target/linux/control/kmod-loop.control +++ b/target/linux/control/kmod-loop.control @@ -1,6 +1,4 @@ Package: kmod-loop Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel module for mount loopback support diff --git a/target/linux/control/kmod-lp.control b/target/linux/control/kmod-lp.control index 7cc358edf5..5d40813159 100644 --- a/target/linux/control/kmod-lp.control +++ b/target/linux/control/kmod-lp.control @@ -1,6 +1,4 @@ Package: kmod-lp Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel modules for parallel port support and line printer diff --git a/target/linux/control/kmod-mppe.control b/target/linux/control/kmod-mppe.control index f5170168b9..e4aa4c963a 100644 --- a/target/linux/control/kmod-mppe.control +++ b/target/linux/control/kmod-mppe.control @@ -1,6 +1,4 @@ Package: kmod-mppe Priority: optional Section: net -Maintainer: Felix Fietkau -Source: buildroot internal Description: Microsoft PPP Encryption/Compression support diff --git a/target/linux/control/kmod-nbd.control b/target/linux/control/kmod-nbd.control index 899e2df352..3c467223bf 100644 --- a/target/linux/control/kmod-nbd.control +++ b/target/linux/control/kmod-nbd.control @@ -1,6 +1,4 @@ Package: kmod-nbd Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel module for network block device diff --git a/target/linux/control/kmod-nls-base.control b/target/linux/control/kmod-nls-base.control index 8e5514eea8..067f5dec86 100644 --- a/target/linux/control/kmod-nls-base.control +++ b/target/linux/control/kmod-nls-base.control @@ -1,6 +1,4 @@ Package: kmod-nls-base Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel modules for basic native language support diff --git a/target/linux/control/kmod-nls-cp437.control b/target/linux/control/kmod-nls-cp437.control index 0beb993d80..f47146083f 100644 --- a/target/linux/control/kmod-nls-cp437.control +++ b/target/linux/control/kmod-nls-cp437.control @@ -1,6 +1,4 @@ Package: kmod-nls-cp437 Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel module for codepage 437 diff --git a/target/linux/control/kmod-nls-cp850.control b/target/linux/control/kmod-nls-cp850.control index 8631ba2ae8..1a7d083f90 100644 --- a/target/linux/control/kmod-nls-cp850.control +++ b/target/linux/control/kmod-nls-cp850.control @@ -1,6 +1,4 @@ Package: kmod-nls-cp850 Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel module for codepage 850 diff --git a/target/linux/control/kmod-nls-iso8859-1.control b/target/linux/control/kmod-nls-iso8859-1.control index d4e88250e6..91e40faa7a 100644 --- a/target/linux/control/kmod-nls-iso8859-1.control +++ b/target/linux/control/kmod-nls-iso8859-1.control @@ -1,6 +1,4 @@ Package: kmod-nls-iso8859-1 Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel module for iso8859-1 charset support diff --git a/target/linux/control/kmod-nls-iso8859-15.control b/target/linux/control/kmod-nls-iso8859-15.control index 33b598eca0..f565e379e9 100644 --- a/target/linux/control/kmod-nls-iso8859-15.control +++ b/target/linux/control/kmod-nls-iso8859-15.control @@ -1,6 +1,4 @@ Package: kmod-nls-iso8859-15 Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel module for iso8859-15 charset support diff --git a/target/linux/control/kmod-nls-utf8.control b/target/linux/control/kmod-nls-utf8.control index cbbd14b8a4..8c5b23c37e 100644 --- a/target/linux/control/kmod-nls-utf8.control +++ b/target/linux/control/kmod-nls-utf8.control @@ -1,6 +1,4 @@ Package: kmod-nls-utf8 Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel module for utf8 support diff --git a/target/linux/control/kmod-ppp.control b/target/linux/control/kmod-ppp.control index c1d9875d53..d851e6526e 100644 --- a/target/linux/control/kmod-ppp.control +++ b/target/linux/control/kmod-ppp.control @@ -1,6 +1,4 @@ Package: kmod-ppp Priority: optional Section: net -Maintainer: Felix Fietkau -Source: buildroot internal Description: PPP support diff --git a/target/linux/control/kmod-pppoatm.control b/target/linux/control/kmod-pppoatm.control index 31c9550c12..c777362ab7 100644 --- a/target/linux/control/kmod-pppoatm.control +++ b/target/linux/control/kmod-pppoatm.control @@ -1,6 +1,4 @@ Package: kmod-pppoatm Priority: optional Section: net -Maintainer: Felix Fietkau -Source: buildroot internal Description: PPP over ATM support diff --git a/target/linux/control/kmod-pppoe.control b/target/linux/control/kmod-pppoe.control index 23986d4382..3216e2c889 100644 --- a/target/linux/control/kmod-pppoe.control +++ b/target/linux/control/kmod-pppoe.control @@ -1,6 +1,4 @@ Package: kmod-pppoe Priority: optional Section: net -Maintainer: Felix Fietkau -Source: buildroot internal Description: PPP over Ethernet support diff --git a/target/linux/control/kmod-pwc.control b/target/linux/control/kmod-pwc.control index ecd5485b44..2860eedf3d 100644 --- a/target/linux/control/kmod-pwc.control +++ b/target/linux/control/kmod-pwc.control @@ -1,6 +1,4 @@ Package: kmod-pwc Priority: optional Section: sys -Maintainer: Nicolas Thill -Source: http://openwrt.org/cgi-bin/viewcvs.cgi/openwrt/target/linux/linux-2.4/ Description: Kernel driver for USB Philips Cameras diff --git a/target/linux/control/kmod-sangam-atm-annex-a.control b/target/linux/control/kmod-sangam-atm-annex-a.control index 8406d7034d..e07e724565 100644 --- a/target/linux/control/kmod-sangam-atm-annex-a.control +++ b/target/linux/control/kmod-sangam-atm-annex-a.control @@ -1,6 +1,4 @@ Package: kmod-sangam-atm-annex-a Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: AR7 Sangam ATM/ADSL driver (Annex A version) diff --git a/target/linux/control/kmod-sangam-atm-annex-b.control b/target/linux/control/kmod-sangam-atm-annex-b.control index 487fe88fb7..7e6ff3f63e 100644 --- a/target/linux/control/kmod-sangam-atm-annex-b.control +++ b/target/linux/control/kmod-sangam-atm-annex-b.control @@ -1,6 +1,4 @@ Package: kmod-sangam-atm-annex-b Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: AR7 Sangam ATM/ADSL driver (Annex B version) diff --git a/target/linux/control/kmod-sched.control b/target/linux/control/kmod-sched.control index 8d1363f541..53e993de47 100644 --- a/target/linux/control/kmod-sched.control +++ b/target/linux/control/kmod-sched.control @@ -1,6 +1,4 @@ Package: kmod-sched Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel schedulers for IP traffic diff --git a/target/linux/control/kmod-softdog.control b/target/linux/control/kmod-softdog.control index 88a7400572..01aff7fe8e 100644 --- a/target/linux/control/kmod-softdog.control +++ b/target/linux/control/kmod-softdog.control @@ -1,6 +1,4 @@ Package: kmod-softdog Priority: optional Section: sys -Maintainer: OpenWrt Developers Team -Source: buildroot internal Description: Kernel software watchdog driver diff --git a/target/linux/control/kmod-soundcore.control b/target/linux/control/kmod-soundcore.control index ea0323b10f..6b4fffa058 100644 --- a/target/linux/control/kmod-soundcore.control +++ b/target/linux/control/kmod-soundcore.control @@ -1,6 +1,4 @@ Package: kmod-soundcore Priority: optional Section: sys -Maintainer: OpenWrt Developers Team , David Collett -Source: buildroot internal Description: Kernel support for audio soundcards diff --git a/target/linux/control/kmod-tun.control b/target/linux/control/kmod-tun.control index c70b75353c..b60a8feee5 100644 --- a/target/linux/control/kmod-tun.control +++ b/target/linux/control/kmod-tun.control @@ -1,6 +1,4 @@ Package: kmod-tun Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel TUN/TAP extension diff --git a/target/linux/control/kmod-usb-acm.control b/target/linux/control/kmod-usb-acm.control index 1a9a2de74e..8d1fca496b 100644 --- a/target/linux/control/kmod-usb-acm.control +++ b/target/linux/control/kmod-usb-acm.control @@ -1,6 +1,4 @@ Package: kmod-usb-acm Priority: optional Section: sys -Maintainer: Waldemar Brodkorb -Source: buildroot internal Description: Kernel modules for USB modems and ISDN diff --git a/target/linux/control/kmod-usb-atm-speedtouch.control b/target/linux/control/kmod-usb-atm-speedtouch.control index 25e20739d5..e8ded69d48 100644 --- a/target/linux/control/kmod-usb-atm-speedtouch.control +++ b/target/linux/control/kmod-usb-atm-speedtouch.control @@ -1,6 +1,4 @@ Package: kmod-usb-atm-speedtouch Priority: optional Section: sys -Maintainer: Jonathan McDowell -Source: buildroot internal Description: Kernel driver for USB Speedtouch ADSL modem diff --git a/target/linux/control/kmod-usb-audio.control b/target/linux/control/kmod-usb-audio.control index 367c590570..d30b8f2c70 100644 --- a/target/linux/control/kmod-usb-audio.control +++ b/target/linux/control/kmod-usb-audio.control @@ -1,7 +1,5 @@ Package: kmod-usb-audio Priority: optional Section: sys -Maintainer: David Collett -Source: buildroot internal Depends: kmod-soundcore Description: Kernel Support for USB Soundcards diff --git a/target/linux/control/kmod-usb-core.control b/target/linux/control/kmod-usb-core.control index 2e69662969..fa1c13bbd8 100644 --- a/target/linux/control/kmod-usb-core.control +++ b/target/linux/control/kmod-usb-core.control @@ -1,6 +1,4 @@ Package: kmod-usb-core Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel Support for USB diff --git a/target/linux/control/kmod-usb-ohci.control b/target/linux/control/kmod-usb-ohci.control index adb6e27635..3d0edc863c 100644 --- a/target/linux/control/kmod-usb-ohci.control +++ b/target/linux/control/kmod-usb-ohci.control @@ -1,6 +1,4 @@ Package: kmod-usb-ohci Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel driver for OHCI USB controllers diff --git a/target/linux/control/kmod-usb-printer.control b/target/linux/control/kmod-usb-printer.control index b9f13fec6c..1c47a3d176 100644 --- a/target/linux/control/kmod-usb-printer.control +++ b/target/linux/control/kmod-usb-printer.control @@ -1,6 +1,4 @@ Package: kmod-usb-printer Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel modules for USB Printer support diff --git a/target/linux/control/kmod-usb-serial-belkin.control b/target/linux/control/kmod-usb-serial-belkin.control index 708cc44351..d907a9702b 100644 --- a/target/linux/control/kmod-usb-serial-belkin.control +++ b/target/linux/control/kmod-usb-serial-belkin.control @@ -1,6 +1,4 @@ Package: kmod-usb-serial-belkin Priority: optional Section: sys -Maintainer: OpenWrt Developers Team -Source: buildroot internal Description: Kernel Support for Belkin USB-to-Serial converters diff --git a/target/linux/control/kmod-usb-serial-ftdi.control b/target/linux/control/kmod-usb-serial-ftdi.control index 16bcdca254..e845294a5f 100644 --- a/target/linux/control/kmod-usb-serial-ftdi.control +++ b/target/linux/control/kmod-usb-serial-ftdi.control @@ -1,6 +1,4 @@ Package: kmod-usb-serial-ftdi Priority: optional Section: sys -Maintainer: OpenWrt Developers Team -Source: buildroot internal Description: Kernel Support for FTDI USB-to-Serial converters diff --git a/target/linux/control/kmod-usb-serial-mct-u232.control b/target/linux/control/kmod-usb-serial-mct-u232.control index 00f2038bf0..b52b7ca7b3 100644 --- a/target/linux/control/kmod-usb-serial-mct-u232.control +++ b/target/linux/control/kmod-usb-serial-mct-u232.control @@ -1,6 +1,4 @@ Package: kmod-usb-serial-mct-u232 Priority: optional Section: sys -Maintainer: OpenWrt Developers Team -Source: buildroot internal Description: Kernel Support for Magic Control Technology USB-to-Serial converters diff --git a/target/linux/control/kmod-usb-serial-pl2303.control b/target/linux/control/kmod-usb-serial-pl2303.control index bccbdd8924..4de43bd510 100644 --- a/target/linux/control/kmod-usb-serial-pl2303.control +++ b/target/linux/control/kmod-usb-serial-pl2303.control @@ -1,6 +1,4 @@ Package: kmod-usb-serial-pl2303 Priority: optional Section: sys -Maintainer: OpenWrt Developers Team -Source: buildroot internal Description: Kernel Support for Prolific PL2303 USB-to-Serial converters diff --git a/target/linux/control/kmod-usb-serial-visor.control b/target/linux/control/kmod-usb-serial-visor.control index 7b993beafd..951c00c51f 100644 --- a/target/linux/control/kmod-usb-serial-visor.control +++ b/target/linux/control/kmod-usb-serial-visor.control @@ -1,7 +1,4 @@ Package: kmod-usb-serial-visor Priority: optional Section: sys -Maintainer: OpenWrt Developers Team -Source: buildroot internal -Description: Kernel Support for Handspring Visor / Palm m50x / Sony Clie -Driver +Description: Kernel Support for Handspring Visor / Palm m50x / Sony Clie Driver diff --git a/target/linux/control/kmod-usb-serial.control b/target/linux/control/kmod-usb-serial.control index dda5f9d01a..136fca752f 100644 --- a/target/linux/control/kmod-usb-serial.control +++ b/target/linux/control/kmod-usb-serial.control @@ -1,6 +1,4 @@ Package: kmod-usb-serial Priority: optional Section: sys -Maintainer: OpenWrt Developers Team -Source: buildroot internal Description: Kernel Support for USB-to-Serial converters diff --git a/target/linux/control/kmod-usb-storage.control b/target/linux/control/kmod-usb-storage.control index 4156a0d91d..4ee70eb8a9 100644 --- a/target/linux/control/kmod-usb-storage.control +++ b/target/linux/control/kmod-usb-storage.control @@ -1,6 +1,4 @@ Package: kmod-usb-storage Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel modules for USB storage support diff --git a/target/linux/control/kmod-usb-uhci.control b/target/linux/control/kmod-usb-uhci.control index c7e678f188..09966a8a0e 100644 --- a/target/linux/control/kmod-usb-uhci.control +++ b/target/linux/control/kmod-usb-uhci.control @@ -1,6 +1,4 @@ Package: kmod-usb-uhci Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel driver for UHCI USB controllers diff --git a/target/linux/control/kmod-usb2.control b/target/linux/control/kmod-usb2.control index 48da3a6fc8..338865e524 100644 --- a/target/linux/control/kmod-usb2.control +++ b/target/linux/control/kmod-usb2.control @@ -1,6 +1,4 @@ Package: kmod-usb2 Priority: optional Section: sys -Maintainer: Felix Fietkau -Source: buildroot internal Description: Kernel driver for USB2 controllers diff --git a/target/linux/control/kmod-videodev.control b/target/linux/control/kmod-videodev.control index c8526835c4..57c0b1cdfe 100644 --- a/target/linux/control/kmod-videodev.control +++ b/target/linux/control/kmod-videodev.control @@ -1,6 +1,4 @@ Package: kmod-videodev Priority: optional Section: sys -Maintainer: Nicolas Thill -Source: http://openwrt.org/cgi-bin/viewcvs.cgi/openwrt/target/linux/linux-2.4/ Description: Video For Linux kernel support diff --git a/target/linux/control/kmod-wd1100.control b/target/linux/control/kmod-wd1100.control index d81924e8a8..32163200ec 100644 --- a/target/linux/control/kmod-wd1100.control +++ b/target/linux/control/kmod-wd1100.control @@ -1,6 +1,4 @@ Package: kmod-wd1100 Priority: optional Section: sys -Maintainer: OpenWrt Developers Team -Source: http://openwrt.org/cgi-bin/viewcvs.cgi/openwrt/target/linux/ Description: NatSemi SC1x00 series Watchdog kernel support diff --git a/target/linux/generic-2.4/modules.mk b/target/linux/generic-2.4/modules.mk index f35e9ba56b..540ac715cc 100644 --- a/target/linux/generic-2.4/modules.mk +++ b/target/linux/generic-2.4/modules.mk @@ -12,9 +12,12 @@ $(eval $(call KMOD_template,GRE,gre,\ ,CONFIG_NET_IPGRE)) $(eval $(call KMOD_template,IMQ,imq,\ - $(MODULES_DIR)/kernel/net/*/netfilter/*IMQ*.o \ + $(MODULES_DIR)/kernel/net/ipv4/netfilter/*IMQ*.o \ $(MODULES_DIR)/kernel/drivers/net/imq.o \ )) +$(eval $(call KMOD_template,IPIP,ipip,\ + $(MODULES_DIR)/kernel/net/ipv4/ipip.o \ +,CONFIG_NET_IPIP,,60,ipip)) $(eval $(call KMOD_template,IPV6,ipv6,\ $(MODULES_DIR)/kernel/net/ipv6/ipv6.o \ @@ -39,12 +42,9 @@ $(eval $(call KMOD_template,PPPOE,pppoe,\ $(MODULES_DIR)/kernel/drivers/net/pppoe.o \ ,CONFIG_PPPOE)) -ifneq ($(wildcard $(MODULES_DIR)/kernel/net/sched/*.o),) -CONFIG_SCHED:=m -endif $(eval $(call KMOD_template,SCHED,sched,\ $(MODULES_DIR)/kernel/net/sched/*.o \ -,CONFIG_SCHED)) +)) $(eval $(call KMOD_template,TUN,tun,\ $(MODULES_DIR)/kernel/drivers/net/tun.o \ diff --git a/target/linux/generic-2.6/modules.mk b/target/linux/generic-2.6/modules.mk index ab8a5f5d51..b582400bd6 100644 --- a/target/linux/generic-2.6/modules.mk +++ b/target/linux/generic-2.6/modules.mk @@ -14,10 +14,14 @@ $(eval $(call KMOD_template,GRE,gre,\ ,CONFIG_NET_IPGRE)) $(eval $(call KMOD_template,IMQ,imq,\ - $(MODULES_DIR)/kernel/net/*/netfilter/*IMQ*.ko \ + $(MODULES_DIR)/kernel/net/ipv4/netfilter/*IMQ*.ko \ $(MODULES_DIR)/kernel/drivers/net/imq.ko \ )) +$(eval $(call KMOD_template,IPIP,ipip,\ + $(MODULES_DIR)/kernel/net/ipv4/ipip.ko \ +,CONFIG_NET_IPIP,,60,ipip)) + $(eval $(call KMOD_template,IPV6,ipv6,\ $(MODULES_DIR)/kernel/net/ipv6/ipv6.ko \ ,CONFIG_IPV6,,20,ipv6)) diff --git a/target/linux/generic-2.6/patches/005-gcc4_fix.patch b/target/linux/generic-2.6/patches/005-gcc4_fix.patch index 91da40ac37..72df58184d 100644 --- a/target/linux/generic-2.6/patches/005-gcc4_fix.patch +++ b/target/linux/generic-2.6/patches/005-gcc4_fix.patch @@ -179,7 +179,19 @@ diff -Nur linux-2.6.15.1/lib/Makefile linux-2.6.15.1-openwrt/lib/Makefile sha1.o lib-y += kobject.o kref.o kobject_uevent.o klist.o -+lib-y += ashldi3.o ashrdi3.o lshrdi3.o ++obj-y += ashldi3.o ashrdi3.o lshrdi3.o obj-y += sort.o parser.o halfmd4.o +diff -Nur linux-2.6.15.1/include/asm-arm/libgcc.h linux-2.6.15.1-openwrt/include/asm-arm/libgcc.h +--- linux-2.6.15.1/include/asm-arm/libgcc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.15.1-openwrt/include/asm-arm/libgcc.h 2006-04-12 23:01:18.000000000 +0200 +@@ -0,0 +1,8 @@ ++#ifndef __ASM_LIBGCC_H ++#define __ASM_LIBGCC_H ++ ++#undef ARCH_NEEDS_ashldi3 ++#undef ARCH_NEEDS_ashrdi3 ++#undef ARCH_NEEDS_lshrdi3 ++ ++#endif /* __ASM_LIBGCC_H */ diff --git a/target/linux/image/au1000/Makefile b/target/linux/image/au1000/Makefile index 04a89f9b19..c7158ca761 100644 --- a/target/linux/image/au1000/Makefile +++ b/target/linux/image/au1000/Makefile @@ -1,17 +1,42 @@ include $(TOPDIR)/rules.mk -KDIR:=$(BUILD_DIR)/linux-$(KERNEL)-$(BOARD) +LOADADDR = 0x8108c8f4 # RAM start + 16M +KERNEL_ENTRY = 0x80100000 # Default kernel entry in arch/mips/Makefile +RAMSIZE = 0x04000000 # 64MB +LOADER_MAKEOPTS= \ + KDIR=$(KDIR) \ + LOADADDR=$(LOADADDR) \ + KERNEL_ENTRY=$(KERNEL_ENTRY) \ + RAMSIZE=$(RAMSIZE) -ifeq ($(FS),jffs2-8MB) +KDIR:=$(BUILD_DIR)/linux-$(KERNEL)-$(BOARD) -$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS).img: $(KDIR)/root.$(FS) - $(CP) $^ $@ +lzma-loader-clean: + $(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) clean -install: $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS).img +lzma-loader-prepare: + $(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) prepare +lzma-loader-compile: $(KDIR)/vmlinux.lzma lzma-loader-prepare + $(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) compile + +ifeq ($(IB),) +$(KDIR)/vmlinux.lzma: $(KDIR)/vmlinux + cat $^ | $(STAGING_DIR)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $@ || (rm -f $@ && false) + +install: $(KDIR)/vmlinux.lzma endif +ifeq ($(FS),jffs2-8MB) + +$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FSNAME).bin: $(KDIR)/root.$(FS) + $(TARGET_CROSS)objcopy -O srec -I binary --adjust-vma 0xbe000000 $(KDIR)/root.$(FS) $(KDIR)/root.srec + grep -v S7 $(KDIR)/root.srec > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS).img + grep -v S0 $(LINUX_DIR)/arch/mips/boot/compressed/images/zImage.flash.srec >> $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS).img + +install: $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FSNAME).bin +endif ifeq ($(FS),tgz) @@ -22,15 +47,30 @@ install: $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-rootfs.tar.gz endif +ifeq ($(FS),squashfs) +$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FSNAME).bin: $(KDIR)/root.$(FS) + $(TARGET_CROSS)objcopy -O srec -I binary --adjust-vma 0xbe000000 $(KDIR)/root.$(FS) $(KDIR)/root.srec + grep -v S7 $(KDIR)/root.srec > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS).img + grep -v S0 $(LINUX_DIR)/arch/mips/boot/compressed/images/zImage.flash.srec >> $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS).img -$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinuz: $(KDIR)/vmlinux - $(CP) $^ $@ +endif +$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinuz: $(KDIR)/zImage.flash + $(CP) $^ $@ +ifeq ($(IB),) +clean: lzma-loader-clean +prepare: lzma-loader-prepare +compile: lzma-loader-compile +else clean: prepare: compile: -install: $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinuz +endif install-ib: + mkdir -p $(IB_DIR)/staging_dir_$(ARCH)/bin mkdir -p $(IB_DIR)/build_$(ARCH)/linux-$(KERNEL)-$(BOARD) - $(CP) $(KDIR)/bzImage $(IB_DIR)/build_$(ARCH)/linux-$(KERNEL)-$(BOARD)/ + $(CP) $(KDIR)/loader.elf $(IB_DIR)/build_$(ARCH)/ + $(CP) $(KDIR)/vmlinux.lzma $(IB_DIR)/build_$(ARCH)/linux-$(KERNEL)-$(BOARD)/ + $(TARGET_CROSS)objcopy -O srec -I binary --adjust-vma 0xbe000000 $(KDIR)/loader.elf $(KDIR)/loader.srec + grep -v S0 $(KDIR)/loader.srec > $(KDIR)/kernel.srec diff --git a/target/linux/image/jffs2.mk b/target/linux/image/jffs2.mk index 7df3aedbcf..432df3e2b1 100644 --- a/target/linux/image/jffs2.mk +++ b/target/linux/image/jffs2.mk @@ -1,4 +1,4 @@ -ifneq ($(CONFIG_mips),y) +ifneq ($(CONFIG_BIG_ENDIAN),y) JFFS2OPTS := --pad --little-endian --squash else JFFS2OPTS := --pad --big-endian --squash diff --git a/target/linux/image/squashfs.mk b/target/linux/image/squashfs.mk index 29ce5522d5..abc58da1e4 100644 --- a/target/linux/image/squashfs.mk +++ b/target/linux/image/squashfs.mk @@ -1,7 +1,7 @@ +ifneq ($(CONFIG_BIG_ENDIAN),y) endian := le - -ifeq ($(ARCH),mips) - endian := be +else +endian := be endif squashfs-prepare: diff --git a/target/linux/image/xscale/Makefile b/target/linux/image/xscale/Makefile new file mode 100644 index 0000000000..04a89f9b19 --- /dev/null +++ b/target/linux/image/xscale/Makefile @@ -0,0 +1,36 @@ +include $(TOPDIR)/rules.mk + +KDIR:=$(BUILD_DIR)/linux-$(KERNEL)-$(BOARD) + + +ifeq ($(FS),jffs2-8MB) + +$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS).img: $(KDIR)/root.$(FS) + $(CP) $^ $@ + +install: $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS).img + +endif + + +ifeq ($(FS),tgz) + +$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-rootfs.tar.gz: $(KDIR)/root.tar.gz + $(CP) $^ $@ + +install: $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-rootfs.tar.gz + +endif + + +$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinuz: $(KDIR)/vmlinux + $(CP) $^ $@ + + +clean: +prepare: +compile: +install: $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinuz +install-ib: + mkdir -p $(IB_DIR)/build_$(ARCH)/linux-$(KERNEL)-$(BOARD) + $(CP) $(KDIR)/bzImage $(IB_DIR)/build_$(ARCH)/linux-$(KERNEL)-$(BOARD)/ diff --git a/target/linux/kernel.mk b/target/linux/kernel.mk index 00ff102d58..f8f4700525 100644 --- a/target/linux/kernel.mk +++ b/target/linux/kernel.mk @@ -103,8 +103,10 @@ mostlyclean: rebuild: -$(MAKE) mostlyclean - @[ -f $(LINUX_KERNEL) ] && $(MAKE) clean - $(MAKE) compile + if [ -f $(LINUX_KERNEL) ]; then \ + $(MAKE) clean; \ + fi + $(MAKE) compile $(MAKE_TRACE) clean: rm -f $(STAMP_DIR)/.linux-compile diff --git a/target/linux/package/Makefile b/target/linux/package/Makefile index 792fb7bd67..f24c845d79 100644 --- a/target/linux/package/Makefile +++ b/target/linux/package/Makefile @@ -6,8 +6,6 @@ package-y += base-files package-$(CONFIG_PACKAGE_KMOD_ALSA) += alsa package-$(CONFIG_PACKAGE_KMOD_FUSE) += fuse package-$(CONFIG_PACKAGE_KMOD_HOSTAP) += hostap -package-$(CONFIG_PACKAGE_KMOD_BCM43XX_STANDALONE) += bcm43xx-standalone -package-$(CONFIG_PACKAGE_KMOD_IEEE80211_DSCAPE) += ieee80211-dscape package-$(CONFIG_PACKAGE_KMOD_MADWIFI) += madwifi package-$(CONFIG_PACKAGE_KMOD_MADWIFI_OLD) += madwifi-old package-$(CONFIG_PACKAGE_KMOD_MINI_FO) += mini_fo @@ -20,7 +18,6 @@ package-$(CONFIG_PACKAGE_KMOD_DIAG) += diag package-$(CONFIG_PACKAGE_KMOD_WLCOMPAT) += wlcompat package-$(CONFIG_PACKAGE_KMOD_ZD1211) += zd1211 -bcm43xx-standalone-compile: ieee80211-dscape-compile wlcompat-compile: base-files-compile all: compile install diff --git a/target/linux/package/base-files/files/au1000-2.6/sbin/mount_root b/target/linux/package/base-files/files/au1000-2.6/sbin/mount_root new file mode 100755 index 0000000000..5dd1b0c562 --- /dev/null +++ b/target/linux/package/base-files/files/au1000-2.6/sbin/mount_root @@ -0,0 +1,23 @@ +#!/bin/sh +size=$(awk '/Mem:/ {l=5242880;print((s=$2/2)&- + if [ $? = 0 ] ; then + if [ $(cat /proc/mtd | wc -l) = 6 ]; then + mtd erase filesystem + jffs2root --move + else + mount -o remount,rw /dev/root / + fi + else + . /bin/firstboot + fi +fi + +mount none /tmp -t tmpfs -o remount,nosuid,nodev,mode=1777 +mkdir -p /dev/pts +mount none /dev/pts -t devpts +mount -t sysfs none /sys 2>&- diff --git a/target/linux/package/base-files/files/brcm-2.4/etc/hotplug.d/net/09-net b/target/linux/package/base-files/files/brcm-2.4/etc/hotplug.d/net/09-net index 856d26b653..9dd77963ba 100644 --- a/target/linux/package/base-files/files/brcm-2.4/etc/hotplug.d/net/09-net +++ b/target/linux/package/base-files/files/brcm-2.4/etc/hotplug.d/net/09-net @@ -1,5 +1,5 @@ #!/bin/sh -setup_eth() +setup_wl() { [ -f /proc/net/wl0 ] && { lsmod | grep wlcompat >&- || insmod wlcompat @@ -7,6 +7,9 @@ setup_eth() iwconfig "$INTERFACE" 2>&- | grep -v 'no wireless' >&- && { /sbin/wifi } +} +setup_eth() +{ [ -d /proc/switch ] || { insmod switch-core insmod switch-robo || insmod switch-adm @@ -30,6 +33,7 @@ do_register() { case "${INTERFACE%%[0-9]*}" in eth) setup_eth;; + wl) setup_wl;; esac } diff --git a/target/linux/package/base-files/files/sibyte-2.6/etc/config/network b/target/linux/package/base-files/files/sibyte-2.6/etc/config/network new file mode 100644 index 0000000000..2cc9e26717 --- /dev/null +++ b/target/linux/package/base-files/files/sibyte-2.6/etc/config/network @@ -0,0 +1,12 @@ +# Network configuration file + +## LAN configuration +lan_ifname="br0" +lan_ifnames="eth0 ath0" +lan_proto="static" +lan_ipaddr="192.168.1.1" +lan_netmask="255.255.255.0" + +## WAN configuration +wan_ifname="" +wan_proto="none" diff --git a/target/linux/package/base-files/files/sibyte-2.6/etc/inittab b/target/linux/package/base-files/files/sibyte-2.6/etc/inittab new file mode 100644 index 0000000000..6eef29efba --- /dev/null +++ b/target/linux/package/base-files/files/sibyte-2.6/etc/inittab @@ -0,0 +1,3 @@ +::sysinit:/etc/init.d/rcS +duart/0::askfirst:/bin/ash --login +#tts/1::askfirst:/bin/ash --login diff --git a/target/linux/package/base-files/files/sibyte-2.6/init b/target/linux/package/base-files/files/sibyte-2.6/init new file mode 100755 index 0000000000..1f98589eb6 --- /dev/null +++ b/target/linux/package/base-files/files/sibyte-2.6/init @@ -0,0 +1,6 @@ +#!/bin/ash +mount none /dev -t devfs +mount none /proc -t proc +mount_root failsafe +mount -o remount,rw /dev/root / +exec /bin/busybox init diff --git a/target/linux/package/base-files/files/xscale-2.6/etc/config/network b/target/linux/package/base-files/files/xscale-2.6/etc/config/network new file mode 100644 index 0000000000..f60332cd8c --- /dev/null +++ b/target/linux/package/base-files/files/xscale-2.6/etc/config/network @@ -0,0 +1,5 @@ +# Network configuration file + +## LAN configuration +lan_ifname="eth0" +lan_proto="dhcp" diff --git a/target/linux/package/base-files/files/xscale-2.6/etc/init.d/S00xscale b/target/linux/package/base-files/files/xscale-2.6/etc/init.d/S00xscale new file mode 100755 index 0000000000..9836de423b --- /dev/null +++ b/target/linux/package/base-files/files/xscale-2.6/etc/init.d/S00xscale @@ -0,0 +1,4 @@ +#!/bin/sh +mount none /proc -t proc +mount_root failsafe +mount -o remount,rw /dev/root / diff --git a/target/linux/package/base-files/files/xscale-2.6/init b/target/linux/package/base-files/files/xscale-2.6/init new file mode 100755 index 0000000000..8ca48a04c1 --- /dev/null +++ b/target/linux/package/base-files/files/xscale-2.6/init @@ -0,0 +1,3 @@ +#!/bin/ash +mount none /dev -t devfs +exec /bin/busybox init diff --git a/target/linux/package/bcm43xx-standalone/Config.in b/target/linux/package/bcm43xx-standalone/Config.in deleted file mode 100644 index 84a4702cf2..0000000000 --- a/target/linux/package/bcm43xx-standalone/Config.in +++ /dev/null @@ -1,12 +0,0 @@ -config PACKAGE_KMOD_BCM43XX_STANDALONE - prompt "kmod-bcm43xx-standalone............... Free Broadcom 43xx wireless driver (devicescape stack)" - tristate - depends LINUX_2_6_BRCM - select PACKAGE_KMOD_IEEE80211_DSCAPE - default n - help - Free driver for the Broadcom 43xx wireless chipset - This driver uses the DeviceScape 802.11 stack - - http://bcm43xx.berlios.de - diff --git a/target/linux/package/bcm43xx-standalone/Makefile b/target/linux/package/bcm43xx-standalone/Makefile deleted file mode 100644 index fed1628eee..0000000000 --- a/target/linux/package/bcm43xx-standalone/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# $Id$ - -include $(TOPDIR)/rules.mk -include ../../rules.mk - -PKG_NAME := bcm43xx-standalone -PKG_VERSION := 060313 -PKG_RELEASE := 1 -PKG_MD%SUM := 773b26a164a54f0da544764969ca019b - -PKG_SOURCE_URL := ftp://bu3sch.de/bcm43xx-snapshots/standalone/bcm43xx/ -PKG_SOURCE := $(PKG_NAME)-$(PKG_VERSION).tar.bz2 -PKG_CAT := bzcat - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) - -FIRMWARE_BLOB := wl_apsta-3.130.20.0.o -FIRMWARE_BLOB_URL := http://downloads.openwrt.org/sources -FIRMWARE_BLOB_MD5SUM := e08665c5c5b66beb9c3b2dd54aa80cb3 - -include $(TOPDIR)/package/rules.mk - -$(eval $(call PKG_template,KMOD_BCM43XX_DSCAPE,kmod-$(PKG_NAME),$(LINUX_VERSION)-$(BOARD)+0.$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH),kernel ($(LINUX_VERSION)-$(BOARD)-$(LINUX_RELEASE)))) - -$(PKG_BUILD_DIR)/.configured: - touch $@ - -$(PKG_BUILD_DIR)/fwcutter/.built: - mkdir -p $(PKG_BUILD_DIR)/fwcutter - $(CP) ./fwcutter/* $(PKG_BUILD_DIR)/fwcutter/ - $(SCRIPT_DIR)/download.pl "$(PKG_BUILD_DIR)/fwcutter" "$(FIRMWARE_BLOB)" "$(FIRMWARE_BLOB_MD5SUM)" $(FIRMWARE_BLOB_URL) - $(MAKE) -C $(PKG_BUILD_DIR)/fwcutter - $(PKG_BUILD_DIR)/fwcutter/fwcutter -w $(PKG_BUILD_DIR)/fwcutter $(PKG_BUILD_DIR)/fwcutter/$(FIRMWARE_BLOB) - touch $@ - -$(PKG_BUILD_DIR)/.built: $(PKG_BUILD_DIR)/fwcutter/.built - $(MAKE) -C "$(LINUX_DIR)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - PATH="$(TARGET_PATH)" \ - SUBDIRS="$(PKG_BUILD_DIR)" \ - LINUXINCLUDE="-I$(STAGING_DIR)/usr/include/ieee80211-dscape -I$(LINUX_DIR)/include -DBCM47XX=1" \ - modules - touch $@ - -$(IPKG_KMOD_BCM43XX_DSCAPE): - install -m0755 -d $(IDIR_KMOD_BCM43XX_DSCAPE)/lib/modules/$(LINUX_VERSION) - install -m0755 -d $(IDIR_KMOD_BCM43XX_DSCAPE)/etc/modules.d - ( \ - echo 80211; \ - echo rate_control; \ - echo bcm43xx; \ - ) >& $(IDIR_KMOD_BCM43XX_DSCAPE)/etc/modules.d/50-bcm43xx - $(CP) $(PKG_BUILD_DIR)/*.ko $(IDIR_KMOD_BCM43XX_DSCAPE)/lib/modules/$(LINUX_VERSION) - install -m0755 -d $(IDIR_KMOD_BCM43XX_DSCAPE)/lib/firmware - $(CP) $(PKG_BUILD_DIR)/fwcutter/*.fw $(IDIR_KMOD_BCM43XX_DSCAPE)/lib/firmware/ - $(IPKG_BUILD) $(IDIR_KMOD_BCM43XX_DSCAPE) $(PACKAGE_DIR) diff --git a/target/linux/package/bcm43xx-standalone/fwcutter/Makefile b/target/linux/package/bcm43xx-standalone/fwcutter/Makefile deleted file mode 100644 index 6402dca85f..0000000000 --- a/target/linux/package/bcm43xx-standalone/fwcutter/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -VERSION = 0.0.1 - -FIRMWARE_INSTALL_DIR ?= /lib/firmware - -CC = cc -PREFIX = /usr/local -CFLAGS = -std=c99 -O2 -fomit-frame-pointer -Wall -pedantic -D_BSD_SOURCE -LDFLAGS = - - -OBJECTS = fwcutter.o md5.o - -CFLAGS += -DFWCUTTER_VERSION_=$(VERSION) - -all: fwcutter - -fwcutter: $(OBJECTS) - $(CC) $(CFLAGS) -o fwcutter $(OBJECTS) $(LDFLAGS) - -install: all - -install -o 0 -g 0 -m 755 fwcutter $(PREFIX)/bin/ - -clean: - -rm -f *~ *.o *.orig *.rej *.fw fwcutter - -installfw: - -if ! [ -d $(FIRMWARE_INSTALL_DIR) ]; then mkdir $(FIRMWARE_INSTALL_DIR); fi - -install -o 0 -g 0 -m 600 bcm43xx_*.fw $(FIRMWARE_INSTALL_DIR) - -# dependencies -fwcutter.o: md5.h fwcutter_list.h -md5.o: md5.h diff --git a/target/linux/package/bcm43xx-standalone/fwcutter/fwcutter.c b/target/linux/package/bcm43xx-standalone/fwcutter/fwcutter.c deleted file mode 100644 index ea98880dff..0000000000 --- a/target/linux/package/bcm43xx-standalone/fwcutter/fwcutter.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * firmware cutter for broadcom 43xx wireless driver files - * - * Copyright (c) 2005 Martin Langer , - * 2005 Michael Buesch - * 2005 Alex Beregszaszi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - - -#include -#include -#include -#include - -typedef unsigned char byte; - -#define DRIVER_UNSUPPORTED 0x01 /* no support for this driver file */ -#define BYTE_ORDER_BIG_ENDIAN 0x02 /* ppc driver files */ -#define BYTE_ORDER_LITTLE_ENDIAN 0x04 /* x86, mips driver files */ - -#define MISSING_INITVAL_08 0x10 /* initval 8 is missing */ -#define MISSING_INITVAL_80211_A 0x20 /* initvals 3,7,9,10 (802.11a cards) are empty */ - -#define FIRMWARE_UCODE_OFFSET 100 -#define FIRMWARE_UNDEFINED 0 -#define FIRMWARE_PCM_4 4 -#define FIRMWARE_PCM_5 5 -#define FIRMWARE_UCODE_2 (FIRMWARE_UCODE_OFFSET + 2) -#define FIRMWARE_UCODE_4 (FIRMWARE_UCODE_OFFSET + 4) -#define FIRMWARE_UCODE_5 (FIRMWARE_UCODE_OFFSET + 5) -#define FIRMWARE_UCODE_11 (FIRMWARE_UCODE_OFFSET + 11) - - -#define fwcutter_stringify_1(x) #x -#define fwcutter_stringify(x) fwcutter_stringify_1(x) -#define FWCUTTER_VERSION fwcutter_stringify(FWCUTTER_VERSION_) - -#include "md5.h" -#include "fwcutter_list.h" - - -struct cmdline_args { - const char *infile; - const char *postfix; - const char *target_dir; - int identify_only; -}; - -static struct cmdline_args cmdargs; -int big_endian_cpu; - - -static void write_little_endian(FILE *f, byte *buffer, int len) -{ - byte swapbuf[4]; - - while (len > 0) { - swapbuf[0] = buffer[3]; swapbuf[1] = buffer[2]; - swapbuf[2] = buffer[1]; swapbuf[3] = buffer[0]; - fwrite(swapbuf, 4, 1, f); - buffer = buffer + 4; - len = len - 4; - } -} - -static void write_big_endian(FILE *f, byte *buffer, int len) -{ - while (len > 0) { - fwrite(buffer, 4, 1, f); - buffer = buffer + 4; - len = len - 4; - } -} - -static void write_fw(const char *outfilename, uint8_t flags, byte *data, int len) -{ - FILE* fw; - char outfile[2048]; - - snprintf(outfile, sizeof(outfile), - "%s/%s", cmdargs.target_dir, outfilename); - - fw = fopen(outfile, "w"); - if (!fw) { - perror(outfile); - exit(1); - } - - if (flags & BYTE_ORDER_LITTLE_ENDIAN) - write_little_endian(fw, data, len); - else if (flags & BYTE_ORDER_BIG_ENDIAN) - write_big_endian(fw, data, len); - else - printf("unknown byteorder...\n"); - - fflush(fw); - fclose(fw); -} - -static void write_iv(uint8_t flags, byte *data) -{ - FILE* fw; - char ivfilename[2048]; - int i; - - for (i = 1; i <= 10; i++) { - - if ((flags & MISSING_INITVAL_08) && (i==8)) { - printf("*****: Sorry, initval08 is not available in driver file \"%s\".\n", cmdargs.infile); - printf("*****: Extracting firmware from an old driver is bad. Choose a more recent one.\n"); - printf("*****: Luckily bcm43xx driver doesn't include initval08 uploads at the moment.\n"); - printf("*****: But this can be added in the future...\n"); - i++; - } - - snprintf(ivfilename, sizeof(ivfilename), - "%s/bcm43xx_initval%02d%s.fw", - cmdargs.target_dir, i, cmdargs.postfix); - fw = fopen(ivfilename, "w"); - - if (!fw) { - perror(ivfilename); - exit(1); - } - - printf("extracting bcm43xx_initval%02d%s.fw ...\n", i, cmdargs.postfix); - - while (1) { - - if ((data[0]==0xff) && (data[1]==0xff) && (data[2]==0x00) && (data[3]==0x00)) { - data = data + 8; - break; - } - - if (flags & BYTE_ORDER_LITTLE_ENDIAN) - fprintf(fw, "%c%c%c%c%c%c%c%c", - data[1], data[0], /* offset */ - data[3], data[2], /* size */ - data[7], data[6], data[5], data[4]); /* value */ - else if (flags & BYTE_ORDER_BIG_ENDIAN) - fprintf(fw, "%c%c%c%c%c%c%c%c", - data[0], data[1], /* offset */ - data[2], data[3], /* size */ - data[4], data[5], data[6], data[7]); /* value */ - else { - printf("unknown byteorder...\n"); - exit(1); - } - - data = data + 8; - } - fflush(fw); - fclose(fw); - } -} - -static byte* read_file(const char* filename) -{ - FILE* file; - long len; - byte* data; - - file = fopen(filename, "rb"); - if (!file) { - perror(filename); - exit(1); - } - if (fseek(file, 0, SEEK_END)) { - perror("cannot seek"); - exit(1); - } - len = ftell(file); - fseek(file, 0, SEEK_SET); - data = malloc(len); - if (!data) { - fputs("out of memory\n", stderr); - exit(1); - } - if (fread(data, 1, len, file) != len) { - perror("cannot read"); - exit(1); - } - fclose(file); - return data; -} - -static void extract_fw(uint8_t fwtype, uint8_t flags, uint32_t pos, uint32_t length) -{ - byte* filedata; - char outfile[1024]; - - switch (fwtype) { - case FIRMWARE_UCODE_2: - case FIRMWARE_UCODE_4: - case FIRMWARE_UCODE_5: - case FIRMWARE_UCODE_11: - snprintf(outfile, sizeof(outfile), "bcm43xx_microcode%i%s.fw", - fwtype - FIRMWARE_UCODE_OFFSET, cmdargs.postfix); - break; - case FIRMWARE_PCM_4: - case FIRMWARE_PCM_5: - snprintf(outfile, sizeof(outfile), "bcm43xx_pcm%i%s.fw", - fwtype, cmdargs.postfix); - break; - default: - snprintf(outfile, sizeof(outfile), "bcm43xx_unknown.fw"); - } - - if (length > 0) { - printf("extracting %s ...\n", outfile); - filedata = read_file(cmdargs.infile); - write_fw(outfile, flags, filedata + pos, length); - free(filedata); - } else { - printf("*****: Sorry, it's not posible to extract \"%s\".\n", outfile); - printf("*****: Extracting firmware from an old driver is bad. Choose a more recent one.\n"); - - switch (fwtype) { - case FIRMWARE_UCODE_2: - printf("*****: bcm43xx driver will not work with with core revision 2.\n"); - break; - case FIRMWARE_UCODE_4: - printf("*****: bcm43xx driver will not work with with core revision 4.\n"); - break; - case FIRMWARE_UCODE_5: - printf("*****: bcm43xx driver will not work with with core revision 5 or higher.\n"); - break; - case FIRMWARE_UCODE_11: - printf("*****: Luckily bcm43xx driver doesn't include microcode11 uploads at the moment.\n"); - printf("*****: But this can be added in the future...\n"); - break; - case FIRMWARE_PCM_4: - printf("*****: bcm43xx driver will not work with with core revision 4 or smaller.\n"); - break; - case FIRMWARE_PCM_5: - printf("*****: bcm43xx driver will not work with with core revision 5 or higher.\n"); - break; - } - } -} - -static void extract_iv(uint8_t flags, uint32_t pos) -{ - byte* filedata; - - if (pos > 0) { - filedata = read_file(cmdargs.infile); - write_iv(flags, filedata + pos); - free(filedata); - } -} - -static void print_banner(void) -{ - printf("fwcutter " FWCUTTER_VERSION "\n"); -} - -static void print_file(const struct file *file) -{ - printf("%s\t", file->name); - if (strlen(file->name) < 8) - printf("\t"); - - printf("%s\t", file->version); - if (strlen(file->version) < 8) - printf("\t"); - if (strlen(file->version) < 16) - printf("\t"); - - if (!(file->flags & DRIVER_UNSUPPORTED)) { - if (file->flags & MISSING_INITVAL_80211_A) - printf("b/g "); - else - printf("a/b/g"); - } - - printf(" %s", file->md5); - printf("\n"); -} - -static void print_supported_files(void) -{ - int i; - - print_banner(); - printf("\nExtracting firmware is possible from these binary driver files:\n\n"); - printf("\t\t <802.11>\n\n"); - for (i = 0; i < FILES; i++) { - if (files[i].flags & DRIVER_UNSUPPORTED) - continue; - print_file(&files[i]); - } - printf("\n\nExtracting firmware is IMPOSSIBLE from these binary driver files:\n\n"); - printf("\t\t \n\n"); - for (i = 0; i < FILES; i++) { - if (!(files[i].flags & DRIVER_UNSUPPORTED)) - continue; - print_file(&files[i]); - } -} - -static const struct file * find_file(FILE *fd) -{ - unsigned char buffer[16384], signature[16]; - struct MD5Context md5c; - char md5sig[33]; - int i; - - MD5Init(&md5c); - while ((i = (int) fread(buffer, 1, sizeof(buffer), fd)) > 0) - MD5Update(&md5c, buffer, (unsigned) i); - MD5Final(signature, &md5c); - - snprintf(md5sig, sizeof(md5sig), - "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", - signature[0], signature[1], signature[2], signature[3], - signature[4], signature[5], signature[6], signature[7], - signature[8], signature[9], signature[10], signature[11], - signature[12], signature[13], signature[14], signature[15]); - - for (i = 0; i < FILES; ++i) { - if (strcasecmp(md5sig, files[i].md5) == 0) { - if (files[i].flags & DRIVER_UNSUPPORTED) { - printf("Extracting firmware from this file is IMPOSSIBLE. (too old)\n"); - return 0; - } - printf("fwcutter can cut the firmware out of %s\n", cmdargs.infile); - printf(" filename : %s\n", files[i].name); - printf(" version : %s\n", files[i].version); - printf(" MD5 : %s\n\n", files[i].md5); - if (files[i].flags & MISSING_INITVAL_80211_A) { - printf("WARNING! This firmware doesn't include support for 802.11a cards.\n"); - printf("WARNING! Use this firmware only for 802.11b/g cards.\n\n"); - } - return &(files[i]); - } - } - printf("Sorry, the input file is either wrong or not supported by fwcutter.\n"); - printf("I can't find the MD5sum %s :(\n", md5sig); - - return 0; -} - -static void get_endianess(void) -{ - const unsigned char x[] = { 0xde, 0xad, 0xbe, 0xef, }; - const uint32_t *p = (uint32_t *)x; - - if (*p == 0xdeadbeef) { - big_endian_cpu = 1; - } else if (*p == 0xefbeadde) { - big_endian_cpu = 0; - } else { - printf("Confused: NUXI endian machine??\n"); - exit(-1); - } -} - -static void print_usage(int argc, char *argv[]) -{ - print_banner(); - printf("\nUsage: %s [OPTION] [driver.sys]\n", argv[0]); - printf(" -l|--list List supported driver versions\n"); - printf(" -i|--identify Only identify the driver file (don't extract)\n"); - printf(" -w|--target-dir DIR Extract and write firmware to DIR\n"); - printf(" -p|--postfix \".FOO\" Postfix for firmware filenames (.FOO.fw)\n"); - printf(" -v|--version Print fwcutter version\n"); - printf(" -h|--help Print this help\n"); - printf("\nExample: %s bcmwl5.sys\n" - " to extract the firmware blobs from bcmwl5.sys\n", argv[0]); -} - -#define ARG_MATCH 0 -#define ARG_NOMATCH 1 -#define ARG_ERROR -1 - -static int do_cmp_arg(char **argv, int *pos, - const char *template, - int allow_merged, - char **param) -{ - char *arg; - char *next_arg; - size_t arg_len, template_len; - - arg = argv[*pos]; - next_arg = argv[*pos + 1]; - arg_len = strlen(arg); - template_len = strlen(template); - - if (param) { - /* Maybe we have a merged parameter here. - * A merged parameter is "-pfoobar" for example. - */ - if (allow_merged && arg_len > template_len) { - if (memcmp(arg, template, template_len) == 0) { - *param = arg + template_len; - return ARG_MATCH; - } - return ARG_NOMATCH; - } else if (arg_len != template_len) - return ARG_NOMATCH; - *param = next_arg; - } - if (strcmp(arg, template) == 0) { - if (param) { - /* Skip the parameter on the next iteration. */ - (*pos)++; - if (*param == 0) { - printf("%s needs a parameter\n", arg); - return ARG_ERROR; - } - } - return ARG_MATCH; - } - - return ARG_NOMATCH; -} - -/* Simple and lean command line argument parsing. */ -static int cmp_arg(char **argv, int *pos, - const char *long_template, - const char *short_template, - char **param) -{ - int err; - - if (long_template) { - err = do_cmp_arg(argv, pos, long_template, 0, param); - if (err == ARG_MATCH || err == ARG_ERROR) - return err; - } - err = ARG_NOMATCH; - if (short_template) - err = do_cmp_arg(argv, pos, short_template, 1, param); - return err; -} - -static int parse_args(int argc, char *argv[]) -{ - int i, res; - char *param; - - if (argc < 2) - goto out_usage; - for (i = 1; i < argc; i++) { - res = cmp_arg(argv, &i, "--list", "-l", 0); - if (res == ARG_MATCH) { - print_supported_files(); - return 1; - } else if (res == ARG_ERROR) - goto out; - - res = cmp_arg(argv, &i, "--version", "-v", 0); - if (res == ARG_MATCH) { - print_banner(); - return 1; - } else if (res == ARG_ERROR) - goto out; - - res = cmp_arg(argv, &i, "--help", "-h", 0); - if (res == ARG_MATCH) - goto out_usage; - else if (res == ARG_ERROR) - goto out; - - res = cmp_arg(argv, &i, "--identify", "-i", 0); - if (res == ARG_MATCH) { - cmdargs.identify_only = 1; - continue; - } else if (res == ARG_ERROR) - goto out; - - res = cmp_arg(argv, &i, "--target-dir", "-w", ¶m); - if (res == ARG_MATCH) { - cmdargs.target_dir = param; - continue; - } else if (res == ARG_ERROR) - goto out; - - res = cmp_arg(argv, &i, "--postfix", "-p", ¶m); - if (res == ARG_MATCH) { - cmdargs.postfix = param; - continue; - } else if (res == ARG_ERROR) - goto out; - - cmdargs.infile = argv[i]; - break; - } - - if (!cmdargs.infile) - goto out_usage; - return 0; - -out_usage: - print_usage(argc, argv); -out: - return -1; -} - -int main(int argc, char *argv[]) -{ - FILE *fd; - const struct file *file; - int err; - - get_endianess(); - - cmdargs.target_dir = "."; - cmdargs.postfix = ""; - err = parse_args(argc, argv); - if (err == 1) - return 0; - else if (err != 0) - return err; - - fd = fopen(cmdargs.infile, "rb"); - if (!fd) { - fprintf(stderr, "Cannot open input file %s\n", cmdargs.infile); - return 2; - } - - err = -1; - file = find_file(fd); - if (!file) - goto out_close; - if (cmdargs.identify_only) { - err = 0; - goto out_close; - } - - extract_fw(FIRMWARE_UCODE_2, file->flags, file->uc2_pos, file->uc2_length); - extract_fw(FIRMWARE_UCODE_4, file->flags, file->uc4_pos, file->uc4_length); - extract_fw(FIRMWARE_UCODE_5, file->flags, file->uc5_pos, file->uc5_length); - extract_fw(FIRMWARE_UCODE_11, file->flags, file->uc11_pos, file->uc11_length); - extract_fw(FIRMWARE_PCM_4, file->flags, file->pcm4_pos, file->pcm4_length); - extract_fw(FIRMWARE_PCM_5, file->flags, file->pcm5_pos, file->pcm5_length); - extract_iv(file->flags, file->iv_pos); - - err = 0; -out_close: - fclose(fd); - - return err; -} diff --git a/target/linux/package/bcm43xx-standalone/fwcutter/fwcutter_list.h b/target/linux/package/bcm43xx-standalone/fwcutter/fwcutter_list.h deleted file mode 100644 index e855b6d6da..0000000000 --- a/target/linux/package/bcm43xx-standalone/fwcutter/fwcutter_list.h +++ /dev/null @@ -1,810 +0,0 @@ - -static const struct file { - const char *name; - const char *version; - const char *md5; - const uint8_t flags; - const uint32_t iv_pos; - const uint32_t uc2_pos; - const uint32_t uc2_length; - const uint32_t uc4_pos; - const uint32_t uc4_length; - const uint32_t uc5_pos; - const uint32_t uc5_length; - const uint32_t uc11_pos; - const uint32_t uc11_length; - const uint32_t pcm4_pos; - const uint32_t pcm4_length; - const uint32_t pcm5_pos; - const uint32_t pcm5_length; -} files[] = -{ - { - .name = "AppleAirPort2", - .version = "3.30.15.p3 (3.1.1b2)", - .md5 = "a8275cc50107a13b5be15d067b2245a0", - .flags = BYTE_ORDER_BIG_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x42550, - .uc2_pos = 0x45630, .uc2_length = 0x3d88, - .uc4_pos = 0x493bc, .uc4_length = 0x44a0, - .uc5_pos = 0x4d860, .uc5_length = 0x4ec0, - .pcm4_pos = 0x52724, .pcm4_length = 0x478, - .pcm5_pos = 0x52ba0, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.30.15.p3 (3.1.2b3)", - .md5 = "55134c1298abaa85f190331f016d4d36", - .flags = BYTE_ORDER_BIG_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x42c24, - .uc2_pos = 0x45d04, .uc2_length = 0x3d88, - .uc4_pos = 0x49a90, .uc4_length = 0x44a0, - .uc5_pos = 0x4df34, .uc5_length = 0x4ec0, - .pcm4_pos = 0x52df8, .pcm4_length = 0x478, - .pcm5_pos = 0x53274, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.30.15.p7 (3.2)", - .md5 = "e74e8d2df2e4eb97e28602f3b2dd4647", - .flags = BYTE_ORDER_BIG_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x40efc, - .uc2_pos = 0x43fdc, .uc2_length = 0x3d88, - .uc4_pos = 0x47d68, .uc4_length = 0x44a0, - .uc5_pos = 0x4c20c, .uc5_length = 0x4ec0, - .pcm4_pos = 0x510d0, .pcm4_length = 0x478, - .pcm5_pos = 0x5154c, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.30.15.p8 (3.3b1)", /* 01/19/2004 */ - .md5 = "87c74c55d2501d2e968f8c132e160b6e", - .flags = BYTE_ORDER_BIG_ENDIAN, - .iv_pos = 0x41c8c, - .uc2_pos = 0x43fe4, .uc2_length = 0x3d88, - .uc4_pos = 0x47d70, .uc4_length = 0x44b2, - .uc5_pos = 0x4c214, .uc5_length = 0x4ec0, - .pcm4_pos = 0x510d8, .pcm4_length = 0x478, - .pcm5_pos = 0x51554, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.50.37.p4 (3.4.2b1)", - .md5 = "1739c357ade1d04c9be47e8604afb1c2", - .flags = BYTE_ORDER_BIG_ENDIAN, - .iv_pos = 0x4f2b8, - .uc2_pos = 0x52da0, .uc2_length = 0x3d30, - .uc4_pos = 0x56ad4, .uc4_length = 0x45c8, - .uc5_pos = 0x5b0a0, .uc5_length = 0x5500, - .pcm4_pos = 0x605a4, .pcm4_length = 0x478, - .pcm5_pos = 0x60a20, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.50.37.p4 (3.4.3f1)", /* 09/29/2004 */ - .md5 = "c672b8c218c5dc4a55060bdfa9f58a69", - .flags = BYTE_ORDER_BIG_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x4f378, - .uc2_pos = 0x52e60, .uc2_length = 0x3d30, - .uc4_pos = 0x56b94, .uc4_length = 0x45c8, - .uc5_pos = 0x5b160, .uc5_length = 0x5500, - .pcm4_pos = 0x60664, .pcm4_length = 0x478, - .pcm5_pos = 0x60ae0, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.50.37.p4 (3.4.4f5)", - .md5 = "2c388e3e8ea9310a58cf76a3757e8ccc", - .flags = BYTE_ORDER_BIG_ENDIAN, - .iv_pos = 0x4f5f0, - .uc2_pos = 0x530d8, .uc2_length = 0x3d30, - .uc4_pos = 0x56e0c, .uc4_length = 0x45c8, - .uc5_pos = 0x5b3d8, .uc5_length = 0x5500, - .pcm4_pos = 0x608dc, .pcm4_length = 0x478, - .pcm5_pos = 0x60d58, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.50.37.p4 (3.4.4f5)", - .md5 = "3860545266b554d2955664db55452f5a", - .flags = BYTE_ORDER_BIG_ENDIAN, - .iv_pos = 0x4f5f0, - .uc2_pos = 0x530d8, .uc2_length = 0x3d30, - .uc4_pos = 0x56e0c, .uc4_length = 0x45c8, - .uc5_pos = 0x5b3d8, .uc5_length = 0x5500, - .pcm4_pos = 0x608dc, .pcm4_length = 0x478, - .pcm5_pos = 0x60d58, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.50.37.p6 (3.5f1)", - .md5 = "a62e35ee9956b286c46b145d35bd6e0c", - .flags = BYTE_ORDER_BIG_ENDIAN, - .iv_pos = 0x4f9b8, - .uc2_pos = 0x534a0, .uc2_length = 0x3d30, - .uc4_pos = 0x571d4, .uc4_length = 0x45c8, - .uc5_pos = 0x5b7a0, .uc5_length = 0x5500, - .pcm4_pos = 0x60ca4, .pcm4_length = 0x478, - .pcm5_pos = 0x61120, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.50.37.p6 (3.5f1)", - .md5 = "b6f3d2437c40277c197f0afcf12208e9", - .flags = BYTE_ORDER_BIG_ENDIAN, - .iv_pos = 0x4f9b8, - .uc2_pos = 0x534a0, .uc2_length = 0x3d30, - .uc4_pos = 0x571d4, .uc4_length = 0x45c8, - .uc5_pos = 0x5b7a0, .uc5_length = 0x5500, - .pcm4_pos = 0x60ca4, .pcm4_length = 0x478, - .pcm5_pos = 0x61120, .pcm5_length = 0x478, - }, - { - .name = "AppleAirPort2", - .version = "3.90.34.0.p11 (400.17)", /* 09/13/2005 (??) */ - .md5 = "ca0f34df2f0bfb8b5cfd83b5848d2bf5", - .flags = BYTE_ORDER_BIG_ENDIAN | - MISSING_INITVAL_80211_A, - .iv_pos = 0x4ff2c, /* A-PHY init vals empty */ - .uc2_pos = 0x5181c, .uc2_length = 0x3f48, - .uc4_pos = 0x55764, .uc4_length = 0x4df0, - .uc5_pos = 0x5a554, .uc5_length = 0x57e0, - .pcm4_pos = 0x5fd34, .pcm4_length = 0x520, - .pcm5_pos = 0x60254, .pcm5_length = 0x520, - }, - { - .name = "AppleAirPort2", - .version = "3.90.34.0.p11 (400.17)", - .md5 = "dc3a69aac95c68fe8edc760e39bbb2c9", - .flags = BYTE_ORDER_BIG_ENDIAN | - MISSING_INITVAL_80211_A, - .iv_pos = 0x50efc, /* A-PHY init vals empty */ - .uc2_pos = 0x527ec, .uc2_length = 0x3f48, - .uc4_pos = 0x56734, .uc4_length = 0x4df0, - .uc5_pos = 0x5b524, .uc5_length = 0x57e0, - .pcm4_pos = 0x60d04, .pcm4_length = 0x520, - .pcm5_pos = 0x61224, .pcm5_length = 0x520, - }, - { - .name = "AppleAirPort2", - .version = "3.90.34.0.p13 (401.2)", /* 07/10/2005 */ - .md5 = "6ecf38e5ab6997c7ec483c0d637f5c68", - .flags = BYTE_ORDER_BIG_ENDIAN | - MISSING_INITVAL_80211_A, - .iv_pos = 0x50fcc, /* A-PHY init vals empty */ - .uc2_pos = 0x528bc, .uc2_length = 0x3f48, - .uc4_pos = 0x56804, .uc4_length = 0x4df0, - .uc5_pos = 0x5b5f4, .uc5_length = 0x57e0, - .pcm4_pos = 0x60dd4, .pcm4_length = 0x520, - .pcm5_pos = 0x612f4, .pcm5_length = 0x520, - }, - { - .name = "AppleAirPort2", - .version = "3.90.34.0.p16 (404.2)", - .md5 = "7200d1aef5f413ebc811046d068b40dc", - .flags = BYTE_ORDER_BIG_ENDIAN | - MISSING_INITVAL_80211_A, - .iv_pos = 0x511ec, /* A-PHY init vals empty */ - .uc2_pos = 0x52adc, .uc2_length = 0x3f48, - .uc4_pos = 0x56a24, .uc4_length = 0x4df0, - .uc5_pos = 0x5b814, .uc5_length = 0x57f0, - .pcm4_pos = 0x61004, .pcm4_length = 0x520, - .pcm5_pos = 0x61524, .pcm5_length = 0x520, - }, - { - .name = "AppleAirPort2", - .version = "3.90.34.0.p16 (404.2)", - .md5 = "86cc708e8df3b035a1dbea41ac4eb7d2", - .flags = BYTE_ORDER_BIG_ENDIAN | - MISSING_INITVAL_80211_A, - .iv_pos = 0x5021c, /* A-PHY init vals empty */ - .uc2_pos = 0x51b0c, .uc2_length = 0x3f48, - .uc4_pos = 0x55a54, .uc4_length = 0x4df0, - .uc5_pos = 0x5a844, .uc5_length = 0x57f0, - .pcm4_pos = 0x60034, .pcm4_length = 0x520, - .pcm5_pos = 0x60554, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5.sys", - .version = "3.10.8.0", /* 10/04/2002 */ - .md5 = "288923b401e87ef76b7ae2652601ee47", - .flags = DRIVER_UNSUPPORTED, /* file differs from later ones */ - }, - { - .name = "bcmwl5.sys", - .version = "3.10.53.6", /* 04/28/2003 */ - .md5 = "b43c593fd7c2a47cdc40580fe341f674", - .flags = DRIVER_UNSUPPORTED, /* file differs from later ones */ - }, - { - .name = "bcmwl5.sys", - .version = "3.20.23.0", /* 06/13/2003 */ - .md5 = "1b1cf5e962c15abca83d1ef2b3906e2f", /* pcm5 not available, driver is too old */ - .flags = BYTE_ORDER_LITTLE_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x2a1d0, - .uc2_pos = 0x2d228, .uc2_length = 0x3da8, - .uc4_pos = 0x30fd8, .uc4_length = 0x4470, - .uc5_pos = 0x35450, .uc5_length = 0x4ba0, - .pcm4_pos = 0x39ff8, .pcm4_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.30.15.0", /* 07/17/2003 */ - .md5 = "ebf36d658d0da5b1ea667fa403919c26", - .flags = BYTE_ORDER_LITTLE_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x2c658, - .uc2_pos = 0x2f738, .uc2_length = 0x3d88, - .uc4_pos = 0x334c8, .uc4_length = 0x44a0, - .uc5_pos = 0x37970, .uc5_length = 0x4ec0, - .pcm4_pos = 0x3c838, .pcm4_length = 0x478, - .pcm5_pos = 0x3ccb8, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.40.20.0", /* 09/24/2003 */ - .md5 = "0c3fc803184f6f85e665dd012611225b", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x302f0, - .uc2_pos = 0x33d88, .uc2_length = 0x3db8, - .uc4_pos = 0x37b48, .uc4_length = 0x45d8, - .uc5_pos = 0x3c128, .uc5_length = 0x5050, - .pcm4_pos = 0x41180, .pcm4_length = 0x478, - .pcm5_pos = 0x41600, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.40.25.3", /* 10/28/2003 */ - .md5 = "5e58a3148b98c9f356cde6049435cb21", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x30970, - .uc2_pos = 0x34408, .uc2_length = 0x3db0, - .uc4_pos = 0x381c0, .uc4_length = 0x45d0, - .uc5_pos = 0x3c798, .uc5_length = 0x5050, - .pcm4_pos = 0x417f0, .pcm4_length = 0x478, - .pcm5_pos = 0x41c70, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.40.73.0", /* 06/25/2004 */ - .md5 = "52d67c5465c01913b03b7daca0cc4077", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x37398, - .uc2_pos = 0x3ae30, .uc2_length = 0x3ff0, - .uc4_pos = 0x3ee28, .uc4_length = 0x47f0, - .uc5_pos = 0x43620, .uc5_length = 0x5260, - .pcm4_pos = 0x48888, .pcm4_length = 0x478, - .pcm5_pos = 0x48d08, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.40.100.0", /* 02/07/2004 */ - .md5 = "431195b941dff794f23c2077fcbf8377", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x34d18, - .uc2_pos = 0x387b0, .uc2_length = 0x3ff0, - .uc4_pos = 0x3c7a8, .uc4_length = 0x47f0, - .uc5_pos = 0x40fa0, .uc5_length = 0x5260, - .pcm4_pos = 0x46208, .pcm4_length = 0x478, - .pcm5_pos = 0x46688, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.50.21.11", /* 02/19/2004 */ - .md5 = "ae96075a3aed5c40f1ead477ea94acd7", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x33370, - .uc2_pos = 0x36e58, .uc2_length = 0x3e00, - .uc4_pos = 0x3ac60, .uc4_length = 0x4628, - .uc5_pos = 0x3f290, .uc5_length = 0x5548, - .pcm4_pos = 0x447e0, .pcm4_length = 0x478, - .pcm5_pos = 0x44c60, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.60.7.0", /* 03/22/2004 */ - .md5 = "c5616736df4e83930780dca5795387ca", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3b988, - .uc2_pos = 0x3f580, .uc2_length = 0x3e08, - .uc4_pos = 0x43390, .uc4_length = 0x4e58, - .uc5_pos = 0x481f0, .uc5_length = 0x5608, - .pcm4_pos = 0x4d800, .pcm4_length = 0x478, - .pcm5_pos = 0x4dc80, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.60.7.5", /* 06/07/2004 */ - .md5 = "d2ae116c741c215ef3ef68603db9917f", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3b988, - .uc2_pos = 0x3f580, .uc2_length = 0x3e08, - .uc4_pos = 0x43390, .uc4_length = 0x4e58, - .uc5_pos = 0x481f0, .uc5_length = 0x5608, - .pcm4_pos = 0x4d800, .pcm4_length = 0x478, - .pcm5_pos = 0x4dc80, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.70.12.0", /* 06/02/2004 */ - .md5 = "d409b089370486521d5408baed9bffde", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x39480, - .uc2_pos = 0x3d0c8, .uc2_length = 0x3e80, - .uc4_pos = 0x40f50, .uc4_length = 0x4ed0, - .uc5_pos = 0x45e28, .uc5_length = 0x5680, - .pcm4_pos = 0x4b4b0, .pcm4_length = 0x478, - .pcm5_pos = 0x4b930, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.70.17.0", /* 06/25/2004 */ - .md5 = "d87b4e14e890091d8e64fb5c570cf192", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x39600, - .uc2_pos = 0x3d248, .uc2_length = 0x3e80, - .uc4_pos = 0x410d0, .uc4_length = 0x4ed0, - .uc5_pos = 0x45fa8, .uc5_length = 0x5680, - .pcm4_pos = 0x4b630, .pcm4_length = 0x478, - .pcm5_pos = 0x4bab0, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.70.22.0", /* 10/20/2004 */ - .md5 = "185a6dc6d655dc31c0b228cc94fb99ac", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x39a88, - .uc2_pos = 0x3d6d0, .uc2_length = 0x3e80, - .uc4_pos = 0x41558, .uc4_length = 0x4ed0, - .uc5_pos = 0x46430, .uc5_length = 0x5680, - .pcm4_pos = 0x4bab8, .pcm4_length = 0x478, - .pcm5_pos = 0x4bf38, .pcm5_length = 0x478, - }, - { - .name = "bcmwl5.sys", - .version = "3.90.41.1", /* 07/04/2005 */ - .md5 = "0a87541dd24c6f046a4bf8f671f74de2", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3bec8, - .uc2_pos = 0x3fb38, .uc2_length = 0x3f48, - .uc4_pos = 0x43a88, .uc4_length = 0x4df0, - .uc5_pos = 0x48880, .uc5_length = 0x57e0, - .pcm4_pos = 0x4e068, .pcm4_length = 0x520, - .pcm5_pos = 0x4e590, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5.sys", - .version = "3.100.35.0", /* 11/27/2004 */ - .md5 = "c3ab2d6954c7b5103770832a3a6a591b", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3de80, - .uc2_pos = 0x41af0, .uc2_length = 0x3f58, - .uc4_pos = 0x45a50, .uc4_length = 0x4df8, - .uc5_pos = 0x4a850, .uc5_length = 0x57f8, - .pcm4_pos = 0x50050, .pcm4_length = 0x520, - .pcm5_pos = 0x50578, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5.sys", - .version = "3.100.35.1", /* 02/10/2005 */ - .md5 = "da7ca369a1a3593ceac85dec2d267a08", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3df00, - .uc2_pos = 0x41b70, .uc2_length = 0x3f58, - .uc4_pos = 0x45ad0, .uc4_length = 0x4df8, - .uc5_pos = 0x4a8d0, .uc5_length = 0x57f8, - .pcm4_pos = 0x500d0, .pcm4_length = 0x520, - .pcm5_pos = 0x505f8, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5.sys", - .version = "3.100.46.0", /* 12/22/2004 */ - .md5 = "38ca1443660d0f5f06887c6a2e692aeb", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3de80, - .uc2_pos = 0x41af0, .uc2_length = 0x3f58, - .uc4_pos = 0x45a50, .uc4_length = 0x4df8, - .uc5_pos = 0x4a850, .uc5_length = 0x57f8, - .pcm4_pos = 0x50050, .pcm4_length = 0x520, - .pcm5_pos = 0x50578, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5.sys", - .version = "3.100.64.0", /* 02/11/2005 */ - .md5 = "e7debb46b9ef1f28932e533be4a3d1a9", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3e980, - .uc2_pos = 0x425f0, .uc2_length = 0x3f58, - .uc4_pos = 0x46550, .uc4_length = 0x4e00, - .uc5_pos = 0x4b358, .uc5_length = 0x5800, - .pcm4_pos = 0x50b60, .pcm4_length = 0x520, - .pcm5_pos = 0x51088, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5.sys", - .version = "3.100.64.50", /* 04/05/2005 */ - .md5 = "4b3e367b829b9b2c0c088909a617e04e", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3e900, - .uc2_pos = 0x42570, .uc2_length = 0x3f58, - .uc4_pos = 0x464d0, .uc4_length = 0x4e00, - .uc5_pos = 0x4b2d8, .uc5_length = 0x5800, - .pcm4_pos = 0x50ae0, .pcm4_length = 0x520, - .pcm5_pos = 0x51008, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5.sys", - .version = "3.100.65.1", /* 04/21/2005 */ - .md5 = "d5f1ab1aab8b81bca6f19da9554a267a", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3e980, - .uc2_pos = 0x425f0, .uc2_length = 0x3f58, - .uc4_pos = 0x46550, .uc4_length = 0x4e00, - .uc5_pos = 0x4b358, .uc5_length = 0x5800, - .pcm4_pos = 0x50b60, .pcm4_length = 0x520, - .pcm5_pos = 0x51088, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5.sys", - .version = "3.120.27.0", /* 05/19/2005 */ - .md5 = "8d49f11238815a320880fee9f98b2c92", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3f700, - .uc2_pos = 0x43370, .uc2_length = 0x3f68, - .uc4_pos = 0x472e0, .uc4_length = 0x4e10, - .uc5_pos = 0x4c0f8, .uc5_length = 0x5800, - .pcm4_pos = 0x51900, .pcm4_length = 0x520, - .pcm5_pos = 0x51e28, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5.sys", - .version = "3.140.16.0", /* 07/21/2005 */ - .md5 = "fa4a4a50b4b2647afedc676cc68c69cc", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3f700, - .uc2_pos = 0x43370, .uc2_length = 0x3f68, - .uc4_pos = 0x472e0, .uc4_length = 0x4e10, - .uc5_pos = 0x4c0f8, .uc5_length = 0x5800, - .pcm4_pos = 0x51900, .pcm4_length = 0x520, - .pcm5_pos = 0x51e28, .pcm5_length = 0x520, - }, - { - .name = "bcmwl564.sys", - .version = "3.70.17.5", /* 09/21/2004 */ - .md5 = "f5590c8784b91dfd9ee092d3040b6e40", /* for 64bit machines */ - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x566f0, - .uc2_pos = 0x5a360, .uc2_length = 0x3e80, - .uc4_pos = 0x5e1f0, .uc4_length = 0x4ed0, - .uc5_pos = 0x630d0, .uc5_length = 0x5680, - .pcm4_pos = 0x68760, .pcm4_length = 0x478, - .pcm5_pos = 0x68be0, .pcm5_length = 0x478, - }, - { - .name = "bcmwl564.sys", - .version = "3.100.64.10", /* 05/12/2005 */ - .md5 = "b8d76da338ecf2c650f5f7ca226ccf89", /* for 64bit machines */ - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x50bf0, - .uc2_pos = 0x54860, .uc2_length = 0x3f58, - .uc4_pos = 0x587c0, .uc4_length = 0x4e00, - .uc5_pos = 0x5d5d0, .uc5_length = 0x5800, - .pcm4_pos = 0x62de0, .pcm4_length = 0x520, - .pcm5_pos = 0x63310, .pcm5_length = 0x520, - }, - { - .name = "bcmwl5a.sys", - .version = "3.90.16.0", /* 12/06/2004 */ - .md5 = "e6d927deea6c75bddf84080e6c3837b7", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3b4c8, - .uc2_pos = 0x3f138, .uc2_length = 0x3f48, - .uc4_pos = 0x43088, .uc4_length = 0x4de8, - .uc5_pos = 0x47e78, .uc5_length = 0x57d8, - .pcm4_pos = 0x4d658, .pcm4_length = 0x520, - .pcm5_pos = 0x4db80, .pcm5_length = 0x520, - }, - { - .name = "d11ucode.o", - .version = "3.31.16.0 ?", /*FIXME: version correct? */ - .md5 = "31e6cac8a8129bf8f91291293e017329", - .flags = BYTE_ORDER_LITTLE_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x40, - .uc2_pos = 0x3120, .uc2_length = 0x3d88, - .uc4_pos = 0x6eac, .uc4_length = 0x44a0, - .uc5_pos = 0xb350, .uc5_length = 0x4ec0, - .pcm4_pos = 0x10214, .pcm4_length = 0x478, - .pcm5_pos = 0x10690, .pcm5_length = 0x478, - }, - { - .name = "d11ucode.o", - .version = "3.60.7.0 ? (1.3.2)", /* no version number found */ - .md5 = "7774e5dda1daa2b3f83d279552ca1cc4", /* but same fw files are also */ - .flags = BYTE_ORDER_LITTLE_ENDIAN, /* in bcmwl5.sys 3.60.7.0 */ - .iv_pos = 0x40, - .uc2_pos = 0x3c38, .uc2_length = 0x3e08, - .uc4_pos = 0x7a44, .uc4_length = 0x4e58, - .uc5_pos = 0xc8a0, .uc5_length = 0x5608, - .pcm4_pos = 0x11eac, .pcm4_length = 0x478, - .pcm5_pos = 0x12328, .pcm5_length = 0x478, - }, - { - .name = "d11ucode.o", - .version = "3.90.7.0 ? (3.90.RC7)", /* 10/14/2004 */ - .md5 = "b2580361620881b06fa810422ec8b7ce", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x60, - .uc2_pos = 0x3cd0, .uc2_length = 0x3ec0, - .uc4_pos = 0x7b94, .uc4_length = 0x4d60, - .uc5_pos = 0xc8f8, .uc5_length = 0x5750, - .pcm4_pos = 0x1204c, .pcm4_length = 0x520, - .pcm5_pos = 0x12570, .pcm5_length = 0x520, - }, - { - .name = "d11ucode.o", - .version = "3.90.37.0", - .md5 = "2543935259739a8a879ccb8386647ac7", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x60, - .uc2_pos = 0x3cd0, .uc2_length = 0x3f48, - .uc4_pos = 0x7c1c, .uc4_length = 0x4df0, - .uc5_pos = 0xca10, .uc5_length = 0x57e0, - .pcm4_pos = 0x121f4, .pcm4_length = 0x520, - .pcm5_pos = 0x12718, .pcm5_length = 0x520, - }, - { - .name = "wl.o", - .version = "3.31.15.0", /* 07/28/2003 */ - .md5 = "a85af65b5ae1d64ee11eab714faab843", - .flags = BYTE_ORDER_LITTLE_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x32270, - .uc2_pos = 0x35350, .uc2_length = 0x3d88, - .uc4_pos = 0x390dc, .uc4_length = 0x44a0, - .uc5_pos = 0x3d580, .uc5_length = 0x4ec0, - .pcm4_pos = 0x42444, .pcm4_length = 0x478, - .pcm5_pos = 0x428c0, .pcm5_length = 0x478, - }, - { - .name = "wl.o", - .version = "3.31.15.0", /* 07/28/2003 */ - .md5 = "98dd50a95b02c8bcb3725c770df81dfc", - .flags = BYTE_ORDER_LITTLE_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x32270, - .uc2_pos = 0x35350, .uc2_length = 0x3d88, - .uc4_pos = 0x390dc, .uc4_length = 0x44a0, - .uc5_pos = 0x3d580, .uc5_length = 0x4ec0, - .pcm4_pos = 0x42444, .pcm4_length = 0x478, - .pcm5_pos = 0x428c0, .pcm5_length = 0x478, - }, - { - .name = "wl.o", - .version = "3.50.21.0", /* 05/11/2003 */ - .md5 = "f71be0e1d14f68c98d916465a300d835", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x38990, - .uc2_pos = 0x3c428, .uc2_length = 0x3db8, - .uc4_pos = 0x401e4, .uc4_length = 0x45d8, - .uc5_pos = 0x447c0, .uc5_length = 0x5050, - .pcm4_pos = 0x49814, .pcm4_length = 0x478, - .pcm5_pos = 0x49c90, .pcm5_length = 0x478, - }, - { - .name = "wl.o", - .version = "3.50.21.10", /* 01/21/2004 */ - .md5 = "191029d5e7097ed7db92cbd6e6131f85", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3a5d0, - .uc2_pos = 0x3e0b8, .uc2_length = 0x3e00, - .uc4_pos = 0x41ebc, .uc4_length = 0x4628, - .uc5_pos = 0x464e8, .uc5_length = 0x5548, - .pcm4_pos = 0x4ba34, .pcm4_length = 0x478, - .pcm5_pos = 0x4beb0, .pcm5_length = 0x478, - }, - { - .name = "wl.o", - .version = "3.60.7.0 ? (1.3.2.0)", /* 02/04/2004 */ - .md5 = "7009220d84c445797443aa0221b7d8a4", /* no bcm version found */ - .flags = BYTE_ORDER_LITTLE_ENDIAN, /* but same fw files are also */ - .iv_pos = 0x545e0, /* in bcmwl5.sys 3.60.7.0, */ - .uc2_pos = 0x581d8, .uc2_length = 0x3e08, - .uc4_pos = 0x5bfe4, .uc4_length = 0x4e58, - .uc5_pos = 0x60e40, .uc5_length = 0x5608, - .pcm4_pos = 0x6644c, .pcm4_length = 0x478, - .pcm5_pos = 0x668c8, .pcm5_length = 0x478, - }, - { - .name = "wl.o", - .version = "3.60.13.0", /* 05/05/2004 */ - .md5 = "275dd4958eb94058d4650f58d534c635", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3b740, - .uc2_pos = 0x3f388, .uc2_length = 0x3e30, - .uc4_pos = 0x431bc, .uc4_length = 0x4e80, - .uc5_pos = 0x48040, .uc5_length = 0x5630, - .pcm4_pos = 0x4d674, .pcm4_length = 0x478, - .pcm5_pos = 0x4daf0, .pcm5_length = 0x478, - }, - { - .name = "wl.o", - .version = "3.60.13.0", /* 08/02/2004 */ - .md5 = "4f20653a0b7c0bb3bd1ee0dd79f77785", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3b730, - .uc2_pos = 0x3f378, .uc2_length = 0x3e30, - .uc4_pos = 0x431ac, .uc4_length = 0x4e80, - .uc5_pos = 0x48030, .uc5_length = 0x5630, - .pcm4_pos = 0x4d664, .pcm4_length = 0x478, - .pcm5_pos = 0x4dae0, .pcm5_length = 0x478, - }, - { - .name = "wl.o", - .version = "3.90.7.0", /* 14/10/2004 */ - .md5 = "f15b59ad4d6f6ad2c7f45193d033aff8", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x4d890, - .uc2_pos = 0x51500, .uc2_length = 0x3ec0, - .uc4_pos = 0x553c4, .uc4_length = 0x4d60, - .uc5_pos = 0x5a128, .uc5_length = 0x5750, - .pcm4_pos = 0x5f87c, .pcm4_length = 0x520, - .pcm5_pos = 0x5fda0, .pcm5_length = 0x520, - }, - { - .name = "wl.o", - .version = "3.90.37.0", /* 15/02/2005 */ - .md5 = "984c42947552652d5ab61b78e7d12227", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x4cf50, - .uc2_pos = 0x50bc0, .uc2_length = 0x3f48, - .uc4_pos = 0x54b0c, .uc4_length = 0x4df0, - .uc5_pos = 0x59900, .uc5_length = 0x57e0, - .pcm4_pos = 0x5f0e4, .pcm4_length = 0x520, - .pcm5_pos = 0x5f608, .pcm5_length = 0x520, - }, - { - .name = "wl_ap.o", - .version = "3.31.16.0", /* 08/06/2003 */ - .md5 = "463633e7bf0efc6c0f8eac2514a71024", - .flags = BYTE_ORDER_LITTLE_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x32270, - .uc2_pos = 0x35350, .uc2_length = 0x3d88, - .uc4_pos = 0x390dc, .uc4_length = 0x44a0, - .uc5_pos = 0x3d580, .uc5_length = 0x4ec0, - .pcm4_pos = 0x42444, .pcm4_length = 0x478, - .pcm5_pos = 0x428c0, .pcm5_length = 0x478, - }, - { - .name = "wl_ap.o", - .version = "3.90.37.0", /* 15/02/2005 */ - .md5 = "0538296d46a854d2facc9a0db2088180", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3eac0, - .uc2_pos = 0x42730, .uc2_length = 0x3f48, - .uc4_pos = 0x4667c, .uc4_length = 0x4df0, - .uc5_pos = 0x4b470, .uc5_length = 0x57e0, - .pcm4_pos = 0x50c54, .pcm4_length = 0x520, - .pcm5_pos = 0x51178, .pcm5_length = 0x520, - }, - { - .name = "wl_ap.o", - .version = "3.90.37.0", /* 15/02/2005 */ - .md5 = "6c9073531a528dd455b716b5e821e696", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x3eac0, - .uc2_pos = 0x42730, .uc2_length = 0x3f48, - .uc4_pos = 0x4667c, .uc4_length = 0x4df0, - .uc5_pos = 0x4b470, .uc5_length = 0x57e0, - .pcm4_pos = 0x50c54, .pcm4_length = 0x520, - .pcm5_pos = 0x51178, .pcm5_length = 0x520, - }, - { - .name = "wl_apsta.o", - .version = "3.31.16.0", /* 06/08/2003 */ - .md5 = "22b90e4cbeee45ad7f78ff536c65712a", - .flags = BYTE_ORDER_LITTLE_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x38020, - .uc2_pos = 0x3b100, .uc2_length = 0x3d88, - .uc4_pos = 0x3ee8c, .uc4_length = 0x44a0, - .uc5_pos = 0x43330, .uc5_length = 0x4ec0, - .pcm4_pos = 0x481f4, .pcm4_length = 0x478, - .pcm5_pos = 0x48670, .pcm5_length = 0x478, - }, - { - .name = "wl_apsta.o", - .version = "3.31.16.0", /* 06/08/2003 */ - .md5 = "dfce35a8b5cb6e53e1ab75342c7e7194", - .flags = BYTE_ORDER_LITTLE_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x38020, - .uc2_pos = 0x3b100, .uc2_length = 0x3d88, - .uc4_pos = 0x3ee8c, .uc4_length = 0x44a0, - .uc5_pos = 0x43330, .uc5_length = 0x4ec0, - .pcm4_pos = 0x481f4, .pcm4_length = 0x478, - .pcm5_pos = 0x48670, .pcm5_length = 0x478, - }, - { - .name = "wl_apsta.o", - .version = "3.90.37.0", /* 15/02/2005 */ - .md5 = "2922e6c48917eacd6c8c094347d2ec4b", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x4ebc0, - .uc2_pos = 0x52830, .uc2_length = 0x3f48, - .uc4_pos = 0x5677c, .uc4_length = 0x4df0, - .uc5_pos = 0x5b570, .uc5_length = 0x57e0, - .pcm4_pos = 0x60d54, .pcm4_length = 0x520, - .pcm5_pos = 0x61278, .pcm5_length = 0x520, - }, - { - .name = "wl_apsta.o", - .version = "3.90.37.0", /* 15/02/2005 */ - .md5 = "f9fa565a766e8befeb495a8a8c0c134b", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x4ebc0, - .uc2_pos = 0x52830, .uc2_length = 0x3f48, - .uc4_pos = 0x5677c, .uc4_length = 0x4df0, - .uc5_pos = 0x5b570, .uc5_length = 0x57e0, - .pcm4_pos = 0x60d54, .pcm4_length = 0x520, - .pcm5_pos = 0x61278, .pcm5_length = 0x520, - }, - { - .name = "wl_apsta.o", - .version = "3.130.20.0", /* 19/05/2005 */ - .md5 = "e08665c5c5b66beb9c3b2dd54aa80cb3", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x56020, - .uc2_pos = 0x59ca0, .uc2_length = 0x3fe0, - .uc4_pos = 0x5dc84, .uc4_length = 0x4e78, - .uc5_pos = 0x62b00, .uc5_length = 0x5700, - .uc11_pos = 0x68204, .uc11_length = 0x54a8, - .pcm4_pos = 0x6d6b0, .pcm4_length = 0x520, - .pcm5_pos = 0x6dbd4, .pcm5_length = 0x520, - }, - { - .name = "wl_sta.o", - .version = "3.31.16.0", /* 08/06/2003 */ - .md5 = "c3e663cb78b2fc299088de69fc11a9a9", - .flags = BYTE_ORDER_LITTLE_ENDIAN | - MISSING_INITVAL_08, - .iv_pos = 0x317b0, - .uc2_pos = 0x34890, .uc2_length = 0x3d88, - .uc4_pos = 0x3861c, .uc4_length = 0x44a0, - .uc5_pos = 0x3cac0, .uc5_length = 0x4ec0, - .pcm4_pos = 0x41984, .pcm4_length = 0x478, - .pcm5_pos = 0x41e00, .pcm5_length = 0x478, - }, - { - .name = "wl_sta.o", - .version = "3.90.37.0", /* 15/02/2005 */ - .md5 = "4631d4d4c3ab943462e1ea24f4dba7bd", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x47040, - .uc2_pos = 0x4acb0, .uc2_length = 0x3f48, - .uc4_pos = 0x4ebfc, .uc4_length = 0x4df0, - .uc5_pos = 0x539f0, .uc5_length = 0x57e0, - .pcm4_pos = 0x591d4, .pcm4_length = 0x520, - .pcm5_pos = 0x596f8, .pcm5_length = 0x520, - }, - { - .name = "wl_sta.o", - .version = "3.90.37.0", /* 15/02/2005 */ - .md5 = "bf824b38b3993e0a8b5a9bf717c428ed", - .flags = BYTE_ORDER_LITTLE_ENDIAN, - .iv_pos = 0x47040, - .uc2_pos = 0x4acb0, .uc2_length = 0x3f48, - .uc4_pos = 0x4ebfc, .uc4_length = 0x4df0, - .uc5_pos = 0x539f0, .uc5_length = 0x57e0, - .pcm4_pos = 0x591d4, .pcm4_length = 0x520, - .pcm5_pos = 0x596f8, .pcm5_length = 0x520, - }, -}; - -#define FILES (sizeof(files) / sizeof(files[0])) diff --git a/target/linux/package/bcm43xx-standalone/fwcutter/md5.c b/target/linux/package/bcm43xx-standalone/fwcutter/md5.c deleted file mode 100644 index ad134146e4..0000000000 --- a/target/linux/package/bcm43xx-standalone/fwcutter/md5.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -/* Brutally hacked by John Walker back from ANSI C to K&R (no - prototypes) to maintain the tradition that Netfone will compile - with Sun's original "cc". */ -/* Ripped out ugly K&R again ;) --mbuesch */ - -#include /* for memcpy() */ -#include "md5.h" - -extern int big_endian_cpu; - -/* - * Note: this code is harmless on little-endian machines, - * but we return early nevertheless. - */ -static void byteReverse(unsigned char *buf, unsigned longs) -{ - uint32_t t; - - if (!big_endian_cpu) - return; - - do { - t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(uint32_t *) buf = t; - buf += 4; - } while (--longs); -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void MD5Transform(uint32_t *buf, uint32_t *in) -{ - register uint32_t a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len) -{ - uint32_t t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32_t *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32_t *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Final(unsigned char *digest, struct MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32_t *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((uint32_t *) ctx->in)[14] = ctx->bits[0]; - ((uint32_t *) ctx->in)[15] = ctx->bits[1]; - - MD5Transform(ctx->buf, (uint32_t *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} diff --git a/target/linux/package/bcm43xx-standalone/fwcutter/md5.h b/target/linux/package/bcm43xx-standalone/fwcutter/md5.h deleted file mode 100644 index ee574e4133..0000000000 --- a/target/linux/package/bcm43xx-standalone/fwcutter/md5.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef FWCUTTER_MD5_H_ -#define FWCUTTER_MD5_H_ - -#include - -struct MD5Context { - uint32_t buf[4]; - uint32_t bits[2]; - unsigned char in[64]; -}; - -void MD5Init(struct MD5Context *ctx); -void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len); -void MD5Final(unsigned char *digest, struct MD5Context *ctx); - -#endif /* FWCUTTER_MD5_H_ */ diff --git a/target/linux/package/bcm43xx-standalone/ipkg/kmod-bcm43xx-standalone.control b/target/linux/package/bcm43xx-standalone/ipkg/kmod-bcm43xx-standalone.control deleted file mode 100644 index 5dcc79f829..0000000000 --- a/target/linux/package/bcm43xx-standalone/ipkg/kmod-bcm43xx-standalone.control +++ /dev/null @@ -1,4 +0,0 @@ -Package: kmod-bcm43xx-standalone -Priority: optional -Section: sys -Description: Free BCM43xx wireless driver (devicescape) diff --git a/target/linux/package/ieee80211-dscape/Config.in b/target/linux/package/ieee80211-dscape/Config.in deleted file mode 100644 index d747ed2fba..0000000000 --- a/target/linux/package/ieee80211-dscape/Config.in +++ /dev/null @@ -1,10 +0,0 @@ -config PACKAGE_KMOD_IEEE80211_DSCAPE - prompt "kmod-ieee80211-dscape............. IEEE 802.11 stack (devicescape)" - tristate - default n - depends LINUX_2_6_BRCM || LINUX_2_6_X86 - - help - IEEE 802.11 stack (devicescape) - - http://ftp.kernel.org/pub/linux/kernel/people/jbenc/ diff --git a/target/linux/package/ieee80211-dscape/Makefile b/target/linux/package/ieee80211-dscape/Makefile deleted file mode 100644 index 3de9b34fb8..0000000000 --- a/target/linux/package/ieee80211-dscape/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# $Id$ - -include $(TOPDIR)/rules.mk -include ../../rules.mk - -PKG_NAME := kmod-ieee80211-dscape -PKG_RELEASE := 1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(TOPDIR)/package/rules.mk - -$(eval $(call PKG_template,KMOD_IEEE80211_DSCAPE,$(PKG_NAME),$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE),$(ARCH),kernel ($(LINUX_VERSION)-$(BOARD)-$(LINUX_RELEASE)))) - -$(PKG_BUILD_DIR)/.prepared: - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ - touch $@ - -$(PKG_BUILD_DIR)/.configured: - touch $@ - -$(PKG_BUILD_DIR)/.built: - $(MAKE) -C "$(LINUX_DIR)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - PATH="$(TARGET_PATH)" \ - SUBDIRS="$(PKG_BUILD_DIR)" \ - LINUXINCLUDE="-I$(shell pwd)/src/include -I$(LINUX_DIR)/include" \ - modules - touch $@ - -$(IPKG_KMOD_IEEE80211_DSCAPE): - install -m0755 -d $(IDIR_KMOD_IEEE80211_DSCAPE)/lib/modules/$(LINUX_VERSION) - #install -m0755 -d $(IDIR_KMOD_IEEE80211_DSCAPE)/etc/modules.d - $(CP) $(PKG_BUILD_DIR)/*.ko $(IDIR_KMOD_IEEE80211_DSCAPE)/lib/modules/$(LINUX_VERSION) - $(IPKG_BUILD) $(IDIR_KMOD_IEEE80211_DSCAPE) $(PACKAGE_DIR) - -install-dev: - mkdir -p $(STAGING_DIR)/usr/include/ieee80211-dscape - $(CP) src/include/* $(STAGING_DIR)/usr/include/ieee80211-dscape/ - -uninstall-dev: - rm -rf $(STAGING_DIR)/usr/include/ieee80211-dscape - -compile-targets: install-dev -clean-targets: uninstall-dev diff --git a/target/linux/package/ieee80211-dscape/ipkg/kmod-ieee80211-dscape.control b/target/linux/package/ieee80211-dscape/ipkg/kmod-ieee80211-dscape.control deleted file mode 100644 index f510d2d18c..0000000000 --- a/target/linux/package/ieee80211-dscape/ipkg/kmod-ieee80211-dscape.control +++ /dev/null @@ -1,4 +0,0 @@ -Package: kmod-ieee80211-dscape -Priority: optional -Section: sys -Description: IEEE 802.11 stack (devicescape) diff --git a/target/linux/package/ieee80211-dscape/src/Kconfig b/target/linux/package/ieee80211-dscape/src/Kconfig deleted file mode 100644 index 052a4190e5..0000000000 --- a/target/linux/package/ieee80211-dscape/src/Kconfig +++ /dev/null @@ -1,32 +0,0 @@ -config IEEE80211 - tristate "Generic IEEE 802.11 Networking Stack" - ---help--- - This option enables the hardware independent IEEE 802.11 - networking stack. - -config IEEE80211_DEBUG - bool "Enable debugging output" - depends on IEEE80211 - ---help--- - This option will enable debug tracing output for the - ieee80211 network stack. - - If you are not trying to debug or develop the ieee80211 - subsystem, you most likely want to say N here. - -config IEEE80211_VERBOSE_DEBUG - bool "Verbose debugging output" - depends on IEEE80211_DEBUG - -config TKIP_DEBUG - bool "TKIP debugging" - depends on IEEE80211_DEBUG - -config IEEE80211_DEBUG_COUNTERS - bool "Extra statistics for TX/RX debugging" - depends on IEEE80211_DEBUG - -config HOSTAPD_WPA_TESTING - bool "Support for TKIP countermeasures testing" - depends on IEEE80211_DEBUG - diff --git a/target/linux/package/ieee80211-dscape/src/Makefile b/target/linux/package/ieee80211-dscape/src/Makefile deleted file mode 100644 index ac4ab887ba..0000000000 --- a/target/linux/package/ieee80211-dscape/src/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -obj-$(CONFIG_IEEE80211) += 80211.o rate_control.o - -80211-objs := \ - ieee80211.o \ - ieee80211_ioctl.o \ - sta_info.o \ - wep.o \ - wpa.o \ - ieee80211_proc.o \ - ieee80211_scan.o \ - ieee80211_sta.o \ - michael.o \ - tkip.o \ - aes_ccm.o \ - wme.o - -ifeq ($(CONFIG_NET_SCHED),) - 80211-objs += fifo_qdisc.o -endif - -ifeq ($(CONFIG_IEEE80211_LEDS),y) - 80211-objs += ieee80211_led.o -endif diff --git a/target/linux/package/ieee80211-dscape/src/aes.c b/target/linux/package/ieee80211-dscape/src/aes.c deleted file mode 100644 index 085e4a9938..0000000000 --- a/target/linux/package/ieee80211-dscape/src/aes.c +++ /dev/null @@ -1,564 +0,0 @@ -/* Based on Rijndael implementation that has been placed in the public domain, - * although heavily modified. - * - * Modifications Copyright 2003, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Optimized both speed and size by removing not used key lengths (only - * 128-bit is used in IEEE 802.11i). - */ - -/* Use 256-byte Te4 table instead of larger 1024-byte */ -#define SMALL_TE4 - -/* Save data size by using only one 1k table, but with a drawback of having to - * rotate entries at lookup. This can be useful, if the CPU supports free - * rotate on memory read. However, if this is not the case, this is much slower - * than four-table implementation. */ -/* #define ONLY_ONE_TABLE */ - - -/* --- start of code that is based on public domain AES implementation --- */ - -/** - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen - * @author Antoon Bosselaers - * @author Paulo Barreto - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. - */ - -/* -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; -*/ - -static const u32 Te0[256] = -{ - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; - -#ifndef ONLY_ONE_TABLE -static const u32 Te1[256] = -{ - 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, - 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, - 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, - 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, - 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, - 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, - 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, - 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, - 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, - 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, - 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, - 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, - 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, - 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, - 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, - 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, - 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, - 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, - 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, - 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, - 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, - 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, - 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, - 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, - 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, - 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, - 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, - 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, - 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, - 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, - 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, - 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, - 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, - 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, - 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, - 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, - 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, - 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, - 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, - 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, - 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, - 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, - 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, - 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, - 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, - 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, - 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, - 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, - 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, - 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, - 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, - 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, - 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, - 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, - 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, - 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, - 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, - 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, - 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, - 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, - 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, - 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, - 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, - 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, -}; - -static const u32 Te2[256] = -{ - 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, - 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, - 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, - 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, - 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, - 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, - 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, - 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, - 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, - 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, - 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, - 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, - 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, - 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, - 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, - 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, - 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, - 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, - 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, - 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, - 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, - 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, - 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, - 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, - 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, - 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, - 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, - 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, - 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, - 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, - 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, - 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, - 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, - 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, - 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, - 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, - 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, - 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, - 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, - 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, - 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, - 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, - 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, - 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, - 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, - 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, - 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, - 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, - 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, - 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, - 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, - 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, - 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, - 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, - 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, - 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, - 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, - 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, - 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, - 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, - 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, - 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, - 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, - 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, -}; - -static const u32 Te3[256] = -{ - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, - 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, - 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, - 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, - 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, - 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, - 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, - 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, - 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, - 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, - 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, - 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, - 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, - 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, - 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, - 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, - 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, - 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, - 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, - 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, - 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, - 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, - 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, - 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, - 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, - 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, - 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, - 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, - 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, - 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, - 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, - 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, - 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, - 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, - 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, - 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, - 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, - 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, - 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, - 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, - 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, - 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, - 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, - 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, - 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, - 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, - 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, - 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, - 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, - 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, - 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, - 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, - 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, - 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, - 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, - 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, - 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, - 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, - 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, - 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, - 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, - 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, - 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, - 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}; - -#define TE0(v) (Te0[(v) >> 24]) -#define TE1(v) (Te1[((v) >> 16) & 0xff]) -#define TE2(v) (Te2[((v) >> 8) & 0xff]) -#define TE3(v) (Te3[(v) & 0xff]) - -#else /* ONLY_ONE_TABLE */ - - -static inline u32 ROR8(u32 v) -{ - return (v >> 8) | (v << 24); -} - -static inline u32 ROR16(u32 v) -{ - return (v >> 16) | (v << 16); -} - -static inline u32 ROR24(u32 v) -{ - return (v >> 24) | (v << 8); -} - -#define TE0(v) (Te0[(v) >> 24]) -#define TE1(v) (ROR8(Te0[((v) >> 16) & 0xff])) -#define TE2(v) (ROR16(Te0[((v) >> 8) & 0xff])) -#define TE3(v) (ROR24(Te0[(v) & 0xff])) - -#endif /* ONLY_ONE_TABLE */ - - - -#ifdef SMALL_TE4 -static const u8 Te4s[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, -}; - -#define TE4_1(v) (Te4s[(v) & 0xff] << 24) -#define TE4_2(v) (Te4s[(v) & 0xff] << 16) -#define TE4_3(v) (Te4s[(v) & 0xff] << 8) -#define TE4_4(v) (Te4s[(v) & 0xff]) - -#else /* SMALL_TE4 */ - -static const u32 Te4[256] = -{ - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; - -#define TE4_1(v) (Te4[(v) & 0xff] & 0xff000000) -#define TE4_2(v) (Te4[(v) & 0xff] & 0x00ff0000) -#define TE4_3(v) (Te4[(v) & 0xff] & 0x0000ff00) -#define TE4_4(v) (Te4[(v) & 0xff] & 0x000000ff) - -#endif /* SMALL_TE4 */ - - -static const u32 rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, -}; - -#define GETU32(pt) \ -(((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ \ -((u32)(pt)[3])) -#define PUTU32(ct, st) \ -{ (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ -(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } - - -/* Expand the cipher key into the encryption key schedule. */ -void ieee80211_aes_key_setup_encrypt(u32 rk[/*44*/], const u8 key[]) -{ - int i; - u32 temp; - - rk[0] = GETU32(key ); - rk[1] = GETU32(key + 4); - rk[2] = GETU32(key + 8); - rk[3] = GETU32(key + 12); - - for (i = 0; i < 10; i++) { - temp = rk[3]; - rk[4] = rk[0] ^ TE4_1(temp >> 16) ^ TE4_2(temp >> 8) ^ - TE4_3(temp) ^ TE4_4(temp >> 24) ^ rcon[i]; - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - rk += 4; - } -} - - -void ieee80211_aes_encrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) -{ - const int Nr = 10; - u32 s0, s1, s2, s3, t0, t1, t2, t3; - - /* Map byte array block to cipher state and add initial round key */ - s0 = GETU32(pt ) ^ rk[0]; - s1 = GETU32(pt + 4) ^ rk[1]; - s2 = GETU32(pt + 8) ^ rk[2]; - s3 = GETU32(pt + 12) ^ rk[3]; - -#define ROUND(r,d,s,i) \ -d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[i]; \ -d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[i + 1]; \ -d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[i + 2]; \ -d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[i + 3] - ROUND(1,t,s,4); - ROUND(2,s,t,8); - ROUND(3,t,s,12); - ROUND(4,s,t,16); - ROUND(5,t,s,20); - ROUND(6,s,t,24); - ROUND(7,t,s,28); - ROUND(8,s,t,32); - ROUND(9,t,s,36); -#undef ROUND - - rk += Nr << 2; - - /* Apply the last round and map cipher state to byte array block */ - s0 = TE4_1(t0 >> 24) ^ TE4_2(t1 >> 16) ^ TE4_3(t2 >> 8) ^ TE4_4(t3) ^ - rk[0]; - PUTU32(ct, s0); - s0 = TE4_1(t1 >> 24) ^ TE4_2(t2 >> 16) ^ TE4_3(t3 >> 8) ^ TE4_4(t0) ^ - rk[1]; - PUTU32(ct + 4, s0); - s0 = TE4_1(t2 >> 24) ^ TE4_2(t3 >> 16) ^ TE4_3(t0 >> 8) ^ TE4_4(t1) ^ - rk[2]; - PUTU32(ct + 8, s0); - s0 = TE4_1(t3 >> 24) ^ TE4_2(t0 >> 16) ^ TE4_3(t1 >> 8) ^ TE4_4(t2) ^ - rk[3]; - PUTU32(ct + 12, s0); -} - -/* --- end of code that is based on public domain AES implementation --- */ diff --git a/target/linux/package/ieee80211-dscape/src/aes_ccm.c b/target/linux/package/ieee80211-dscape/src/aes_ccm.c deleted file mode 100644 index bbc1f7bc96..0000000000 --- a/target/linux/package/ieee80211-dscape/src/aes_ccm.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2003-2004, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include - -#include -#include "ieee80211_key.h" -#include "aes_ccm.h" - -#include "aes.c" - -static inline void aes_ccm_prepare(u32 *rk, u8 *b_0, u8 *aad, u8 *b, - u8 *s_0, u8 *a) -{ - int i; - - ieee80211_aes_encrypt(rk, b_0, b); - - /* Extra Authenticate-only data (always two AES blocks) */ - for (i = 0; i < AES_BLOCK_LEN; i++) - aad[i] ^= b[i]; - ieee80211_aes_encrypt(rk, aad, b); - - aad += AES_BLOCK_LEN; - - for (i = 0; i < AES_BLOCK_LEN; i++) - aad[i] ^= b[i]; - ieee80211_aes_encrypt(rk, aad, a); - - /* Mask out bits from auth-only-b_0 */ - b_0[0] &= 0x07; - - /* S_0 is used to encrypt T (= MIC) */ - b_0[14] = 0; - b_0[15] = 0; - ieee80211_aes_encrypt(rk, b_0, s_0); -} - - -void ieee80211_aes_ccm_encrypt(u32 *rk, u8 *b_0, u8 *aad, u8 *data, - size_t data_len, u8 *cdata, u8 *mic) -{ - int i, j, last_len, num_blocks; - u8 *pos, *cpos; - u8 b[AES_BLOCK_LEN], s_0[AES_BLOCK_LEN], e[AES_BLOCK_LEN]; - - num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; - last_len = data_len % AES_BLOCK_LEN; - aes_ccm_prepare(rk, b_0, aad, b, s_0, b); - - /* Process payload blocks */ - pos = data; - cpos = cdata; - for (j = 1; j <= num_blocks; j++) { - int blen = (j == num_blocks && last_len) ? - last_len : AES_BLOCK_LEN; - - /* Authentication followed by encryption */ - for (i = 0; i < blen; i++) - b[i] ^= pos[i]; - ieee80211_aes_encrypt(rk, b, b); - - b_0[14] = (j >> 8) & 0xff; - b_0[15] = j & 0xff; - ieee80211_aes_encrypt(rk, b_0, e); - for (i = 0; i < blen; i++) - *cpos++ = *pos++ ^ e[i]; - } - - for (i = 0; i < CCMP_MIC_LEN; i++) - mic[i] = b[i] ^ s_0[i]; -} - - -int ieee80211_aes_ccm_decrypt(u32 *rk, u8 *b_0, u8 *aad, u8 *cdata, - size_t data_len, u8 *mic, u8 *data) -{ - int i, j, last_len, num_blocks; - u8 *pos, *cpos; - u8 b[AES_BLOCK_LEN], s_0[AES_BLOCK_LEN], a[AES_BLOCK_LEN]; - - num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; - last_len = data_len % AES_BLOCK_LEN; - aes_ccm_prepare(rk, b_0, aad, b, s_0, a); - - /* Process payload blocks */ - cpos = cdata; - pos = data; - for (j = 1; j <= num_blocks; j++) { - int blen = (j == num_blocks && last_len) ? - last_len : AES_BLOCK_LEN; - - /* Decryption followed by authentication */ - b_0[14] = (j >> 8) & 0xff; - b_0[15] = j & 0xff; - ieee80211_aes_encrypt(rk, b_0, b); - for (i = 0; i < blen; i++) { - *pos = *cpos++ ^ b[i]; - a[i] ^= *pos++; - } - - ieee80211_aes_encrypt(rk, a, a); - } - - for (i = 0; i < CCMP_MIC_LEN; i++) { - if ((mic[i] ^ s_0[i]) != a[i]) - return -1; - } - - return 0; -} - diff --git a/target/linux/package/ieee80211-dscape/src/aes_ccm.h b/target/linux/package/ieee80211-dscape/src/aes_ccm.h deleted file mode 100644 index f741b088ed..0000000000 --- a/target/linux/package/ieee80211-dscape/src/aes_ccm.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2003-2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef AES_CCM_H -#define AES_CCM_H - -#define AES_BLOCK_LEN 16 -#define AES_STATE_LEN 44 - -void ieee80211_aes_key_setup_encrypt(u32 rk[/*44*/], const u8 key[]); -void ieee80211_aes_encrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]); -void ieee80211_aes_ccm_encrypt(u32 rk[/*44*/], u8 *b_0, u8 *aad, u8 *data, - size_t data_len, u8 *cdata, u8 *mic); -int ieee80211_aes_ccm_decrypt(u32 rk[/*44*/], u8 *b_0, u8 *aad, u8 *cdata, - size_t data_len, u8 *mic, u8 *data); - -#endif /* AES_CCM_H */ diff --git a/target/linux/package/ieee80211-dscape/src/fifo_qdisc.c b/target/linux/package/ieee80211-dscape/src/fifo_qdisc.c deleted file mode 100644 index 95bc0b5777..0000000000 --- a/target/linux/package/ieee80211-dscape/src/fifo_qdisc.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * If building without CONFIG_NET_SCHED we need a simple - * fifo qdisc to install by default as the sub-qdisc. - * This is a simple replacement for sch_fifo. - */ - -#include -#include -#include -#include -#include "ieee80211_i.h" -#include "wme.h" - -static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* qd) -{ - struct sk_buff_head *q = qdisc_priv(qd); - - if (skb_queue_len(q) > qd->dev->tx_queue_len) { - qd->qstats.drops++; - kfree_skb(skb); - return NET_XMIT_DROP; - } - - skb_queue_tail(q, skb); - qd->q.qlen++; - qd->bstats.bytes += skb->len; - qd->bstats.packets++; - - return NET_XMIT_SUCCESS; -} - - -static int pfifo_requeue(struct sk_buff *skb, struct Qdisc* qd) -{ - struct sk_buff_head *q = qdisc_priv(qd); - - skb_queue_head(q, skb); - qd->q.qlen++; - qd->bstats.bytes += skb->len; - qd->bstats.packets++; - - return NET_XMIT_SUCCESS; -} - - -static struct sk_buff *pfifo_dequeue(struct Qdisc* qd) -{ - struct sk_buff_head *q = qdisc_priv(qd); - - return skb_dequeue(q); -} - - -static int pfifo_init(struct Qdisc* qd, struct rtattr *opt) -{ - struct sk_buff_head *q = qdisc_priv(qd); - - skb_queue_head_init(q); - return 0; -} - - -static void pfifo_reset(struct Qdisc* qd) -{ - struct sk_buff_head *q = qdisc_priv(qd); - - skb_queue_purge(q); - qd->q.qlen = 0; -} - - -static int pfifo_dump(struct Qdisc *qd, struct sk_buff *skb) -{ - return skb->len; -} - - -struct Qdisc_ops pfifo_qdisc_ops = -{ - .next = NULL, - .cl_ops = NULL, - .id = "ieee80211_pfifo", - .priv_size = sizeof(struct sk_buff_head), - - .enqueue = pfifo_enqueue, - .dequeue = pfifo_dequeue, - .requeue = pfifo_requeue, - .drop = NULL, - - .init = pfifo_init, - .reset = pfifo_reset, - .destroy = NULL, - .change = NULL, - - .dump = pfifo_dump, -}; - diff --git a/target/linux/package/ieee80211-dscape/src/hostapd_ioctl.h b/target/linux/package/ieee80211-dscape/src/hostapd_ioctl.h deleted file mode 100644 index eff4858353..0000000000 --- a/target/linux/package/ieee80211-dscape/src/hostapd_ioctl.h +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Host AP (software wireless LAN access point) user space daemon for - * Host AP kernel driver - * Copyright 2002-2003, Jouni Malinen - * Copyright 2002-2004, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef HOSTAPD_IOCTL_H -#define HOSTAPD_IOCTL_H - -#ifndef __KERNEL__ -#include "ieee80211_shared.h" -#endif /* __KERNEL__ */ - -#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) -#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1) -#define PRISM2_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 3) -#define PRISM2_IOCTL_TEST_PARAM (SIOCIWFIRSTPRIV + 4) - -/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ -enum { - PRISM2_PARAM_PTYPE = 1, - PRISM2_PARAM_TXRATECTRL = 2, - PRISM2_PARAM_BEACON_INT = 3, - PRISM2_PARAM_PSEUDO_IBSS = 4, - PRISM2_PARAM_ALC = 5, - PRISM2_PARAM_TXPOWER = 6, - PRISM2_PARAM_DUMP = 7, - PRISM2_PARAM_OTHER_AP_POLICY = 8, - PRISM2_PARAM_AP_MAX_INACTIVITY = 9, - PRISM2_PARAM_AP_BRIDGE_PACKETS = 10, - PRISM2_PARAM_DTIM_PERIOD = 11, - PRISM2_PARAM_AP_NULLFUNC_ACK = 12, - PRISM2_PARAM_MAX_WDS = 13, - PRISM2_PARAM_AP_AUTOM_AP_WDS = 14, - PRISM2_PARAM_AP_AUTH_ALGS = 15, - PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16, - PRISM2_PARAM_HOST_ENCRYPT = 17, - PRISM2_PARAM_HOST_DECRYPT = 18, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, - PRISM2_PARAM_HOST_ROAMING = 21, - PRISM2_PARAM_BCRX_STA_KEY = 22, - PRISM2_PARAM_IEEE_802_1X = 23, - PRISM2_PARAM_ANTSEL_TX = 24, - PRISM2_PARAM_ANTSEL_RX = 25, - PRISM2_PARAM_MONITOR_TYPE = 26, - PRISM2_PARAM_WDS_TYPE = 27, - PRISM2_PARAM_HOSTSCAN = 28, - PRISM2_PARAM_AP_SCAN = 29, - - /* Instant802 additions */ - PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001, - PRISM2_PARAM_DROP_UNENCRYPTED = 1002, - PRISM2_PARAM_PREAMBLE = 1003, - PRISM2_PARAM_RATE_LIMIT = 1004, - PRISM2_PARAM_RATE_LIMIT_BURST = 1005, - PRISM2_PARAM_SHORT_SLOT_TIME = 1006, - PRISM2_PARAM_TEST_MODE = 1007, - PRISM2_PARAM_NEXT_MODE = 1008, - PRISM2_PARAM_CLEAR_KEYS = 1009, - PRISM2_PARAM_ADM_STATUS = 1010, - PRISM2_PARAM_ANTENNA_SEL = 1011, - PRISM2_PARAM_CALIB_INT = 1012, - PRISM2_PARAM_ANTENNA_MODE = 1013, - PRISM2_PARAM_PRIVACY_INVOKED = 1014, - PRISM2_PARAM_BROADCAST_SSID = 1015, - PRISM2_PARAM_STAT_TIME = 1016, - PRISM2_PARAM_STA_ANTENNA_SEL = 1017, - PRISM2_PARAM_FORCE_UNICAST_RATE = 1018, - PRISM2_PARAM_RATE_CTRL_NUM_UP = 1019, - PRISM2_PARAM_RATE_CTRL_NUM_DOWN = 1020, - PRISM2_PARAM_MAX_RATECTRL_RATE = 1021, - PRISM2_PARAM_TX_POWER_REDUCTION = 1022, - PRISM2_PARAM_EAPOL = 1023, - PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024, - PRISM2_PARAM_KEY_INDEX = 1025, - PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026, - PRISM2_PARAM_WIFI_WME_NOACK_TEST = 1033, - PRISM2_PARAM_ALLOW_BROADCAST_ALWAYS = 1034, - PRISM2_PARAM_SCAN_FLAGS = 1035, - PRISM2_PARAM_HW_MODES = 1036, - PRISM2_PARAM_CREATE_IBSS = 1037, - PRISM2_PARAM_WMM_ENABLED = 1038, - PRISM2_PARAM_MIXED_CELL = 1039, - PRISM2_PARAM_KEY_MGMT = 1040, - PRISM2_PARAM_RADAR_DETECT = 1043, - PRISM2_PARAM_SPECTRUM_MGMT = 1044, - /* NOTE: Please try to coordinate with other active development - * branches before allocating new param numbers so that each new param - * will be unique within all branches and the allocated number will not - * need to be changed when merging new features. Existing numbers in - * the mainline (or main devel branch) must not be changed when merging - * in new features. */ -}; - -/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ -enum { - PRISM2_HOSTAPD_FLUSH = 1, - PRISM2_HOSTAPD_ADD_STA = 2, - PRISM2_HOSTAPD_REMOVE_STA = 3, - PRISM2_HOSTAPD_GET_INFO_STA = 4, - /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */ - PRISM2_SET_ENCRYPTION = 6, - PRISM2_GET_ENCRYPTION = 7, - PRISM2_HOSTAPD_SET_FLAGS_STA = 8, - PRISM2_HOSTAPD_GET_RID = 9, - PRISM2_HOSTAPD_SET_RID = 10, - PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11, - PRISM2_HOSTAPD_MLME = 13, - - /* Instant802 additions */ - PRISM2_HOSTAPD_SET_BEACON = 1001, - PRISM2_HOSTAPD_GET_HW_FEATURES = 1002, - PRISM2_HOSTAPD_SCAN = 1003, - PRISM2_HOSTAPD_WPA_TRIGGER = 1004, - PRISM2_HOSTAPD_SET_RATE_SETS = 1005, - PRISM2_HOSTAPD_ADD_IF = 1006, - PRISM2_HOSTAPD_REMOVE_IF = 1007, - PRISM2_HOSTAPD_GET_DOT11COUNTERSTABLE = 1008, - PRISM2_HOSTAPD_GET_LOAD_STATS = 1009, - PRISM2_HOSTAPD_SET_STA_VLAN = 1010, - PRISM2_HOSTAPD_SET_GENERIC_INFO_ELEM = 1011, - PRISM2_HOSTAPD_SET_CHANNEL_FLAG = 1012, - PRISM2_HOSTAPD_SET_REGULATORY_DOMAIN = 1013, - PRISM2_HOSTAPD_SET_TX_QUEUE_PARAMS = 1014, - PRISM2_HOSTAPD_SET_BSS = 1015, - PRISM2_HOSTAPD_GET_TX_STATS = 1016, - PRISM2_HOSTAPD_UPDATE_IF = 1017, - PRISM2_HOSTAPD_SCAN_REQ = 1019, - PRISM2_STA_GET_STATE = 1020, - PRISM2_HOSTAPD_FLUSH_IFS = 1021, - PRISM2_HOSTAPD_SET_RADAR_PARAMS = 1023, - PRISM2_HOSTAPD_SET_QUIET_PARAMS = 1024, - PRISM2_HOSTAPD_GET_TX_POWER = 1025, - /* NOTE: Please try to coordinate with other active development - * branches before allocating new param numbers so that each new param - * will be unique within all branches and the allocated number will not - * need to be changed when merging new features. Existing numbers in - * the mainline (or main devel branch) must not be changed when merging - * in new features. */ -}; - - /* these definitions mirror the ieee80211_i.h - * IEEE80211_DISABLED, ... IEEE80211_ASSOCIATED enumeration */ -enum { - PRISM2_PARAM_STA_DISABLED, - PRISM2_PARAM_STA_AUTHENTICATE, - PRISM2_PARAM_STA_ASSOCIATE, - PRISM2_PARAM_STA_ASSOCIATED, -}; - -#define PRISM2_HOSTAPD_MAX_BUF_SIZE 2048 -#define HOSTAP_CRYPT_ALG_NAME_LEN 16 - -/* Use this to make sure that structure elements are correctly aligned - * for access as other types. Most commonly, this affects the placeholder - * types used for data at the end of a structure in this union. - */ -#ifdef __GNUC__ -#undef ALIGNED -#define ALIGNED __attribute__ ((aligned)) -#else -/* Check if it has been defined elsewhere */ -#ifndef ALIGNED -#error "Must define ALIGNED to generate aligned structure elements" -#endif -#endif - -struct prism2_hostapd_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - u8 pad[2]; - union { - struct { - u16 aid; - u16 capability; - u8 supp_rates[32]; - /* atheros_super_ag and enc_flags are only used with - * IEEE80211_ATHEROS_SUPER_AG - */ - u8 atheros_super_ag; - u8 atheros_xr_mode; - u8 wds_flags; -#define IEEE80211_STA_DYNAMIC_ENC BIT(0) - u8 enc_flags; - } add_sta; - struct { - u32 inactive_msec; - u32 rx_packets; - u32 tx_packets; - u32 rx_bytes; - u32 tx_bytes; - u32 current_tx_rate; /* in 100 kbps */ - u32 channel_use; - u32 flags; - u32 num_ps_buf_frames; - u32 tx_retry_failed; - u32 tx_retry_count; - u32 last_rssi; - u32 last_ack_rssi; - } get_info_sta; - struct { - u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; - u32 flags; - u32 err; - u8 idx; -#define HOSTAP_SEQ_COUNTER_SIZE 8 - u8 seq_counter[HOSTAP_SEQ_COUNTER_SIZE]; - u16 key_len; - u8 key[0] ALIGNED; - } crypt; - struct { - u32 flags_and; - u32 flags_or; - } set_flags_sta; - struct { - u16 rid; - u16 len; - u8 data[0] ALIGNED; - } rid; - struct { - u16 head_len; - u16 tail_len; - u8 data[0] ALIGNED; /* head_len + tail_len bytes */ - } beacon; - struct { - u16 num_modes; - u16 flags; - u8 data[0] ALIGNED; /* num_modes * feature data */ - } hw_features; - struct { - u8 now; - s8 our_mode_only; - s16 last_rx; - u16 channel; - s16 interval; /* seconds */ - s32 listen; /* microseconds */ - } scan; - struct { -#define WPA_TRIGGER_FAIL_TX_MIC BIT(0) -#define WPA_TRIGGER_FAIL_TX_ICV BIT(1) -#define WPA_TRIGGER_FAIL_RX_MIC BIT(2) -#define WPA_TRIGGER_FAIL_RX_ICV BIT(3) -#define WPA_TRIGGER_TX_REPLAY BIT(4) -#define WPA_TRIGGER_TX_REPLAY_FRAG BIT(5) -#define WPA_TRIGGER_TX_SKIP_SEQ BIT(6) - u32 trigger; - } wpa_trigger; - struct { - u16 mode; /* MODE_* */ - u16 num_supported_rates; - u16 num_basic_rates; - u8 data[0] ALIGNED; /* num_supported_rates * u16 + - * num_basic_rates * u16 */ - } set_rate_sets; - struct { - u8 type; /* WDS, VLAN, etc */ - u8 name[IFNAMSIZ]; - u8 data[0] ALIGNED; - } if_info; - struct dot11_counters { - u32 dot11TransmittedFragmentCount; - u32 dot11MulticastTransmittedFrameCount; - u32 dot11FailedCount; - u32 dot11ReceivedFragmentCount; - u32 dot11MulticastReceivedFrameCount; - u32 dot11FCSErrorCount; - u32 dot11TransmittedFrameCount; - u32 dot11WEPUndecryptableCount; - u32 dot11ACKFailureCount; - u32 dot11RTSFailureCount; - u32 dot11RTSSuccessCount; - } dot11CountersTable; - struct { -#define LOAD_STATS_CLEAR BIT(1) - u32 flags; - u32 channel_use; - } get_load_stats; - struct { - char vlan_name[IFNAMSIZ]; - int vlan_id; - } set_sta_vlan; - struct { - u8 len; - u8 data[0] ALIGNED; - } set_generic_info_elem; - struct { - u16 mode; /* MODE_* */ - u16 chan; - u32 flag; - u8 power_level; /* regulatory limit in dBm */ - u8 antenna_max; - } set_channel_flag; - struct { - u32 rd; - } set_regulatory_domain; - struct { - u32 queue; - s32 aifs; - u32 cw_min; - u32 cw_max; - u32 burst_time; /* maximum burst time in 0.1 ms, i.e., - * 10 = 1 ms */ - } tx_queue_params; - struct { - u32 bss_count; - u8 bssid_mask[ETH_ALEN]; - } set_bss; - struct ieee80211_tx_stats { - struct { - unsigned int len; /* num packets in queue */ - unsigned int limit; /* queue len (soft) limit - */ - unsigned int count; /* total num frames sent */ - } data[4]; - } get_tx_stats; - struct { - u8 ssid_len; - u8 ssid[0] ALIGNED; - } scan_req; - struct { - u32 state; - } sta_get_state; - struct { -#define MLME_STA_DEAUTH 0 -#define MLME_STA_DISASSOC 1 - u16 cmd; - u16 reason_code; - } mlme; - struct { - unsigned int value; - /* TODO - int pulse_width; - int num_pulse; - int period; - */ - }radar; - struct { - unsigned int period; - unsigned int offset; - unsigned int duration; - }quiet; - struct { - unsigned int tx_power_min; - unsigned int tx_power_max; - }tx_power; - struct { - u8 dummy[80]; /* Make sizeof() this struct large enough - * with some compiler versions. */ - } dummy; - } u; -}; - - -#ifndef IEEE80211_TX_QUEUE_NUMS -#define IEEE80211_TX_QUEUE_NUMS -/* TODO: these need to be synchronized with ieee80211.h; make a shared header - * file that can be included into low-level drivers, 80211.o, and hostapd */ -/* tx_queue_params - queue */ -enum { - IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */ - IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */ - IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */ - IEEE80211_TX_QUEUE_DATA3 = 3, /* used for EDCA AC_BK data */ - IEEE80211_TX_QUEUE_DATA4 = 4, - IEEE80211_TX_QUEUE_AFTER_BEACON = 6, - IEEE80211_TX_QUEUE_BEACON = 7 -}; -#endif /* IEEE80211_TX_QUEUE_NUMS */ - - -#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0) -#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1) - -#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 -#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 - -#define HOSTAP_HW_FLAG_NULLFUNC_OK BIT(0) - -enum { - IEEE80211_KEY_MGMT_NONE = 0, - IEEE80211_KEY_MGMT_IEEE8021X = 1, - IEEE80211_KEY_MGMT_WPA_PSK = 2, - IEEE80211_KEY_MGMT_WPA_EAP = 3, -}; - - -/* Data structures used for get_hw_features ioctl */ -struct hostapd_ioctl_hw_modes_hdr { - int mode; - int num_channels; - int num_rates; -}; - -struct ieee80211_channel_data { - short chan; /* channel number (IEEE 802.11) */ - short freq; /* frequency in MHz */ - int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */ -}; - -struct ieee80211_rate_data { - int rate; /* rate in 100 kbps */ - int flags; /* IEEE80211_RATE_ flags */ -}; - - -/* ADD_IF, REMOVE_IF, and UPDATE_IF 'type' argument */ -enum { - HOSTAP_IF_WDS = 1, HOSTAP_IF_VLAN = 2, HOSTAP_IF_BSS = 3, - HOSTAP_IF_STA = 4 -}; - -struct hostapd_if_wds { - u8 remote_addr[ETH_ALEN]; -}; - -struct hostapd_if_vlan { - u8 id; -}; - -struct hostapd_if_bss { - u8 bssid[ETH_ALEN]; -}; - -struct hostapd_if_sta { -}; - -#endif /* HOSTAPD_IOCTL_H */ diff --git a/target/linux/package/ieee80211-dscape/src/ieee80211.c b/target/linux/package/ieee80211-dscape/src/ieee80211.c deleted file mode 100644 index 5e4e7acfba..0000000000 --- a/target/linux/package/ieee80211-dscape/src/ieee80211.c +++ /dev/null @@ -1,4895 +0,0 @@ -/* - * Copyright 2002-2005, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef EXPORT_SYMTAB -#define EXPORT_SYMTAB -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "ieee80211_i.h" -#include "ieee80211_proc.h" -#include "rate_control.h" -#include "wep.h" -#include "wpa.h" -#include "tkip.h" -#include "wme.h" - - -/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ -/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static unsigned char rfc1042_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char bridge_tunnel_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; -/* No encapsulation header if EtherType < 0x600 (=length) */ - -static unsigned char eapol_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e }; - - -struct rate_control_algs { - struct rate_control_algs *next; - struct rate_control_ops *ops; -}; - -static struct rate_control_algs *ieee80211_rate_ctrl_algs; - -static int rate_control_initialize(struct ieee80211_local *local); - - -static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len); - - -struct ieee80211_key_conf * -ieee80211_key_data2conf(struct ieee80211_local *local, - struct ieee80211_key *data) -{ - struct ieee80211_key_conf *conf; - - conf = kmalloc(sizeof(*conf) + data->keylen, GFP_ATOMIC); - if (conf == NULL) - return NULL; - - conf->hw_key_idx = data->hw_key_idx; - conf->alg = data->alg; - conf->keylen = data->keylen; - conf->force_sw_encrypt = data->force_sw_encrypt; - conf->keyidx = data->keyidx; - conf->default_tx_key = data->default_tx_key; - conf->default_wep_only = local->default_wep_only; - memcpy(conf->key, data->key, data->keylen); - - return conf; -} - - -static int rate_list_match(int *rate_list, int rate) -{ - int i; - - if (rate_list == NULL) - return 0; - - for (i = 0; rate_list[i] >= 0; i++) - if (rate_list[i] == rate) - return 1; - - return 0; -} - - -void ieee80211_prepare_rates(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - int i; - - for (i = 0; i < local->num_curr_rates; i++) { - struct ieee80211_rate *rate = &local->curr_rates[i]; - - rate->flags &= ~(IEEE80211_RATE_SUPPORTED | - IEEE80211_RATE_BASIC); - - if (local->supp_rates[local->conf.phymode]) { - if (!rate_list_match(local->supp_rates - [local->conf.phymode], - rate->rate)) - continue; - } - - rate->flags |= IEEE80211_RATE_SUPPORTED; - - /* Use configured basic rate set if it is available. If not, - * use defaults that are sane for most cases. */ - if (local->basic_rates[local->conf.phymode]) { - if (rate_list_match(local->basic_rates - [local->conf.phymode], - rate->rate)) - rate->flags |= IEEE80211_RATE_BASIC; - } else switch (local->conf.phymode) { - case MODE_IEEE80211A: - if (rate->rate == 60 || rate->rate == 120 || - rate->rate == 240) - rate->flags |= IEEE80211_RATE_BASIC; - break; - case MODE_IEEE80211B: - if (rate->rate == 10 || rate->rate == 20) - rate->flags |= IEEE80211_RATE_BASIC; - break; - case MODE_ATHEROS_TURBO: - if (rate->rate == 120 || rate->rate == 240 || - rate->rate == 480) - rate->flags |= IEEE80211_RATE_BASIC; - break; - case MODE_IEEE80211G: - if (rate->rate == 10 || rate->rate == 20 || - rate->rate == 55 || rate->rate == 110) - rate->flags |= IEEE80211_RATE_BASIC; - break; - } - - /* Set ERP and MANDATORY flags based on phymode */ - switch (local->conf.phymode) { - case MODE_IEEE80211A: - if (rate->rate == 60 || rate->rate == 120 || - rate->rate == 240) - rate->flags |= IEEE80211_RATE_MANDATORY; - break; - case MODE_IEEE80211B: - if (rate->rate == 10) - rate->flags |= IEEE80211_RATE_MANDATORY; - break; - case MODE_ATHEROS_TURBO: - break; - case MODE_IEEE80211G: - if (rate->rate == 10 || rate->rate == 20 || - rate->rate == 55 || rate->rate == 110 || - rate->rate == 60 || rate->rate == 120 || - rate->rate == 240) - rate->flags |= IEEE80211_RATE_MANDATORY; - if (rate->rate != 10 && rate->rate != 20 && - rate->rate != 55 && rate->rate != 110) - rate->flags |= IEEE80211_RATE_ERP; - break; - } - } -} - - -static void ieee80211_key_threshold_notify(struct net_device *dev, - struct ieee80211_key *key, - struct sta_info *sta) -{ - struct sk_buff *skb; - struct ieee80211_msg_key_notification *msg; - - skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) + - sizeof(struct ieee80211_msg_key_notification)); - if (skb == NULL) - return; - - skb_reserve(skb, sizeof(struct ieee80211_frame_info)); - msg = (struct ieee80211_msg_key_notification *) - skb_put(skb, sizeof(struct ieee80211_msg_key_notification)); - msg->tx_rx_count = key->tx_rx_count; - memcpy(msg->ifname, dev->name, IFNAMSIZ); - if (sta) - memcpy(msg->addr, sta->addr, ETH_ALEN); - else - memset(msg->addr, 0xff, ETH_ALEN); - - key->tx_rx_count = 0; - - ieee80211_rx_mgmt(dev, skb, 0, - ieee80211_msg_key_threshold_notification); -} - - -int ieee80211_get_hdrlen(u16 fc) -{ - int hdrlen = 24; - - switch (WLAN_FC_GET_TYPE(fc)) { - case WLAN_FC_TYPE_DATA: - if ((fc & WLAN_FC_FROMDS) && (fc & WLAN_FC_TODS)) - hdrlen = 30; /* Addr4 */ - if (WLAN_FC_GET_STYPE(fc) & 0x08) - hdrlen += 2; /* QoS Control Field */ - break; - case WLAN_FC_TYPE_CTRL: - switch (WLAN_FC_GET_STYPE(fc)) { - case WLAN_FC_STYPE_CTS: - case WLAN_FC_STYPE_ACK: - hdrlen = 10; - break; - default: - hdrlen = 16; - break; - } - break; - } - - return hdrlen; -} - - -int ieee80211_get_hdrlen_from_skb(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - int hdrlen; - - if (unlikely(skb->len < 10)) - return 0; - hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); - if (unlikely(hdrlen > skb->len)) - return 0; - return hdrlen; -} - - -#ifdef IEEE80211_VERBOSE_DEBUG_FRAME_DUMP -static void ieee80211_dump_frame(const char *ifname, const char *title, - struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 fc; - int hdrlen; - - printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); - if (skb->len < 4) { - printk("\n"); - return; - } - - fc = le16_to_cpu(hdr->frame_control); - hdrlen = ieee80211_get_hdrlen(fc); - if (hdrlen > skb->len) - hdrlen = skb->len; - if (hdrlen >= 4) - printk(" FC=0x%04x DUR=0x%04x", - fc, le16_to_cpu(hdr->duration_id)); - if (hdrlen >= 10) - printk(" A1=" MACSTR, MAC2STR(hdr->addr1)); - if (hdrlen >= 16) - printk(" A2=" MACSTR, MAC2STR(hdr->addr2)); - if (hdrlen >= 24) - printk(" A3=" MACSTR, MAC2STR(hdr->addr3)); - if (hdrlen >= 30) - printk(" A4=" MACSTR, MAC2STR(hdr->addr4)); - printk("\n"); -} -#else /* IEEE80211_VERBOSE_DEBUG_FRAME_DUMP */ -static inline void ieee80211_dump_frame(const char *ifname, const char *title, - struct sk_buff *skb) -{ -} -#endif /* IEEE80211_VERBOSE_DEBUG_FRAME_DUMP */ - - -static int ieee80211_is_eapol(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - u16 fc; - int hdrlen; - - if (unlikely(skb->len < 10)) - return 0; - - hdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(hdr->frame_control); - - if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) - return 0; - - hdrlen = ieee80211_get_hdrlen(fc); - - if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) && - memcmp(skb->data + hdrlen, eapol_header, - sizeof(eapol_header)) == 0)) - return 1; - - return 0; -} - - -static ieee80211_txrx_result -ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx) -{ - struct rate_control_extra extra; - - memset(&extra, 0, sizeof(extra)); - extra.mgmt_data = tx->sdata && - tx->sdata->type == IEEE80211_SUB_IF_TYPE_MGMT; - extra.ethertype = tx->ethertype; - extra.startidx = 0; - extra.endidx = tx->local->num_curr_rates; - - - tx->u.tx.rate = rate_control_get_rate(tx->dev, tx->skb, &extra); - if (unlikely(extra.probe != NULL)) { - tx->u.tx.control->rate_ctrl_probe = 1; - tx->u.tx.probe_last_frag = 1; -// tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val; - tx->u.tx.rate = extra.probe; - } else { -// tx->u.tx.control->alt_retry_rate = -1; - } - if (!tx->u.tx.rate) - return TXRX_DROP; - if (tx->local->conf.phymode == MODE_IEEE80211G && - tx->local->cts_protect_erp_frames && tx->fragmented && - extra.nonerp) { - tx->u.tx.last_frag_rate = tx->u.tx.rate; - tx->u.tx.last_frag_rateidx = extra.rateidx; - tx->u.tx.probe_last_frag = extra.probe ? 1 : 0; - - tx->u.tx.rate = extra.nonerp; -// tx->u.tx.control->rateidx = extra.nonerp_idx; - tx->u.tx.control->rate_ctrl_probe = 0; - } else { - tx->u.tx.last_frag_rate = tx->u.tx.rate; - tx->u.tx.last_frag_rateidx = extra.rateidx; -// tx->u.tx.control->rateidx = extra.rateidx; - } - tx->u.tx.control->tx_rate = tx->u.tx.rate->val; - if ((tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) && - tx->local->short_preamble && - (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) { - tx->u.tx.short_preamble = 1; - tx->u.tx.control->tx_rate = tx->u.tx.rate->val2; - } - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx) -{ - if (tx->sta) - tx->u.tx.control->key_idx = tx->sta->key_idx_compression; - else - tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID; - - if (unlikely(tx->u.tx.control->do_not_encrypt)) - tx->key = NULL; - else if (tx->sta && tx->sta->key) - tx->key = tx->sta->key; - else if (tx->sdata->default_key) - tx->key = tx->sdata->default_key; - else if (tx->sdata->drop_unencrypted && !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) { - I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); - return TXRX_DROP; - } else - tx->key = NULL; - - if (tx->key) { - tx->key->tx_rx_count++; - if (unlikely(tx->local->key_tx_rx_threshold && - tx->key->tx_rx_count > - tx->local->key_tx_rx_threshold)) { - ieee80211_key_threshold_notify(tx->dev, tx->key, - tx->sta); - } - } - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; - size_t hdrlen, per_fragm, num_fragm, payload_len, left; - struct sk_buff **frags, *first, *frag; - int i; - u8 *pos; - int frag_threshold = tx->local->fragmentation_threshold; - - if (!tx->fragmented) - return TXRX_CONTINUE; - - - first = tx->skb; - - hdrlen = ieee80211_get_hdrlen(tx->fc); - payload_len = first->len - hdrlen; - per_fragm = frag_threshold - hdrlen - 4 /* FCS */; - num_fragm = (payload_len + per_fragm - 1) / per_fragm; - - frags = (struct sk_buff **) - kmalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC); - if (frags == NULL) - goto fail; - memset(frags, 0, num_fragm * sizeof(struct sk_buff *)); - - hdr->frame_control |= cpu_to_le16(WLAN_FC_MOREFRAG); - pos = first->data + hdrlen + per_fragm; - left = payload_len - per_fragm; - for (i = 0; i < num_fragm - 1; i++) { - struct ieee80211_hdr *fhdr; - size_t copylen; - - if (left <= 0) - goto fail; - - /* reserve enough extra head and tail room for possible - * encryption */ -#define IEEE80211_ENCRYPT_HEADROOM 8 -#define IEEE80211_ENCRYPT_TAILROOM 12 - frag = frags[i] = - dev_alloc_skb(frag_threshold + - IEEE80211_ENCRYPT_HEADROOM + - IEEE80211_ENCRYPT_TAILROOM); - if (!frag) - goto fail; - /* Make sure that all fragments use the same priority so - * that they end up using the same TX queue */ - frag->priority = first->priority; - skb_reserve(frag, IEEE80211_ENCRYPT_HEADROOM); - fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); - memcpy(fhdr, first->data, hdrlen); - if (i == num_fragm - 2) - fhdr->frame_control &= cpu_to_le16(~WLAN_FC_MOREFRAG); - fhdr->seq_ctrl = cpu_to_le16(i + 1); - copylen = left > per_fragm ? per_fragm : left; - memcpy(skb_put(frag, copylen), pos, copylen); - - pos += copylen; - left -= copylen; - } - skb_trim(first, hdrlen + per_fragm); - - tx->u.tx.num_extra_frag = num_fragm - 1; - tx->u.tx.extra_frag = frags; - - return TXRX_CONTINUE; - - fail: - printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name); - if (frags) { - for (i = 0; i < num_fragm - 1; i++) - if (frags[i]) - dev_kfree_skb(frags[i]); - kfree(frags); - } - I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment); - return TXRX_DROP; -} - - -static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb) -{ - if (tx->key->force_sw_encrypt || tx->local->conf.sw_encrypt) { - if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) - return -1; - } else { - tx->u.tx.control->key_idx = tx->key->hw_key_idx; - if (tx->local->hw->wep_include_iv) { - if (ieee80211_wep_add_iv(tx->local, skb, tx->key) == - NULL) - return -1; - } - } - return 0; -} - - -void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; - - hdr->frame_control |= cpu_to_le16(WLAN_FC_ISWEP); - if (tx->u.tx.extra_frag) { - struct ieee80211_hdr *fhdr; - int i; - for (i = 0; i < tx->u.tx.num_extra_frag; i++) { - fhdr = (struct ieee80211_hdr *) - tx->u.tx.extra_frag[i]->data; - fhdr->frame_control |= cpu_to_le16(WLAN_FC_ISWEP); - } - } -} - - -static ieee80211_txrx_result -ieee80211_tx_h_wep_encrypt(struct ieee80211_txrx_data *tx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; - u16 fc; - - fc = le16_to_cpu(hdr->frame_control); - - if (!tx->key || tx->key->alg != ALG_WEP || - (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_DATA && - (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || - WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_AUTH))) - return TXRX_CONTINUE; - - tx->u.tx.control->iv_len = WEP_IV_LEN; - tx->u.tx.control->icv_len = WEP_ICV_LEN; - ieee80211_tx_set_iswep(tx); - - if (wep_encrypt_skb(tx, tx->skb) < 0) { - I802_DEBUG_INC(tx->local->tx_handlers_drop_wep); - return TXRX_DROP; - } - - if (tx->u.tx.extra_frag) { - int i; - for (i = 0; i < tx->u.tx.num_extra_frag; i++) { - if (wep_encrypt_skb(tx, tx->u.tx.extra_frag[i]) < 0) { - I802_DEBUG_INC(tx->local-> - tx_handlers_drop_wep); - return TXRX_DROP; - } - } - } - - return TXRX_CONTINUE; -} - - -static inline int ceiling_div(int dividend, int divisor) -{ - return ((dividend + divisor - 1) / divisor); -} - - -static int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, - int rate, int erp, int short_preamble) -{ - int dur; - - /* calculate duration (in microseconds, rounded up to next higher - * integer if it includes a fractional microsecond) to send frame of - * len bytes (does not include FCS) at the given rate. Duration will - * also include SIFS. - * - * rate is in 100 kbps, so divident is multiplied by 10 in the - * ceiling_div() operations. - */ - - if (local->conf.phymode == MODE_IEEE80211A || erp || - local->conf.phymode == MODE_ATHEROS_TURBO) { - /* - * OFDM: - * - * N_DBPS = DATARATE x 4 - * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS) - * (16 = SIGNAL time, 6 = tail bits) - * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext - * - * T_SYM = 4 usec - * 802.11a - 17.5.2: aSIFSTime = 16 usec - * 802.11g - 19.8.4: aSIFSTime = 10 usec + - * signal ext = 6 usec - */ - /* FIX: Atheros Turbo may have different (shorter) duration? */ - dur = 16; /* SIFS + signal ext */ - dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */ - dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */ - dur += 4 * ceiling_div((16 + 8 * (len + 4) + 6) * 10, - 4 * rate); /* T_SYM x N_SYM */ - } else { - /* - * 802.11b or 802.11g with 802.11b compatibility: - * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime + - * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0. - * - * 802.11 (DS): 15.3.3, 802.11b: 18.3.4 - * aSIFSTime = 10 usec - * aPreambleLength = 144 usec or 72 usec with short preamble - * aPLCPHeaderLength = 48 ms or 24 ms with short preamble - */ - dur = 10; /* aSIFSTime = 10 usec */ - dur += short_preamble ? (72 + 24) : (144 + 48); - - dur += ceiling_div(8 * (len + 4) * 10, rate); - } - - return dur; -} - - -static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr, - int next_frag_len) -{ - int rate, mrate, erp, dur, i; - struct ieee80211_rate *txrate = tx->u.tx.rate; - struct ieee80211_local *local = tx->local; - - erp = txrate->flags & IEEE80211_RATE_ERP; - - /* - * data and mgmt (except PS Poll): - * - during CFP: 32768 - * - during contention period: - * if addr1 is group address: 0 - * if more fragments = 0 and addr1 is individual address: time to - * transmit one ACK plus SIFS - * if more fragments = 1 and addr1 is individual address: time to - * transmit next fragment plus 2 x ACK plus 3 x SIFS - * - * IEEE 802.11, 9.6: - * - control response frame (CTS or ACK) shall be transmitted using the - * same rate as the immediately previous frame in the frame exchange - * sequence, if this rate belongs to the PHY mandatory rates, or else - * at the highest possible rate belonging to the PHY rates in the - * BSSBasicRateSet - */ - - if (WLAN_FC_GET_TYPE(tx->fc) == WLAN_FC_TYPE_CTRL) { - /* TODO: These control frames are not currently sent by - * 80211.o, but should they be implemented, this function - * needs to be updated to support duration field calculation. - * - * RTS: time needed to transmit pending data/mgmt frame plus - * one CTS frame plus one ACK frame plus 3 x SIFS - * CTS: duration of immediately previous RTS minus time - * required to transmit CTS and its SIFS - * ACK: 0 if immediately previous directed data/mgmt had - * more=0, with more=1 duration in ACK frame is duration - * from previous frame minus time needed to transmit ACK - * and its SIFS - * PS Poll: BIT(15) | BIT(14) | aid - */ - return 0; - } - - /* data/mgmt */ - if (0 /* FIX: data/mgmt during CFP */) - return 32768; - - if (group_addr) /* Group address as the destination - no ACK */ - return 0; - - /* Individual destination address: - * IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes) - * CTS and ACK frames shall be transmitted using the highest rate in - * basic rate set that is less than or equal to the rate of the - * immediately previous frame and that is using the same modulation - * (CCK or OFDM). If no basic rate set matches with these requirements, - * the highest mandatory rate of the PHY that is less than or equal to - * the rate of the previous frame is used. - * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps - */ - rate = -1; - mrate = 10; /* use 1 Mbps if everything fails */ - for (i = 0; i < local->num_curr_rates; i++) { - struct ieee80211_rate *r = &local->curr_rates[i]; - if (r->rate > txrate->rate) - break; - - if (IEEE80211_RATE_MODULATION(txrate->flags) != - IEEE80211_RATE_MODULATION(r->flags)) - continue; - - if (r->flags & IEEE80211_RATE_BASIC) - rate = r->rate; - else if (r->flags & IEEE80211_RATE_MANDATORY) - mrate = r->rate; - } - if (rate == -1) { - /* No matching basic rate found; use highest suitable mandatory - * PHY rate */ - rate = mrate; - } - - /* Time needed to transmit ACK - * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up - * to closest integer */ - - dur = ieee80211_frame_duration(local, 10, rate, erp, - local->short_preamble); - - if (next_frag_len) { - /* Frame is fragmented: duration increases with time needed to - * transmit next fragment plus ACK and 2 x SIFS. */ - dur *= 2; /* ACK + SIFS */ - /* next fragment */ - dur += ieee80211_frame_duration(local, next_frag_len, - txrate->rate, erp, - local->short_preamble); - } - - return dur; -} - - -static ieee80211_txrx_result -ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; - u16 dur; - struct ieee80211_tx_control *control = tx->u.tx.control; - - if (!MULTICAST_ADDR(hdr->addr1)) { - if (tx->skb->len >= tx->local->rts_threshold && - tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD) { - control->use_rts_cts = 1; - control->retry_limit = - tx->local->long_retry_limit; - } else { - control->retry_limit = - tx->local->short_retry_limit; - } - } else { - control->retry_limit = 1; - } - - if (tx->fragmented) { - /* Do not use multiple retry rates when sending fragmented - * frames. - * TODO: The last fragment could still use multiple retry - * rates. */ -// control->alt_retry_rate = -1; - } - - /* Use CTS protection for unicast frames sent using extended rates if - * there are associated non-ERP stations and RTS/CTS is not configured - * for the frame. */ - if (tx->local->conf.phymode == MODE_IEEE80211G && - (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) && - tx->u.tx.unicast && - tx->local->cts_protect_erp_frames && - !control->use_rts_cts) - control->use_cts_protect = 1; - - - /* Setup duration field for the first fragment of the frame. Duration - * for remaining fragments will be updated when they are being sent - * to low-level driver in ieee80211_tx(). */ - dur = ieee80211_duration(tx, MULTICAST_ADDR(hdr->addr1), - tx->fragmented ? tx->u.tx.extra_frag[0]->len : - 0); - hdr->duration_id = cpu_to_le16(dur); - - if (control->use_rts_cts || control->use_cts_protect) { - struct ieee80211_rate *rate; - int erp = tx->u.tx.rate->flags & IEEE80211_RATE_ERP; - - /* Do not use multiple retry rates when using RTS/CTS */ -// control->alt_retry_rate = -1; - - /* Use min(data rate, max base rate) as CTS/RTS rate */ - rate = tx->u.tx.rate; - while (rate > tx->local->curr_rates && - !(rate->flags & IEEE80211_RATE_BASIC)) - rate--; - - - if (control->use_rts_cts) - dur += ieee80211_frame_duration(tx->local, 10, - rate->rate, erp, - tx->local-> - short_preamble); - dur += ieee80211_frame_duration(tx->local, tx->skb->len, - tx->u.tx.rate->rate, erp, - tx->u.tx.short_preamble); - control->rts_cts_duration = dur; - control->rts_cts_rate = rate->val; - } - - if (tx->sta) { - tx->sta->tx_packets++; - tx->sta->tx_fragments++; - tx->sta->tx_bytes += tx->skb->len; - if (tx->u.tx.extra_frag) { - int i; - tx->sta->tx_fragments += tx->u.tx.num_extra_frag; - for (i = 0; i < tx->u.tx.num_extra_frag; i++) { - tx->sta->tx_bytes += - tx->u.tx.extra_frag[i]->len; - } - } - } - tx->local->scan.txrx_count++; - - return TXRX_CONTINUE; -} - - -static void ieee80211_rate_limit(unsigned long data) -{ - struct ieee80211_local *local = (struct ieee80211_local *) data; - - if (local->rate_limit) { - local->rate_limit_bucket += local->rate_limit; - if (local->rate_limit_bucket > local->rate_limit_burst) - local->rate_limit_bucket = local->rate_limit_burst; - local->rate_limit_timer.expires = jiffies + HZ; - add_timer(&local->rate_limit_timer); - } - -} - -static ieee80211_txrx_result -ieee80211_tx_h_rate_limit(struct ieee80211_txrx_data *tx) -{ - - if (likely(!tx->local->rate_limit || tx->u.tx.unicast)) - return TXRX_CONTINUE; - - /* rate limit */ - if (tx->local->rate_limit_bucket) { - tx->local->rate_limit_bucket--; - return TXRX_CONTINUE; - } - - I802_DEBUG_INC(tx->local->tx_handlers_drop_rate_limit); - return TXRX_DROP; -} - - - -static ieee80211_txrx_result -ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx) -{ -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - struct sk_buff *skb = tx->skb; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - u32 sta_flags; - - if (unlikely(tx->local->sta_scanning != 0) && - (WLAN_FC_GET_TYPE(tx->fc) != WLAN_FC_TYPE_MGMT || - WLAN_FC_GET_STYPE(tx->fc) != WLAN_FC_STYPE_PROBE_REQ)) - return TXRX_DROP; - - if (tx->u.tx.ps_buffered) - return TXRX_CONTINUE; - - sta_flags = tx->sta ? tx->sta->flags : 0; - - if (likely(tx->u.tx.unicast)) { - if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && - tx->local->conf.mode != IW_MODE_ADHOC && - WLAN_FC_GET_TYPE(tx->fc) == WLAN_FC_TYPE_DATA)) { -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: dropped data frame to not " - "associated station " MACSTR "\n", - tx->dev->name, MAC2STR(hdr->addr1)); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); - return TXRX_DROP; - } - } else { - if (unlikely(WLAN_FC_GET_TYPE(tx->fc) == WLAN_FC_TYPE_DATA && - tx->local->num_sta == 0 && - !tx->local->allow_broadcast_always && - tx->local->conf.mode != IW_MODE_ADHOC)) { - /* - * No associated STAs - no need to send multicast - * frames. - */ - return TXRX_DROP; - } - return TXRX_CONTINUE; - } - - if (unlikely(!tx->u.tx.mgmt_interface && tx->sdata->ieee802_1x && - !(sta_flags & WLAN_STA_AUTHORIZED))) { -#ifdef CONFIG_IEEE80211_DEBUG - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) tx->skb->data; - printk(KERN_DEBUG "%s: dropped frame to " MACSTR - " (unauthorized port)\n", tx->dev->name, - MAC2STR(hdr->addr1)); -#endif - I802_DEBUG_INC(tx->local->tx_handlers_drop_unauth_port); - return TXRX_DROP; - } - - return TXRX_CONTINUE; -} - - -/* This function is called whenever the AP is about to exceed the maximum limit - * of buffered frames for power saving STAs. This situation should not really - * happen often during normal operation, so dropping the oldest buffered packet - * from each queue should be OK to make some room for new frames. */ -static void purge_old_ps_buffers(struct ieee80211_local *local) -{ - int total = 0, purged = 0; - struct sk_buff *skb; - struct list_head *ptr; - - spin_lock_bh(&local->sub_if_lock); - list_for_each(ptr, &local->sub_if_list) { - struct ieee80211_if_norm *norm; - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - if (sdata->dev == local->mdev || - sdata->type != IEEE80211_SUB_IF_TYPE_NORM) - continue; - norm = &sdata->u.norm; - skb = skb_dequeue(&norm->ps_bc_buf); - if (skb) { - purged++; - dev_kfree_skb(skb); - } - total += skb_queue_len(&norm->ps_bc_buf); - } - spin_unlock_bh(&local->sub_if_lock); - - spin_lock_bh(&local->sta_lock); - list_for_each(ptr, &local->sta_list) { - struct sta_info *sta = - list_entry(ptr, struct sta_info, list); - skb = skb_dequeue(&sta->ps_tx_buf); - if (skb) { - purged++; - dev_kfree_skb(skb); - } - total += skb_queue_len(&sta->ps_tx_buf); - } - spin_unlock_bh(&local->sta_lock); - - local->total_ps_buffered = total; - printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n", - local->mdev->name, purged); -} - - -static inline ieee80211_txrx_result -ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx) -{ - /* broadcast/multicast frame */ - /* If any of the associated stations is in power save mode, - * the frame is buffered to be sent after DTIM beacon frame */ - if (tx->local->hw->host_broadcast_ps_buffering && - tx->sdata->type != IEEE80211_SUB_IF_TYPE_WDS && - tx->sdata->bss && atomic_read(&tx->sdata->bss->num_sta_ps) && - !(tx->fc & WLAN_FC_ORDER)) { - if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) - purge_old_ps_buffers(tx->local); - if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= - AP_MAX_BC_BUFFER) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: BC TX buffer full - " - "dropping the oldest frame\n", - tx->dev->name); - } - dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); - } else - tx->local->total_ps_buffered++; - skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb); - return TXRX_QUEUED; - } - - return TXRX_CONTINUE; -} - - -static inline ieee80211_txrx_result -ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx) -{ - struct sta_info *sta = tx->sta; - - if (unlikely(!sta || - (WLAN_FC_GET_TYPE(tx->fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(tx->fc) == WLAN_FC_STYPE_PROBE_RESP))) - return TXRX_CONTINUE; - - if (unlikely((sta->flags & WLAN_STA_PS) && !sta->pspoll)) { - struct ieee80211_tx_packet_data *pkt_data; -#ifdef IEEE80211_VERBOSE_DEBUG_PS - printk(KERN_DEBUG "STA " MACSTR " aid %d: PS buffer (entries " - "before %d)\n", - MAC2STR(sta->addr), sta->aid, - skb_queue_len(&sta->ps_tx_buf)); -#endif /* IEEE80211_VERBOSE_DEBUG_PS */ - sta->flags |= WLAN_STA_TIM; - if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) - purge_old_ps_buffers(tx->local); - if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) { - struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf); - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: STA " MACSTR " TX " - "buffer full - dropping oldest frame\n", - tx->dev->name, MAC2STR(sta->addr)); - } - dev_kfree_skb(old); - } else - tx->local->total_ps_buffered++; - /* Queue frame to be sent after STA sends an PS Poll frame */ - if (skb_queue_empty(&sta->ps_tx_buf) && tx->local->hw->set_tim) - tx->local->hw->set_tim(tx->dev, sta->aid, 1); - pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb; - pkt_data->jiffies = jiffies; - skb_queue_tail(&sta->ps_tx_buf, tx->skb); - return TXRX_QUEUED; - } -#ifdef IEEE80211_VERBOSE_DEBUG_PS - else if (unlikely(sta->flags & WLAN_STA_PS)) { - printk(KERN_DEBUG "%s: STA " MACSTR " in PS mode, but pspoll " - "set -> send frame\n", tx->dev->name, - MAC2STR(sta->addr)); - } -#endif /* IEEE80211_VERBOSE_DEBUG_PS */ - sta->pspoll = 0; - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) -{ - if (unlikely(tx->u.tx.ps_buffered)) - return TXRX_CONTINUE; - - if (tx->u.tx.unicast) - return ieee80211_tx_h_unicast_ps_buf(tx); - else - return ieee80211_tx_h_multicast_ps_buf(tx); -} - - -static void inline ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, - struct sk_buff *skb, - struct net_device *dev, - struct ieee80211_tx_control *control) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_tx_packet_data *pkt_data; - int hdrlen; - - pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; - - memset(tx, 0, sizeof(*tx)); - tx->skb = skb; - tx->dev = pkt_data->sdata->dev; /* use original interface */ - tx->local = local; - tx->sdata = pkt_data->sdata; - tx->sta = sta_info_get(local, hdr->addr1); - tx->fc = le16_to_cpu(hdr->frame_control); - control->power_level = local->conf.power_level; - tx->u.tx.control = control; - tx->u.tx.unicast = !MULTICAST_ADDR(hdr->addr1); - control->no_ack = MULTICAST_ADDR(hdr->addr1); - tx->fragmented = local->fragmentation_threshold < - IEEE80211_MAX_FRAG_THRESHOLD && tx->u.tx.unicast && - skb->len + 4 /* FCS */ > local->fragmentation_threshold && - (local->hw->set_frag_threshold == NULL); - if (tx->sta == NULL) - control->clear_dst_mask = 1; - else if (tx->sta->clear_dst_mask) { - control->clear_dst_mask = 1; - tx->sta->clear_dst_mask = 0; - } - control->antenna_sel = local->conf.antenna_sel; - if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta) - control->antenna_sel = tx->sta->antenna_sel; - hdrlen = ieee80211_get_hdrlen(tx->fc); - if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { - u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; - tx->ethertype = (pos[0] << 8) | pos[1]; - } - -} - - -static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_tx_control *control, int mgmt) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - ieee80211_tx_handler *handler; - struct ieee80211_txrx_data tx; - ieee80211_txrx_result res = TXRX_DROP; - int ret, i; - - if (unlikely(skb->len < 10)) { - dev_kfree_skb(skb); - return 0; - } - - ieee80211_tx_prepare(&tx, skb, dev, control); - sta = tx.sta; - tx.u.tx.mgmt_interface = mgmt; - - for (handler = local->tx_handlers; *handler != NULL; handler++) { - res = (*handler)(&tx); - if (res != TXRX_CONTINUE) - break; - } - - skb = tx.skb; /* handlers are allowed to change skb */ - - if (sta) - sta_info_release(local, sta); - - if (unlikely(res == TXRX_DROP)) { - I802_DEBUG_INC(local->tx_handlers_drop); - goto drop; - } - - if (unlikely(res == TXRX_QUEUED)) { - I802_DEBUG_INC(local->tx_handlers_queued); - return 0; - } - - ieee80211_dump_frame(dev->name, "TX to low-level driver", skb); - ret = local->hw->tx(dev, skb, control); -#ifdef IEEE80211_LEDS - if (!ret && local->tx_led_counter++ == 0) { - ieee80211_tx_led(1, dev); - } -#endif /* IEEE80211_LEDS */ - if (tx.u.tx.extra_frag) { - if (ret > 0) { - /* Must free all fragments and return 0 since skb data - * has been fragmented into multiple buffers. - * TODO: could free extra fragments and restore skb to - * the original form since the data is still there and - * then return nonzero so that Linux netif would - * retry. */ - goto drop; - } - - skb = NULL; /* skb is now owned by low-level driver */ - control->use_rts_cts = 0; - control->use_cts_protect = 0; - control->clear_dst_mask = 0; - for (i = 0; i < tx.u.tx.num_extra_frag; i++) { - int next_len, dur; - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) - tx.u.tx.extra_frag[i]->data; - if (i + 1 < tx.u.tx.num_extra_frag) - next_len = tx.u.tx.extra_frag[i + 1]->len; - else { - next_len = 0; - tx.u.tx.rate = tx.u.tx.last_frag_rate; - tx.u.tx.control->tx_rate = tx.u.tx.rate->val; -// tx.u.tx.control->rateidx = -// tx.u.tx.last_frag_rateidx; - tx.u.tx.control->rate_ctrl_probe = - tx.u.tx.probe_last_frag; - } - dur = ieee80211_duration(&tx, 0, next_len); - hdr->duration_id = cpu_to_le16(dur); - - ieee80211_dump_frame(dev->name, - "TX to low-level driver", skb); - ret = local->hw->tx(dev, tx.u.tx.extra_frag[i], - control); - if (ret > 0) - goto drop; -#ifdef IEEE80211_LEDS - if (local->tx_led_counter++ == 0) { - ieee80211_tx_led(1, dev); - } -#endif /* IEEE80211_LEDS */ - tx.u.tx.extra_frag[i] = NULL; - } - kfree(tx.u.tx.extra_frag); - } - if (ret == -1) - ret = 0; - return ret; - - drop: - if (skb) - dev_kfree_skb(skb); - for (i = 0; i < tx.u.tx.num_extra_frag; i++) - if (tx.u.tx.extra_frag[i]) - dev_kfree_skb(tx.u.tx.extra_frag[i]); - kfree(tx.u.tx.extra_frag); - return 0; -} - - -static int ieee80211_master_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct ieee80211_tx_control control; - struct ieee80211_tx_packet_data *pkt_data; - struct ieee80211_sub_if_data *sdata; - int ret = 1; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - /* - * copy control out of the skb so other people can use skb->cb - */ - pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; - if (unlikely(pkt_data->magic != IEEE80211_CB_MAGIC)) { - printk(KERN_WARNING "%s: Someone messed with our skb->cb\n", - dev->name); - dev_kfree_skb(skb); - return 0; - } - memcpy(&control, &pkt_data->control, - sizeof(struct ieee80211_tx_control)); - - ret = ieee80211_tx(dev, skb, &control, - pkt_data->sdata->type == - IEEE80211_SUB_IF_TYPE_MGMT); - - return ret; -} - - -/** - * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type - * subinterfaces (wlan#, WDS, and VLAN interfaces) - * @skb: packet to be sent - * @dev: incoming interface - * - * Returns: 0 on success (and frees skb in this case) or 1 on failure (skb will - * not be freed, and caller is responsible for either retrying later or freeing - * skb). - * - * This function takes in an Ethernet header and encapsulates it with suitable - * IEEE 802.11 header based on which interface the packet is coming in. The - * encapsulated packet will then be passed to master interface, wlan#.11, for - * transmission (through low-level driver). - */ -static int ieee80211_subif_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct ieee80211_local *local = (struct ieee80211_local *) dev->priv; - struct ieee80211_tx_packet_data *pkt_data; - struct ieee80211_sub_if_data *sdata; - int ret = 1, head_need; - u16 ethertype, hdrlen, fc; - struct ieee80211_hdr hdr; - u8 *encaps_data; - int encaps_len, skip_header_bytes; - int nh_pos, h_pos, no_encrypt = 0; - struct sta_info *sta; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (unlikely(skb->len < ETH_HLEN)) { - printk(KERN_DEBUG "%s: short skb (len=%d)\n", - dev->name, skb->len); - ret = 0; - goto fail; - } - - nh_pos = skb->nh.raw - skb->data; - h_pos = skb->h.raw - skb->data; - - /* convert Ethernet header to proper 802.11 header (based on - * operation mode) */ - ethertype = (skb->data[12] << 8) | skb->data[13]; - /* TODO: handling for 802.1x authorized/unauthorized port */ - fc = (WLAN_FC_TYPE_DATA << 2) | (WLAN_FC_STYPE_DATA << 4); - - if (likely(sdata->type == IEEE80211_SUB_IF_TYPE_NORM || - sdata->type == IEEE80211_SUB_IF_TYPE_VLAN)) { - if (local->conf.mode == IW_MODE_MASTER) { - fc |= WLAN_FC_FROMDS; - /* DA BSSID SA */ - memcpy(hdr.addr1, skb->data, ETH_ALEN); - memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); - memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); - } else if (local->conf.mode == IW_MODE_INFRA) { - fc |= WLAN_FC_TODS; - /* BSSID SA DA */ - memcpy(hdr.addr1, local->bssid, ETH_ALEN); - memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); - memcpy(hdr.addr3, skb->data, ETH_ALEN); - } else if (local->conf.mode == IW_MODE_ADHOC) { - /* DA SA BSSID */ - memcpy(hdr.addr1, skb->data, ETH_ALEN); - memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); - memcpy(hdr.addr3, local->bssid, ETH_ALEN); - } - hdrlen = 24; - } else if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS) { - fc |= WLAN_FC_FROMDS | WLAN_FC_TODS; - /* RA TA DA SA */ - memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); - memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); - memcpy(hdr.addr3, skb->data, ETH_ALEN); - memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); - hdrlen = 30; - } else if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - if (local->conf.mode == IW_MODE_INFRA) { - fc |= WLAN_FC_TODS; - /* BSSID SA DA */ - memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); - memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); - memcpy(hdr.addr3, skb->data, ETH_ALEN); - } else { - /* DA SA BSSID */ - memcpy(hdr.addr1, skb->data, ETH_ALEN); - memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); - memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN); - } - hdrlen = 24; - } else { - ret = 0; - goto fail; - } - - /* receiver is QoS enabled, use a QoS type frame */ - sta = sta_info_get(local, hdr.addr1); - if (sta) { - if (sta->flags & WLAN_STA_WME) { - fc |= WLAN_FC_STYPE_QOS_DATA << 4; - hdrlen += 2; - } - sta_info_release(local, sta); - } - - hdr.frame_control = cpu_to_le16(fc); - hdr.duration_id = 0; - hdr.seq_ctrl = 0; - - skip_header_bytes = ETH_HLEN; - if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) { - encaps_data = bridge_tunnel_header; - encaps_len = sizeof(bridge_tunnel_header); - skip_header_bytes -= 2; - } else if (ethertype >= 0x600) { - encaps_data = rfc1042_header; - encaps_len = sizeof(rfc1042_header); - skip_header_bytes -= 2; - } else { - encaps_data = NULL; - encaps_len = 0; - } - - skb_pull(skb, skip_header_bytes); - nh_pos -= skip_header_bytes; - h_pos -= skip_header_bytes; - - /* TODO: implement support for fragments so that there is no need to - * reallocate and copy payload; it might be enough to support one - * extra fragment that would be copied in the beginning of the frame - * data.. anyway, it would be nice to include this into skb structure - * somehow - * - * There are few options for this: - * use skb->cb as an extra space for 802.11 header - * allocate new buffer if not enough headroom - * make sure that there is enough headroom in every skb by increasing - * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and - * alloc_skb() (net/core/skbuff.c) - */ - head_need = hdrlen + encaps_len + (local->hw->extra_hdr_room ? 2 : 0); - head_need -= skb_headroom(skb); - - /* We are going to modify skb data, so make a copy of it if happens to - * be cloned. This could happen, e.g., with Linux bridge code passing - * us broadcast frames. */ - - if (head_need > 0 || skb_cloned(skb)) { -#if 0 - printk(KERN_DEBUG "%s: need to reallocate buffer for %d bytes " - "of headroom\n", dev->name, head_need); -#endif - - if (skb_cloned(skb)) - I802_DEBUG_INC(local->tx_expand_skb_head_cloned); - else - I802_DEBUG_INC(local->tx_expand_skb_head); - /* Since we have to reallocate the buffer, make sure that there - * is enough room for possible WEP IV/ICV and TKIP (8 bytes - * before payload and 12 after). */ - if (pskb_expand_head(skb, (head_need > 0 ? head_need + 8 : 8), - 12, GFP_ATOMIC)) { - printk(KERN_DEBUG "%s: failed to reallocate TX buffer" - "\n", dev->name); - goto fail; - } - } - - if (encaps_data) { - memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len); - nh_pos += encaps_len; - h_pos += encaps_len; - } - memcpy(skb_push(skb, hdrlen), &hdr, hdrlen); - nh_pos += hdrlen; - h_pos += hdrlen; - - pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; - memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); - pkt_data->magic = IEEE80211_CB_MAGIC; - pkt_data->sdata = sdata; - pkt_data->control.do_not_encrypt = no_encrypt; - - skb->dev = sdata->master; - sdata->stats.tx_packets++; - sdata->stats.tx_bytes += skb->len; - - /* Update skb pointers to various headers since this modified frame - * is going to go through Linux networking code that may potentially - * need things like pointer to IP header. */ - skb->mac.raw = skb->data; - skb->nh.raw = skb->data + nh_pos; - skb->h.raw = skb->data + h_pos; - - - dev_queue_xmit(skb); - - return 0; - - fail: - if (!ret) - dev_kfree_skb(skb); - - return ret; -} - - -/* - * This is the transmit routine for the 802.11 type interfaces - * called by upper layers of the linux networking - * stack when it has a frame to transmit - */ -static int -ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct ieee80211_sub_if_data *sdata; - struct ieee80211_tx_packet_data *pkt_data; - struct ieee80211_hdr *hdr; - u16 fc; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (skb->len < 10) { - dev_kfree_skb(skb); - return 0; - } - - hdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(hdr->frame_control); - - pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; - memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); - pkt_data->magic = IEEE80211_CB_MAGIC; - pkt_data->sdata = sdata; - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) - pkt_data->control.pkt_type = PKT_PROBE_RESP; - - skb->priority = 20; /* use hardcode priority for mgmt TX queue */ - skb->dev = sdata->master; - - /* - * We're using the protocol field of the the frame control header - * to request TX callback for hostapd. BIT(1) is checked. - */ - if ((fc & BIT(1)) == BIT(1)) { - pkt_data->control.req_tx_status = 1; - fc &= ~BIT(1); - hdr->frame_control = cpu_to_le16(fc); - } - - - - pkt_data->control.do_not_encrypt = !(fc & WLAN_FC_ISWEP); - - sdata->stats.tx_packets++; - sdata->stats.tx_bytes += skb->len; - - dev_queue_xmit(skb); - - return 0; -} - - -static void ieee80211_beacon_add_tim(struct ieee80211_local *local, - struct ieee80211_if_norm *bss, - struct sk_buff *skb) -{ - u8 *pos, *tim; - int aid0 = 0; - int i, num_bits = 0, n1, n2; - u8 bitmap[251]; - - /* Generate bitmap for TIM only if there are any STAs in power save - * mode. */ - if (atomic_read(&bss->num_sta_ps) > 0 && bss->max_aid > 0) { - memset(bitmap, 0, sizeof(bitmap)); - spin_lock_bh(&local->sta_lock); - for (i = 0; i < bss->max_aid; i++) { - if (bss->sta_aid[i] && - (!skb_queue_empty(&bss->sta_aid[i]->ps_tx_buf) || - !skb_queue_empty(&bss->sta_aid[i]->tx_filtered))) - { - bitmap[(i + 1) / 8] |= 1 << (i + 1) % 8; - num_bits++; - } - } - spin_unlock_bh(&local->sta_lock); - } - - if (bss->dtim_count == 0) - bss->dtim_count = bss->dtim_period - 1; - else - bss->dtim_count--; - - tim = pos = (u8 *) skb_put(skb, 6); - *pos++ = WLAN_EID_TIM; - *pos++ = 4; - *pos++ = bss->dtim_count; - *pos++ = bss->dtim_period; - - if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) { - aid0 = 1; - } - - if (num_bits) { - /* Find largest even number N1 so that bits numbered 1 through - * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits - * (N2 + 1) x 8 through 2007 are 0. */ - n1 = 0; - for (i = 0; i < sizeof(bitmap); i++) { - if (bitmap[i]) { - n1 = i & 0xfe; - break; - } - } - n2 = n1; - for (i = sizeof(bitmap) - 1; i >= n1; i--) { - if (bitmap[i]) { - n2 = i; - break; - } - } - - /* Bitmap control */ - *pos++ = n1 | (aid0 ? 1 : 0); - /* Part Virt Bitmap */ - memcpy(pos, bitmap + n1, n2 - n1 + 1); - - tim[1] = n2 - n1 + 4; - skb_put(skb, n2 - n1); - } else { - *pos++ = aid0 ? 1 : 0; /* Bitmap control */ - *pos++ = 0; /* Part Virt Bitmap */ - } -} - - - - -struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int bss_idx, - struct ieee80211_tx_control *control) -{ - struct ieee80211_local *local = dev->priv; - struct sk_buff *skb; - struct net_device *bdev; - struct ieee80211_sub_if_data *sdata = NULL; - struct ieee80211_if_norm *norm = NULL; - struct ieee80211_rate *rate; - struct rate_control_extra extra; - u8 *b_head, *b_tail; - int bh_len, bt_len; - - - spin_lock_bh(&local->sub_if_lock); - if (bss_idx < 0 || bss_idx >= local->bss_dev_count) - bdev = NULL; - else { - bdev = local->bss_devs[bss_idx]; - sdata = IEEE80211_DEV_TO_SUB_IF(bdev); - norm = &sdata->u.norm; - } - spin_unlock_bh(&local->sub_if_lock); - - if (bdev == NULL || norm == NULL || norm->beacon_head == NULL) { -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - if (net_ratelimit()) - printk(KERN_DEBUG "no beacon data avail for idx=%d " - "(%s)\n", bss_idx, bdev ? bdev->name : "N/A"); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - return NULL; - } - - /* Assume we are generating the normal beacon locally */ - b_head = norm->beacon_head; - b_tail = norm->beacon_tail; - bh_len = norm->beacon_head_len; - bt_len = norm->beacon_tail_len; - - - skb = dev_alloc_skb(bh_len + bt_len + 256 /* maximum TIM len */); - if (!skb) - return NULL; - - memcpy(skb_put(skb, bh_len), b_head, bh_len); - - ieee80211_beacon_add_tim(local, norm, skb); - - if (b_tail) { - memcpy(skb_put(skb, bt_len), b_tail, bt_len); - } - - memset(&extra, 0, sizeof(extra)); - extra.endidx = local->num_curr_rates; - - - rate = rate_control_get_rate(dev, skb, &extra); - if (rate == NULL) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: ieee80211_beacon_get: no rate " - "found\n", dev->name); - } - dev_kfree_skb(skb); - return NULL; - } - - control->tx_rate = (local->short_preamble && - (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? - rate->val2 : rate->val; - control->antenna_sel = local->conf.antenna_sel; - control->power_level = local->conf.power_level; - control->no_ack = 1; - control->retry_limit = 1; - control->rts_cts_duration = 0; - control->clear_dst_mask = 1; - - - norm->num_beacons++; - return skb; -} - -struct sk_buff * -ieee80211_get_buffered_bc(struct net_device *dev, int bss_idx, - struct ieee80211_tx_control *control) -{ - struct ieee80211_local *local = dev->priv; - struct sk_buff *skb; - struct sta_info *sta; - ieee80211_tx_handler *handler; - struct ieee80211_txrx_data tx; - ieee80211_txrx_result res = TXRX_DROP; - struct net_device *bdev; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_norm *bss; - - - spin_lock_bh(&local->sub_if_lock); - if (bss_idx < 0 || bss_idx >= local->bss_dev_count) { - bdev = NULL; - bss = NULL; - } else { - bdev = local->bss_devs[bss_idx]; - sdata = IEEE80211_DEV_TO_SUB_IF(bdev); - bss = &sdata->u.norm; - } - spin_unlock_bh(&local->sub_if_lock); - if (bdev == NULL || bss == NULL || bss->beacon_head == NULL) - return NULL; - - if (bss->dtim_count != 0) - return NULL; /* send buffered bc/mc only after DTIM beacon */ - skb = skb_dequeue(&bss->ps_bc_buf); - memset(control, 0, sizeof(*control)); - if (skb == NULL) - return NULL; - local->total_ps_buffered--; - - if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - /* more buffered multicast/broadcast frames ==> set MoreData - * flag in IEEE 802.11 header to inform PS STAs */ - hdr->frame_control |= cpu_to_le16(WLAN_FC_MOREDATA); - } - - ieee80211_tx_prepare(&tx, skb, dev, control); - sta = tx.sta; - tx.u.tx.ps_buffered = 1; - - for (handler = local->tx_handlers; *handler != NULL; handler++) { - res = (*handler)(&tx); - if (res == TXRX_DROP || res == TXRX_QUEUED) - break; - } - - if (res == TXRX_DROP) { - I802_DEBUG_INC(local->tx_handlers_drop); - dev_kfree_skb(skb); - skb = NULL; - } else if (res == TXRX_QUEUED) { - I802_DEBUG_INC(local->tx_handlers_queued); - skb = NULL; - } - - if (sta) - sta_info_release(local, sta); - - return skb; -} - - -int ieee80211_hw_config(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - int i, ret = 0; - -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d mode=%d " - "phymode=%d\n", local->conf.channel, local->conf.freq, - local->conf.mode, local->conf.phymode); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - - if (local->hw->config) - ret = local->hw->config(dev, &local->conf); - - for (i = 0; i < local->hw->num_modes; i++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[i]; - if (mode->mode == local->conf.phymode) { - if (local->curr_rates != mode->rates) { - rate_control_clear(local); - } - local->curr_rates = mode->rates; - local->num_curr_rates = mode->num_rates; - ieee80211_prepare_rates(dev); - break; - } - } - - return ret; -} - - -struct ieee80211_conf *ieee80211_get_hw_conf(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - return &local->conf; -} - - -static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) -{ - /* FIX: what would be proper limits for MTU? - * This interface uses 802.3 frames. */ - if (new_mtu < 256 || new_mtu > 2304 - 24 - 6) { - printk(KERN_WARNING "%s: invalid MTU %d\n", - dev->name, new_mtu); - return -EINVAL; - } - -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - dev->mtu = new_mtu; - return 0; -} - - -static int ieee80211_change_mtu_apdev(struct net_device *dev, int new_mtu) -{ - /* FIX: what would be proper limits for MTU? - * This interface uses 802.11 frames. */ - if (new_mtu < 256 || new_mtu > 2304) { - printk(KERN_WARNING "%s: invalid MTU %d\n", - dev->name, new_mtu); - return -EINVAL; - } - -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - dev->mtu = new_mtu; - return 0; -} - - -static void ieee80211_tx_timeout(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - - printk(KERN_WARNING "%s: resetting interface.\n", dev->name); - - if (local->hw->reset(dev)) - printk(KERN_ERR "%s: failed to reset interface.\n", dev->name); - else - netif_wake_queue(dev); -} - - -static int ieee80211_set_mac_address(struct net_device *dev, void *addr) -{ - struct ieee80211_local *local = dev->priv; - struct sockaddr *a = addr; - struct list_head *ptr; - int res; - - if (!local->hw->set_mac_address) - return -EOPNOTSUPP; - - res = local->hw->set_mac_address(dev, addr); - if (res) - return res; - - list_for_each(ptr, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - memcpy(sdata->dev->dev_addr, a->sa_data, ETH_ALEN); - } - - return 0; -} - - -static struct net_device_stats *ieee80211_get_stats(struct net_device *dev) -{ - struct ieee80211_sub_if_data *sdata; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - return &(sdata->stats); -} - - -static int ieee80211_open(struct net_device *dev) -{ - struct ieee80211_sub_if_data *sdata; - struct ieee80211_local *local = dev->priv; - int res; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (local->open_count == 0) { - res = local->hw->open(sdata->master); - if (res) - return res; - ieee80211_init_scan(sdata->master); - } - local->open_count++; - - netif_start_queue(dev); - return 0; -} - - -static int ieee80211_stop(struct net_device *dev) -{ - struct ieee80211_sub_if_data *sdata; - struct ieee80211_local *local = dev->priv; - int res; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - netif_stop_queue(dev); - - local->open_count--; - if (local->open_count == 0) { - ieee80211_stop_scan(sdata->master); - res = local->hw->stop(sdata->master); - if (res) - return res; - } - - return 0; -} - - -static int header_parse_80211(struct sk_buff *skb, unsigned char *haddr) -{ - memcpy(haddr, skb->mac.raw + 10, ETH_ALEN); /* addr2 */ - return ETH_ALEN; -} - - -static struct net_device * -ieee80211_get_wds_dev(struct ieee80211_local *local, u8 *addr) -{ - struct list_head *ptr; - - list_for_each(ptr, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS && - memcmp(addr, sdata->u.wds.remote_addr, ETH_ALEN) == 0) - return sdata->dev; - } - - return NULL; -} - - -static struct net_device * ieee80211_own_bssid(struct ieee80211_local *local, - u8 *addr) -{ - int i; - struct net_device *dev = NULL; - - spin_lock_bh(&local->sub_if_lock); - for (i = 0; i < local->bss_dev_count; i++) { - if ((memcmp(local->bss_devs[i]->dev_addr, addr, ETH_ALEN) == 0) - ) { - dev = local->bss_devs[i]; - break; - } - } - spin_unlock_bh(&local->sub_if_lock); - - return dev; -} - - - - -static struct net_device * ieee80211_sta_bssid(struct ieee80211_local *local, - u8 *addr, u8 *a1, - int *sta_multicast) -{ - struct list_head *ptr; - int multicast; - u8 *own_addr = local->mdev->dev_addr; - - multicast = a1[0] & 0x01; - - /* Try O(1) lookup for a common case of only one AP being used. */ - if (own_addr[0] == a1[0] && own_addr[1] == a1[1] && - own_addr[2] == a1[2]) { - int index = (((int) a1[3] << 16) | ((int) a1[4] << 8) | a1[5]) - - (((int) own_addr[3] << 16) | - ((int) own_addr[4] << 8) | own_addr[5]); - if (index >= 0 && index < local->conf.bss_count && - local->sta_devs[index]) { - struct net_device *dev = local->sta_devs[index]; - struct ieee80211_sub_if_data *sdata; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (memcmp(addr, sdata->u.sta.bssid, ETH_ALEN) == 0) { - *sta_multicast = multicast; - return dev; - } - } - } - - if (!multicast) - return NULL; - - /* Could not find station interface, resort to O(n) lookup. */ - list_for_each(ptr, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - continue; - if (!multicast && - memcmp(a1, sdata->dev->dev_addr, ETH_ALEN) != 0) - continue; - - if (memcmp(addr, sdata->u.sta.bssid, ETH_ALEN) == 0 || - (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0 && - local->conf.mode == IW_MODE_ADHOC)) { - *sta_multicast = multicast; - return sdata->dev; - } - } - - return NULL; -} - - -static int ieee80211_own_addr(struct net_device *dev, u8 *addr) -{ - struct ieee80211_local *local = dev->priv; - u8 *own = dev->dev_addr; - int index; - - /* Optimization: assume that BSSID mask does not change for first - * three octets. */ - if (own[0] != addr[0] || own[1] != addr[1] || own[2] != addr[2]) - return 0; - - index = (((int) addr[3] << 16) | ((int) addr[4] << 8) | addr[5]) - - (((int) own[3] << 16) | ((int) own[4] << 8) | own[5]); - if (index >= 0 && index < local->conf.bss_count && - local->sta_devs[index]) - return 1; - - return 0; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) -{ - struct net_device *dev = rx->dev; - struct ieee80211_local *local = rx->local; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - u16 fc, hdrlen, ethertype; - u8 *payload; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - struct sk_buff *skb = rx->skb, *skb2; - struct ieee80211_sub_if_data *sdata; - - fc = rx->fc; - if (unlikely(WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_DATA)) - return TXRX_CONTINUE; - - if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) - return TXRX_DROP; - - hdrlen = ieee80211_get_hdrlen(fc); - - /* convert IEEE 802.11 header + possible LLC headers into Ethernet - * header - * IEEE 802.11 address fields: - * ToDS FromDS Addr1 Addr2 Addr3 Addr4 - * 0 0 DA SA BSSID n/a - * 0 1 DA BSSID SA n/a - * 1 0 BSSID SA DA n/a - * 1 1 RA TA DA SA - */ - - switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) { - case WLAN_FC_TODS: - /* BSSID SA DA */ - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - - if (unlikely(local->conf.mode != IW_MODE_MASTER || - !ieee80211_own_bssid(local, hdr->addr1))) { - printk(KERN_DEBUG "%s: dropped ToDS frame (BSSID=" - MACSTR " SA=" MACSTR " DA=" MACSTR ")\n", - dev->name, MAC2STR(hdr->addr1), - MAC2STR(hdr->addr2), MAC2STR(hdr->addr3)); - return TXRX_DROP; - } - break; - case (WLAN_FC_TODS | WLAN_FC_FROMDS): - /* RA TA DA SA */ - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr4, ETH_ALEN); - - dev = ieee80211_get_wds_dev(local, hdr->addr2); - if (!dev || memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) != 0) { - printk(KERN_DEBUG "%s: dropped FromDS&ToDS frame (RA=" - MACSTR " TA=" MACSTR " DA=" MACSTR " SA=" - MACSTR ")\n", - rx->dev->name, MAC2STR(hdr->addr1), - MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), - MAC2STR(hdr->addr4)); - return TXRX_DROP; - } - break; - case WLAN_FC_FROMDS: - /* DA BSSID SA */ - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr3, ETH_ALEN); - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA || - memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0 || - memcmp(hdr->addr2, sdata->u.sta.bssid, ETH_ALEN) != 0) { - return TXRX_DROP; - } - break; - case 0: - /* DA SA BSSID */ - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - - if (local->conf.mode != IW_MODE_ADHOC || - memcmp(hdr->addr3, local->bssid, ETH_ALEN) != 0) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: dropped IBSS frame (DA=" - MACSTR " SA=" MACSTR " BSSID=" MACSTR - ")\n", - dev->name, MAC2STR(hdr->addr1), - MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3)); - } - return TXRX_DROP; - } - break; - } - - payload = skb->data + hdrlen; - - if (unlikely(skb->len - hdrlen < 8)) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: RX too short data frame " - "payload\n", dev->name); - } - return TXRX_DROP; - } - - ethertype = (payload[6] << 8) | payload[7]; - - if (likely((memcmp(payload, rfc1042_header, 6) == 0 && - ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || - memcmp(payload, bridge_tunnel_header, 6) == 0)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ - skb_pull(skb, hdrlen + 6); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } else { - struct ethhdr *ehdr; - unsigned short len; - skb_pull(skb, hdrlen); - len = htons(skb->len); - ehdr = (struct ethhdr *)skb_push(skb, sizeof(struct ethhdr)); - memcpy(ehdr->h_dest, dst, ETH_ALEN); - memcpy(ehdr->h_source, src, ETH_ALEN); - ehdr->h_proto = len; - } - - if (rx->sta && !rx->sta->assoc_ap && - !(rx->sta && (rx->sta->flags & WLAN_STA_WDS))) - skb->dev = rx->sta->dev; - else - skb->dev = dev; - - skb2 = NULL; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - /* - * don't count the master since the low level code - * counts it already for us. - */ - if (skb->dev != sdata->master) { - sdata->stats.rx_packets++; - sdata->stats.rx_bytes += skb->len; - } - - if (local->bridge_packets && sdata->type != IEEE80211_SUB_IF_TYPE_WDS - && sdata->type != IEEE80211_SUB_IF_TYPE_STA) { - if (MULTICAST_ADDR(skb->data)) { - /* send multicast frames both to higher layers in - * local net stack and back to the wireless media */ - skb2 = skb_copy(skb, GFP_ATOMIC); - if (skb2 == NULL) - printk(KERN_DEBUG "%s: failed to clone " - "multicast frame\n", dev->name); - } else { - struct sta_info *dsta; - dsta = sta_info_get(local, skb->data); - if (dsta && dsta->dev == NULL) { - printk(KERN_DEBUG "Station with null dev " - "structure!\n"); - } else if (dsta && dsta->dev == dev) { - /* Destination station is associated to this - * AP, so send the frame directly to it and - * do not pass the frame to local net stack. - */ - skb2 = skb; - skb = NULL; - } - if (dsta) - sta_info_release(local, dsta); - } - } - - if (skb) { - /* deliver to local stack */ - skb->protocol = eth_type_trans(skb, dev); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); - } - - if (skb2) { - /* send to wireless media */ - skb2->protocol = __constant_htons(ETH_P_802_3); - skb2->mac.raw = skb2->nh.raw = skb2->data; - dev_queue_xmit(skb2); - } - - return TXRX_QUEUED; -} - - -static struct ieee80211_rate * -ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate) -{ - int m, r; - - for (m = 0; m < local->hw->num_modes; m++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[m]; - if (mode->mode != phymode) - continue; - for (r = 0; r < mode->num_rates; r++) { - struct ieee80211_rate *rate = &mode->rates[r]; - if (rate->val == hw_rate || - (rate->flags & IEEE80211_RATE_PREAMBLE2 && - rate->val2 == hw_rate)) - return rate; - } - } - - return NULL; -} - - -void -ieee80211_rx_mgmt(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *status, u32 msg_type) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_frame_info *fi; - size_t hlen; - struct ieee80211_sub_if_data *sdata; - - dev = local->apdev; - skb->dev = dev; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (skb_headroom(skb) < sizeof(struct ieee80211_frame_info)) { - I802_DEBUG_INC(local->rx_expand_skb_head); - if (pskb_expand_head(skb, sizeof(struct ieee80211_frame_info), - 0, GFP_ATOMIC)) { - dev_kfree_skb(skb); - return; - } - } - - hlen = sizeof(struct ieee80211_frame_info); - if (msg_type == ieee80211_msg_monitor) - hlen -= sizeof(fi->msg_type); - - fi = (struct ieee80211_frame_info *) skb_push(skb, hlen); - memset(fi, 0, hlen); - if (msg_type != ieee80211_msg_monitor) - fi->msg_type = htonl(msg_type); - fi->version = htonl(IEEE80211_FI_VERSION); - fi->length = htonl(hlen); - if (status) { -// struct timespec ts; - struct ieee80211_rate *rate; - -#if 0 - jiffies_to_timespec(status->hosttime, &ts); - fi->hosttime = cpu_to_be64(ts.tv_sec * 1000000 + - ts.tv_nsec / 1000); - fi->mactime = cpu_to_be64(status->mactime); -#endif - switch (status->phymode) { - case MODE_IEEE80211A: - fi->phytype = htonl(ieee80211_phytype_ofdm_dot11_a); - break; - case MODE_IEEE80211B: - fi->phytype = htonl(ieee80211_phytype_dsss_dot11_b); - break; - case MODE_IEEE80211G: - fi->phytype = htonl(ieee80211_phytype_pbcc_dot11_g); - break; - case MODE_ATHEROS_TURBO: - fi->phytype = - htonl(ieee80211_phytype_dsss_dot11_turbo); - break; - default: - fi->phytype = 0xAAAAAAAA; - break; - } - fi->channel = htonl(status->channel); - rate = ieee80211_get_rate(local, status->phymode, - status->rate); - if (rate) { - fi->datarate = htonl(rate->rate); - if (rate->flags & IEEE80211_RATE_PREAMBLE2) { - if (status->rate == rate->val) - fi->preamble = htonl(2); /* long */ - else if (status->rate == rate->val2) - fi->preamble = htonl(1); /* short */ - } else - fi->preamble = htonl(0); - } else { - fi->datarate = htonl(0); - fi->preamble = htonl(0); - } - - fi->antenna = htonl(status->antenna); - fi->priority = 0xffffffff; /* no clue */ - fi->ssi_type = htonl(ieee80211_ssi_raw); - fi->ssi_signal = htonl(status->ssi); - fi->ssi_noise = 0x00000000; - fi->encoding = 0; - } else { - fi->ssi_type = htonl(ieee80211_ssi_none); - } - - sdata->stats.rx_packets++; - sdata->stats.rx_bytes += skb->len; - - skb->mac.raw = skb->data; - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_802_2); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); -} - - -int ieee80211_radar_status(struct net_device *dev, int channel, int radar, - int radar_type) -{ - struct sk_buff *skb; - struct ieee80211_radar_info *msg; - - skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) + - sizeof(struct ieee80211_radar_info)); - - if (skb == NULL) - return -ENOMEM; - skb_reserve(skb, sizeof(struct ieee80211_frame_info)); - - msg = (struct ieee80211_radar_info *) - skb_put(skb, sizeof(struct ieee80211_radar_info)); - msg->channel = channel; - msg->radar = radar; - msg->radar_type = radar_type; - - ieee80211_rx_mgmt(dev, skb, 0, ieee80211_msg_radar); - return 0; -} - - -int ieee80211_set_aid_for_sta(struct net_device *dev, u8 *peer_address, - u16 aid) -{ - struct sk_buff *skb; - struct ieee80211_msg_set_aid_for_sta *msg; - - skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) + - sizeof(struct ieee80211_msg_set_aid_for_sta)); - - if (skb == NULL) - return -ENOMEM; - skb_reserve(skb, sizeof(struct ieee80211_frame_info)); - - msg = (struct ieee80211_msg_set_aid_for_sta *) - skb_put(skb, sizeof(struct ieee80211_msg_set_aid_for_sta)); - memcpy(msg->sta_address, peer_address, ETH_ALEN); - msg->aid = aid; - - ieee80211_rx_mgmt(dev, skb, 0, ieee80211_msg_set_aid_for_sta); - return 0; -} - - -static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata; - sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); - - if (sdata->bss) - atomic_inc(&sdata->bss->num_sta_ps); - sta->flags |= WLAN_STA_PS; - sta->pspoll = 0; -#ifdef IEEE80211_VERBOSE_DEBUG_PS - printk(KERN_DEBUG "%s: STA " MACSTR " aid %d enters power " - "save mode\n", dev->name, MAC2STR(sta->addr), sta->aid); -#endif /* IEEE80211_VERBOSE_DEBUG_PS */ -} - - -static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) -{ - struct ieee80211_local *local = dev->priv; - struct sk_buff *skb; - int sent = 0; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_tx_packet_data *pkt_data; - - sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); - if (sdata->bss) - atomic_dec(&sdata->bss->num_sta_ps); - sta->flags &= ~(WLAN_STA_PS | WLAN_STA_TIM); - sta->pspoll = 0; - if (!skb_queue_empty(&sta->ps_tx_buf) && local->hw->set_tim) - local->hw->set_tim(dev, sta->aid, 0); -#ifdef IEEE80211_VERBOSE_DEBUG_PS - printk(KERN_DEBUG "%s: STA " MACSTR " aid %d exits power " - "save mode\n", dev->name, MAC2STR(sta->addr), sta->aid); -#endif /* IEEE80211_VERBOSE_DEBUG_PS */ - /* Send all buffered frames to the station */ - while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { - pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; - sent++; - pkt_data->control.requeue = 1; - dev_queue_xmit(skb); - } - while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { - pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; - local->total_ps_buffered--; - sent++; -#ifdef IEEE80211_VERBOSE_DEBUG_PS - printk(KERN_DEBUG "%s: STA " MACSTR " aid %d send PS frame " - "since STA not sleeping anymore\n", dev->name, - MAC2STR(sta->addr), sta->aid); -#endif /* IEEE80211_VERBOSE_DEBUG_PS */ - pkt_data->control.requeue = 1; - dev_queue_xmit(skb); - } - - return sent; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx) -{ - struct sk_buff *skb; - int no_pending_pkts; - - if (likely(!rx->sta || WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_CTRL || - WLAN_FC_GET_STYPE(rx->fc) != WLAN_FC_STYPE_PSPOLL)) - return TXRX_CONTINUE; - - skb = skb_dequeue(&rx->sta->tx_filtered); - if (skb == NULL) { - skb = skb_dequeue(&rx->sta->ps_tx_buf); - if (skb) - rx->local->total_ps_buffered--; - } - no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) && - skb_queue_empty(&rx->sta->ps_tx_buf); - - if (skb) { - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) skb->data; - - /* tell TX path to send one frame even though the STA may - * still remain is PS mode after this frame exchange */ - rx->sta->pspoll = 1; - -#ifdef IEEE80211_VERBOSE_DEBUG_PS - printk(KERN_DEBUG "STA " MACSTR " aid %d: PS Poll (entries " - "after %d)\n", - MAC2STR(rx->sta->addr), rx->sta->aid, - skb_queue_len(&rx->sta->ps_tx_buf)); -#endif /* IEEE80211_VERBOSE_DEBUG_PS */ - - /* Use MoreData flag to indicate whether there are more - * buffered frames for this STA */ - if (no_pending_pkts) { - hdr->frame_control &= cpu_to_le16(~WLAN_FC_MOREDATA); - rx->sta->flags &= ~WLAN_STA_TIM; - } else - hdr->frame_control |= cpu_to_le16(WLAN_FC_MOREDATA); - - dev_queue_xmit(skb); - - if (no_pending_pkts && rx->local->hw->set_tim) - rx->local->hw->set_tim(rx->dev, rx->sta->aid, 0); -#ifdef IEEE80211_VERBOSE_DEBUG_PS - } else if (!rx->u.rx.sent_ps_buffered) { - printk(KERN_DEBUG "%s: STA " MACSTR " sent PS Poll even " - "though there is no buffered frames for it\n", - rx->dev->name, MAC2STR(rx->sta->addr)); -#endif /* IEEE80211_VERBOSE_DEBUG_PS */ - - } - - /* Free PS Poll skb here instead of returning TXRX_DROP that would - * count as an dropped frame. */ - dev_kfree_skb(rx->skb); - - return TXRX_QUEUED; -} - - -static inline struct ieee80211_fragment_entry * -ieee80211_reassemble_add(struct ieee80211_local *local, - unsigned int frag, unsigned int seq, int rx_queue, - struct sk_buff **skb) -{ - struct ieee80211_fragment_entry *entry; - int idx; - - idx = local->fragment_next; - entry = &local->fragments[local->fragment_next++]; - if (local->fragment_next >= IEEE80211_FRAGMENT_MAX) - local->fragment_next = 0; - - if (entry->skb) { -#ifdef CONFIG_IEEE80211_DEBUG - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) entry->skb->data; - printk(KERN_DEBUG "%s: RX reassembly removed oldest " - "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " - "addr1=" MACSTR " addr2=" MACSTR "\n", - local->mdev->name, idx, - jiffies - entry->first_frag_time, entry->seq, - entry->last_frag, MAC2STR(hdr->addr1), - MAC2STR(hdr->addr2)); -#endif /* CONFIG_IEEE80211_DEBUG */ - dev_kfree_skb(entry->skb); - } - - entry->skb = *skb; - *skb = NULL; - entry->first_frag_time = jiffies; - entry->seq = seq; - entry->rx_queue = rx_queue; - entry->last_frag = frag; - entry->ccmp = 0; - - return entry; -} - - -static inline struct ieee80211_fragment_entry * -ieee80211_reassemble_find(struct ieee80211_local *local, - u16 fc, unsigned int frag, unsigned int seq, - int rx_queue, struct ieee80211_hdr *hdr) -{ - struct ieee80211_fragment_entry *entry; - int i, idx; - - idx = local->fragment_next; - for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { - struct ieee80211_hdr *f_hdr; - u16 f_fc; - - idx--; - if (idx < 0) - idx = IEEE80211_FRAGMENT_MAX - 1; - - entry = &local->fragments[idx]; - if (!entry->skb || entry->seq != seq || - entry->rx_queue != rx_queue || - entry->last_frag + 1 != frag) - continue; - - f_hdr = (struct ieee80211_hdr *) entry->skb->data; - f_fc = le16_to_cpu(f_hdr->frame_control); - - if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_GET_TYPE(f_fc) || - memcmp(hdr->addr1, f_hdr->addr1, ETH_ALEN) != 0 || - memcmp(hdr->addr2, f_hdr->addr2, ETH_ALEN) != 0) - continue; - - if (entry->first_frag_time + 2 * HZ < jiffies) { - dev_kfree_skb(entry->skb); - entry->skb = NULL; - continue; - } - return entry; - } - - return NULL; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx) -{ - struct ieee80211_hdr *hdr; - u16 sc; - unsigned int frag, seq; - struct ieee80211_fragment_entry *entry; - - hdr = (struct ieee80211_hdr *) rx->skb->data; - sc = le16_to_cpu(hdr->seq_ctrl); - frag = WLAN_GET_SEQ_FRAG(sc); - - if (likely((!(rx->fc & WLAN_FC_MOREFRAG) && frag == 0) || - (rx->skb)->len < 24 || MULTICAST_ADDR(hdr->addr1))) { - /* not fragmented */ - goto out; - } - I802_DEBUG_INC(rx->local->rx_handlers_fragments); - - seq = WLAN_GET_SEQ_SEQ(sc); - - if (frag == 0) { - /* This is the first fragment of a new frame. */ - entry = ieee80211_reassemble_add(rx->local, frag, seq, - rx->u.rx.queue, &(rx->skb)); - if (rx->key && rx->key->alg == ALG_CCMP && - (rx->fc & WLAN_FC_ISWEP)) { - /* Store CCMP PN so that we can verify that the next - * fragment has a sequential PN value. */ - entry->ccmp = 1; - memcpy(entry->last_pn, - rx->key->u.ccmp.rx_pn[rx->u.rx.queue], - CCMP_PN_LEN); - } - return TXRX_QUEUED; - } - - /* This is a fragment for a frame that should already be pending in - * fragment cache. Add this fragment to the end of the pending entry. - */ - entry = ieee80211_reassemble_find(rx->local, rx->fc, frag, seq, - rx->u.rx.queue, hdr); - if (!entry) { - I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); - return TXRX_DROP; - } - - /* Verify that MPDUs within one MSDU have sequential PN values. - * (IEEE 802.11i, 8.3.3.4.5) */ - if (entry->ccmp) { - int i; - u8 pn[CCMP_PN_LEN], *rpn; - if (rx->key == NULL || rx->key->alg != ALG_CCMP) - return TXRX_DROP; - memcpy(pn, entry->last_pn, CCMP_PN_LEN); - for (i = CCMP_PN_LEN - 1; i >= 0; i--) { - pn[i]++; - if (pn[i]) - break; - } - rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue]; - if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) { - printk(KERN_DEBUG "%s: defrag: CCMP PN not sequential" - " A2=" MACSTR " PN=%02x%02x%02x%02x%02x%02x " - "(expected %02x%02x%02x%02x%02x%02x)\n", - rx->dev->name, MAC2STR(hdr->addr2), - rpn[0], rpn[1], rpn[2], rpn[3], rpn[4], rpn[5], - pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]); - return TXRX_DROP; - } - memcpy(entry->last_pn, pn, CCMP_PN_LEN); - } - - /* TODO: could gather list of skb's and reallocate data buffer only - * after finding out the total length of the frame */ - skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc)); - if (skb_tailroom(entry->skb) < rx->skb->len) { - I802_DEBUG_INC(rx->local->rx_expand_skb_head2); - if (unlikely(pskb_expand_head(entry->skb, 0, rx->skb->len, - GFP_ATOMIC))) { - I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); - return TXRX_DROP; - } - } - memcpy(skb_put(entry->skb, rx->skb->len), rx->skb->data, rx->skb->len); - entry->last_frag = frag; - dev_kfree_skb(rx->skb); - - if (rx->fc & WLAN_FC_MOREFRAG) { - rx->skb = NULL; - return TXRX_QUEUED; - } - - /* Complete frame has been reassembled - process it now */ - rx->skb = entry->skb; - rx->fragmented = 1; - entry->skb = NULL; - - out: - if (rx->sta) - rx->sta->rx_packets++; - if (MULTICAST_ADDR(hdr->addr1)) - rx->local->dot11MulticastReceivedFrameCount++; -#ifdef IEEE80211_LEDS - else - ieee80211_rx_led(2, rx->dev); -#endif /* IEEE80211_LEDS */ - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx) -{ - if (rx->local->conf.mode == IW_MODE_MONITOR) { - ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status, - ieee80211_msg_monitor); - return TXRX_QUEUED; - } - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_check(struct ieee80211_txrx_data *rx) -{ - struct ieee80211_hdr *hdr; - int always_sta_key; - hdr = (struct ieee80211_hdr *) rx->skb->data; - - /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ - if (rx->sta && !MULTICAST_ADDR(hdr->addr1)) { - if (unlikely(rx->fc & WLAN_FC_RETRY && - rx->sta->last_seq_ctrl[rx->u.rx.queue] == - hdr->seq_ctrl)) { - rx->local->dot11FrameDuplicateCount++; - rx->sta->num_duplicates++; - return TXRX_DROP; - } else - rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl; - } - - if (rx->local->hw->rx_includes_fcs && rx->skb->len > FCS_LEN) - skb_trim(rx->skb, rx->skb->len - FCS_LEN); - - if (unlikely(rx->skb->len < 16)) { - I802_DEBUG_INC(rx->local->rx_handlers_drop_short); - return TXRX_DROP; - } - - /* Filter out foreign unicast packets when in promiscuous mode. - * FIX: Filter out multicast to foreign BSSID. */ - if (rx->local->conf.mode == IW_MODE_INFRA && - !MULTICAST_ADDR(hdr->addr1) && - !ieee80211_own_addr(rx->dev, hdr->addr1)) - return TXRX_DROP; - - /* Drop disallowed frame classes based on STA auth/assoc state; - * IEEE 802.11, Chap 5.5. - * - * 80211.o does filtering only based on association state, i.e., it - * drops Class 3 frames from not associated stations. hostapd sends - * deauth/disassoc frames when needed. In addition, hostapd is - * responsible for filtering on both auth and assoc states. - */ - if (unlikely((WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_DATA || - (WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_CTRL && - WLAN_FC_GET_STYPE(rx->fc) == WLAN_FC_STYPE_PSPOLL)) && - rx->local->conf.mode != IW_MODE_ADHOC && - (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) { - if (!(rx->fc & WLAN_FC_FROMDS) && !(rx->fc & WLAN_FC_TODS)) { - /* Drop IBSS frames silently. */ - return TXRX_DROP; - } - - ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status, - ieee80211_msg_sta_not_assoc); - return TXRX_QUEUED; - } - - if (rx->local->conf.mode == IW_MODE_INFRA) - always_sta_key = 0; - else - always_sta_key = 1; - - if (rx->sta && rx->sta->key && always_sta_key) { - rx->key = rx->sta->key; - } else { - if (!rx->sdata) { - printk(KERN_DEBUG "%s: sdata was null in packet!!\n", - rx->dev->name); - printk(KERN_DEBUG "%s: Addr1: " MACSTR "\n", - rx->dev->name, MAC2STR(hdr->addr1)); - printk(KERN_DEBUG "%s: Addr2: " MACSTR "\n", - rx->dev->name, MAC2STR(hdr->addr2)); - printk(KERN_DEBUG "%s: Addr3: " MACSTR "\n", - rx->dev->name, MAC2STR(hdr->addr3)); - return TXRX_DROP; - } - if (rx->sta && rx->sta->key) - rx->key = rx->sta->key; - else - rx->key = rx->sdata->default_key; - - if (rx->local->hw->wep_include_iv && - rx->fc & WLAN_FC_ISWEP) { - int keyidx = ieee80211_wep_get_keyidx(rx->skb); - - if (keyidx >= 0 && keyidx < NUM_DEFAULT_KEYS && - (rx->sta == NULL || rx->sta->key == NULL || - keyidx > 0)) { - rx->key = rx->sdata->keys[keyidx]; - } - if (!rx->key) { - printk(KERN_DEBUG "%s: RX WEP frame with " - "unknown keyidx %d (A1=" MACSTR " A2=" - MACSTR " A3=" MACSTR ")\n", - rx->dev->name, keyidx, - MAC2STR(hdr->addr1), - MAC2STR(hdr->addr2), - MAC2STR(hdr->addr3)); - ieee80211_rx_mgmt( - rx->dev, rx->skb, rx->u.rx.status, - ieee80211_msg_wep_frame_unknown_key); - return TXRX_QUEUED; - } - } - } - - if (rx->fc & WLAN_FC_ISWEP && rx->key) { - rx->key->tx_rx_count++; - if (unlikely(rx->local->key_tx_rx_threshold && - rx->key->tx_rx_count > - rx->local->key_tx_rx_threshold)) { - ieee80211_key_threshold_notify(rx->dev, rx->key, - rx->sta); - } - } - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx) -{ - struct sta_info *sta = rx->sta; - struct net_device *dev = rx->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - - if (!sta) - return TXRX_CONTINUE; - - /* Update last_rx only for IBSS packets which are for the current - * BSSID to avoid keeping the current IBSS network alive in cases where - * other STAs are using different BSSID. */ - if (rx->local->conf.mode == IW_MODE_ADHOC) { - u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len); - if (memcmp(bssid, rx->local->bssid, ETH_ALEN) == 0) - sta->last_rx = jiffies; - } else - if (!MULTICAST_ADDR(hdr->addr1) || - rx->local->conf.mode == IW_MODE_INFRA) { - /* Update last_rx only for unicast frames in order to prevent - * the Probe Request frames (the only broadcast frames from a - * STA in infrastructure mode) from keeping a connection alive. - */ - sta->last_rx = jiffies; - } - sta->rx_fragments++; - sta->rx_bytes += rx->skb->len; - sta->last_rssi = rx->u.rx.status->ssi; - - if (!(rx->fc & WLAN_FC_MOREFRAG)) { - /* Change STA power saving mode only in the end of a frame - * exchange sequence */ - if ((sta->flags & WLAN_STA_PS) && !(rx->fc & WLAN_FC_PWRMGT)) - rx->u.rx.sent_ps_buffered += ap_sta_ps_end(dev, sta); - else if (!(sta->flags & WLAN_STA_PS) && - (rx->fc & WLAN_FC_PWRMGT)) - ap_sta_ps_start(dev, sta); - } - - /* Drop data::nullfunc frames silently, since they are used only to - * control station power saving mode. */ - if (WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_DATA && - WLAN_FC_GET_STYPE(rx->fc) == WLAN_FC_STYPE_NULLFUNC) { - I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); - /* Update counter and free packet here to avoid counting this - * as a dropped packed. */ - sta->rx_packets++; - dev_kfree_skb(rx->skb); - return TXRX_QUEUED; - } - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx) -{ - if (!rx->sta || !(rx->fc & WLAN_FC_ISWEP) || - WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_DATA || !rx->key || - rx->key->alg != ALG_WEP) - return TXRX_CONTINUE; - - /* Check for weak IVs, if hwaccel did not remove IV from the frame */ - if (rx->local->hw->wep_include_iv || - rx->key->force_sw_encrypt || rx->local->conf.sw_decrypt) { - u8 *iv = ieee80211_wep_is_weak_iv(rx->skb, rx->key); - if (iv) { - rx->sta->wep_weak_iv_count++; - } - } - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_wep_decrypt(struct ieee80211_txrx_data *rx) -{ - /* If the device handles decryption totally, skip this test */ - if (rx->local->hw->device_hides_wep) - return TXRX_CONTINUE; - - if ((rx->key && rx->key->alg != ALG_WEP) || - !(rx->fc & WLAN_FC_ISWEP) || - (WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_DATA && - (WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_MGMT || - WLAN_FC_GET_STYPE(rx->fc) != WLAN_FC_STYPE_AUTH))) - return TXRX_CONTINUE; - - if (!rx->key) { - printk(KERN_DEBUG "%s: RX WEP frame, but no key set\n", - rx->dev->name); - return TXRX_DROP; - } - - if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED) || - rx->key->force_sw_encrypt || rx->local->conf.sw_decrypt) { - if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) { - printk(KERN_DEBUG "%s: RX WEP frame, decrypt " - "failed\n", rx->dev->name); - return TXRX_DROP; - } - } else if (rx->local->hw->wep_include_iv) { - ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); - /* remove ICV */ - skb_trim(rx->skb, rx->skb->len - 4); - } - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx) -{ - if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) && - rx->local->conf.mode != IW_MODE_INFRA) { - /* Pass both encrypted and unencrypted EAPOL frames to user - * space for processing. */ - ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status, - ieee80211_msg_normal); - return TXRX_QUEUED; - } - - if (unlikely(rx->sdata->ieee802_1x && - WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_DATA && - WLAN_FC_GET_STYPE(rx->fc) != WLAN_FC_STYPE_NULLFUNC && - (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) && - !ieee80211_is_eapol(rx->skb))) { -#ifdef CONFIG_IEEE80211_DEBUG - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) rx->skb->data; - printk(KERN_DEBUG "%s: dropped frame from " MACSTR - " (unauthorized port)\n", rx->dev->name, - MAC2STR(hdr->addr2)); -#endif /* CONFIG_IEEE80211_DEBUG */ - return TXRX_DROP; - } - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx) -{ - /* If the device handles decryption totally, skip this test */ - if (rx->local->hw->device_hides_wep) - return TXRX_CONTINUE; - - /* Drop unencrypted frames if key is set. */ - if (unlikely(!(rx->fc & WLAN_FC_ISWEP) && - WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_DATA && - WLAN_FC_GET_STYPE(rx->fc) != WLAN_FC_STYPE_NULLFUNC && - (rx->key || rx->sdata->drop_unencrypted) && - (rx->sdata->eapol == 0 || - !ieee80211_is_eapol(rx->skb)))) { - printk(KERN_DEBUG "%s: RX non-WEP frame, but expected " - "encryption\n", rx->dev->name); - return TXRX_DROP; - } - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx) -{ - struct ieee80211_sub_if_data *sdata; - sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status); - } else { - /* Management frames are sent to hostapd for processing */ - ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status, - ieee80211_msg_normal); - } - return TXRX_QUEUED; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx) -{ - struct ieee80211_local *local = rx->local; - struct sk_buff *skb = rx->skb; - - if (unlikely(local->sta_scanning != 0)) { - ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status); - return TXRX_QUEUED; - } - - if (WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_DATA) - local->scan.txrx_count++; - if (unlikely(local->scan.in_scan != 0 && - rx->u.rx.status->freq == local->scan.freq)) { - struct ieee80211_hdr *hdr; - u16 fc; - - local->scan.rx_packets++; - - hdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(hdr->frame_control); - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) { - local->scan.rx_beacon++; - /* Need to trim FCS here because it is normally - * removed only after this passive scan handler. */ - if (rx->local->hw->rx_includes_fcs && - rx->skb->len > FCS_LEN) - skb_trim(rx->skb, rx->skb->len - FCS_LEN); - - ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status, - ieee80211_msg_passive_scan); - return TXRX_QUEUED; - } else { - I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); - return TXRX_DROP; - } - } - - return TXRX_CONTINUE; -} - - -static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len) -{ - u16 fc; - - if (len < 24) - return NULL; - - fc = le16_to_cpu(hdr->frame_control); - - switch (WLAN_FC_GET_TYPE(fc)) { - case WLAN_FC_TYPE_DATA: - switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) { - case WLAN_FC_TODS: - return hdr->addr1; - case (WLAN_FC_TODS | WLAN_FC_FROMDS): - return NULL; - case WLAN_FC_FROMDS: - return hdr->addr2; - case 0: - return hdr->addr3; - } - break; - case WLAN_FC_TYPE_MGMT: - return hdr->addr3; - case WLAN_FC_TYPE_CTRL: - if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PSPOLL) - return hdr->addr1; - else - return NULL; - } - - return NULL; -} - - -static struct net_device * ieee80211_get_rx_dev(struct ieee80211_local *local, - struct ieee80211_hdr *hdr, - size_t len, int *sta_broadcast) -{ - u8 *bssid; - struct net_device *dev; - u16 fc; - - bssid = ieee80211_get_bssid(hdr, len); - if (bssid) { - dev = ieee80211_own_bssid(local, bssid); - if (!dev && (local->conf.mode == IW_MODE_INFRA || - local->conf.mode == IW_MODE_ADHOC)) - dev = ieee80211_sta_bssid(local, bssid, hdr->addr1, - sta_broadcast); - if (dev) - return dev; - } - - if (len >= 30) { - fc = le16_to_cpu(hdr->frame_control); - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA && - (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == - (WLAN_FC_TODS | WLAN_FC_FROMDS)) { - dev = ieee80211_get_wds_dev(local, hdr->addr2); - if (dev) - return dev; - } - } - - /* Default to default device if nothing else matches */ - return local->wdev; -} - - -static void ieee80211_rx_michael_mic_report(struct net_device *dev, - struct ieee80211_hdr *hdr, - struct sta_info *sta, - struct ieee80211_txrx_data *rx) -{ - int keyidx, hdrlen; - - hdrlen = ieee80211_get_hdrlen_from_skb(rx->skb); - if (rx->skb->len >= hdrlen + 4) - keyidx = rx->skb->data[hdrlen + 3] >> 6; - else - keyidx = -1; - - /* TODO: verify that this is not triggered by fragmented - * frames (hw does not verify MIC for them). */ - printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC " - "failure from " MACSTR " to " MACSTR " keyidx=%d\n", - dev->name, MAC2STR(hdr->addr2), MAC2STR(hdr->addr1), keyidx); - - if (sta == NULL) { - /* Some hardware versions seem to generate incorrect - * Michael MIC reports; ignore them to avoid triggering - * countermeasures. */ - printk(KERN_DEBUG "%s: ignored spurious Michael MIC " - "error for unknown address " MACSTR "\n", - dev->name, MAC2STR(hdr->addr2)); - goto ignore; - } - - if (!(rx->fc & WLAN_FC_ISWEP)) { - printk(KERN_DEBUG "%s: ignored spurious Michael MIC " - "error for a frame with no ISWEP flag (src " - MACSTR ")\n", dev->name, MAC2STR(hdr->addr2)); - goto ignore; - } - - if (rx->local->hw->wep_include_iv && - rx->local->conf.mode == IW_MODE_MASTER) { - int keyidx = ieee80211_wep_get_keyidx(rx->skb); - /* AP with Pairwise keys support should never receive Michael - * MIC errors for non-zero keyidx because these are reserved - * for group keys and only the AP is sending real multicast - * frames in BSS. */ - if (keyidx) { - printk(KERN_DEBUG "%s: ignored Michael MIC error for " - "a frame with non-zero keyidx (%d) (src " MACSTR - ")\n", dev->name, keyidx, MAC2STR(hdr->addr2)); - goto ignore; - } - } - - if (WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_DATA && - (WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_MGMT || - WLAN_FC_GET_STYPE(rx->fc) != WLAN_FC_STYPE_AUTH)) { - printk(KERN_DEBUG "%s: ignored spurious Michael MIC " - "error for a frame that cannot be encrypted " - "(fc=0x%04x) (src " MACSTR ")\n", - dev->name, rx->fc, MAC2STR(hdr->addr2)); - goto ignore; - } - - do { - union iwreq_data wrqu; - char *buf = kmalloc(128, GFP_ATOMIC); - if (buf == NULL) - break; - - /* TODO: needed parameters: count, key type, TSC */ - sprintf(buf, "MLME-MICHAELMICFAILURE.indication(" - "keyid=%d %scast addr=" MACSTR ")", - keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni", - MAC2STR(hdr->addr2)); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = strlen(buf); - wireless_send_event(rx->dev, IWEVCUSTOM, &wrqu, buf); - kfree(buf); - } while (0); - - /* TODO: consider verifying the MIC error report with software - * implementation if we get too many spurious reports from the - * hardware. */ - ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status, - ieee80211_msg_michael_mic_failure); - return; - - ignore: - dev_kfree_skb(rx->skb); - rx->skb = NULL; -} - - -static void ieee80211_sta_rx_broadcast(struct ieee80211_txrx_data *rx) -{ - struct ieee80211_local *local = rx->dev->priv; - u8 *_bssid, bssid[ETH_ALEN]; - struct sk_buff *orig_skb = rx->skb, *skb; - struct ieee80211_hdr *hdr; - ieee80211_rx_handler *handler; - ieee80211_txrx_result res; - struct list_head *ptr; - - hdr = (struct ieee80211_hdr *) orig_skb->data; - _bssid = ieee80211_get_bssid(hdr, orig_skb->len); - if (_bssid == NULL) { - dev_kfree_skb(orig_skb); - return; - } - memcpy(bssid, _bssid, ETH_ALEN); - - list_for_each(ptr, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA || - (memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) != 0 && - !(bssid[0] & 0x01))) - continue; - - skb = skb_copy(orig_skb, GFP_ATOMIC); - if (skb == NULL) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: failed to copy " - "multicast frame for %s", - rx->dev->name, sdata->dev->name); - } - continue; - } - - hdr = (struct ieee80211_hdr *) skb->data; - rx->skb = skb; - rx->dev = sdata->dev; - rx->sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); - - res = TXRX_DROP; - for (handler = local->rx_handlers; *handler != NULL; handler++) - { - res = (*handler)(rx); - if (res == TXRX_DROP || res == TXRX_QUEUED) - break; - } - - if (res == TXRX_DROP || *handler == NULL) - dev_kfree_skb(skb); - } - - dev_kfree_skb(orig_skb); -} - - -/* - * This is the receive path handler. It is called by a low level driver when an - * 802.11 MPDU is received from the hardware. - */ -void ieee80211_rx(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *status) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - struct ieee80211_hdr *hdr; - ieee80211_rx_handler *handler; - struct ieee80211_txrx_data rx; - ieee80211_txrx_result res = TXRX_DROP; - u16 type; - int sta_broadcast = 0; - - hdr = (struct ieee80211_hdr *) skb->data; - memset(&rx, 0, sizeof(rx)); - rx.skb = skb; - rx.local = local; - if (skb->len >= 16) { - sta = rx.sta = sta_info_get(local, hdr->addr2); - if (unlikely(sta == NULL && - local->conf.mode == IW_MODE_ADHOC)) { - u8 *bssid = ieee80211_get_bssid(hdr, skb->len); - if (bssid && - memcmp(bssid, local->bssid, ETH_ALEN) == 0) - sta = rx.sta = - ieee80211_ibss_add_sta(dev, skb, bssid, - hdr->addr2); - } - } else - sta = rx.sta = NULL; - if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS)) - rx.dev = sta->dev; - else - rx.dev = ieee80211_get_rx_dev(local, hdr, skb->len, - &sta_broadcast); - - rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev); - rx.u.rx.status = status; - rx.fc = skb->len >= 2 ? le16_to_cpu(hdr->frame_control) : 0; - type = WLAN_FC_GET_TYPE(rx.fc); - if (type == WLAN_FC_TYPE_DATA || type == WLAN_FC_TYPE_MGMT) - local->dot11ReceivedFragmentCount++; - if (sta_broadcast) { - ieee80211_sta_rx_broadcast(&rx); - goto end; - } - - if ((status->flag & RX_FLAG_MMIC_ERROR)) { - ieee80211_rx_michael_mic_report(dev, hdr, sta, &rx); - goto end; - } - - for (handler = local->rx_handlers; *handler != NULL; handler++) { - res = (*handler)(&rx); - if (res != TXRX_CONTINUE) { - if (res == TXRX_DROP) { - I802_DEBUG_INC(local->rx_handlers_drop); - if (sta) - sta->rx_dropped++; - } - if (res == TXRX_QUEUED) - I802_DEBUG_INC(local->rx_handlers_queued); - break; - } - } - - if (res == TXRX_DROP || *handler == NULL) - dev_kfree_skb(skb); - - end: - if (sta) - sta_info_release(local, sta); -} - - -static ieee80211_txrx_result -ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx) -{ - struct ieee80211_local *local = tx->local; - struct sk_buff *skb = tx->skb; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u32 load = 0, hdrtime; - - /* TODO: this could be part of tx_status handling, so that the number - * of retries would be known; TX rate should in that case be stored - * somewhere with the packet */ - - /* Estimate total channel use caused by this frame */ - - /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values, - * 1 usec = 1/8 * (1080 / 10) = 13.5 */ - - if (local->conf.phymode == MODE_IEEE80211A || - local->conf.phymode == MODE_ATHEROS_TURBO || - local->conf.phymode == MODE_ATHEROS_TURBOG || - (local->conf.phymode == MODE_IEEE80211G && - tx->u.tx.rate->flags & IEEE80211_RATE_ERP)) - hdrtime = CHAN_UTIL_HDR_SHORT; - else - hdrtime = CHAN_UTIL_HDR_LONG; - - load = hdrtime; - if (!MULTICAST_ADDR(hdr->addr1)) - load += hdrtime; - - if (tx->u.tx.control->use_rts_cts) - load += 2 * hdrtime; - else if (tx->u.tx.control->use_cts_protect) - load += hdrtime; - - load += skb->len * tx->u.tx.rate->rate_inv; - - if (tx->u.tx.extra_frag) { - int i; - for (i = 0; i < tx->u.tx.num_extra_frag; i++) { - load += 2 * hdrtime; - load += tx->u.tx.extra_frag[i]->len * - tx->u.tx.rate->rate; - } - } - - /* Divide channel_use by 8 to avoid wrapping around the counter */ - load >>= CHAN_UTIL_SHIFT; - local->channel_use_raw += load; - if (tx->sta) - tx->sta->channel_use_raw += load; - tx->sdata->channel_use_raw += load; - - return TXRX_CONTINUE; -} - - -static ieee80211_txrx_result -ieee80211_rx_h_load_stats(struct ieee80211_txrx_data *rx) -{ - struct ieee80211_local *local = rx->local; - struct sk_buff *skb = rx->skb; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u32 load = 0, hdrtime; - struct ieee80211_rate *rate; - int i; - - /* Estimate total channel use caused by this frame */ - - if (unlikely(local->num_curr_rates < 0)) - return TXRX_CONTINUE; - - rate = &local->curr_rates[0]; - for (i = 0; i < local->num_curr_rates; i++) { - if (local->curr_rates[i].val == rx->u.rx.status->rate) { - rate = &local->curr_rates[i]; - break; - } - } - - /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values, - * 1 usec = 1/8 * (1080 / 10) = 13.5 */ - - if (local->conf.phymode == MODE_IEEE80211A || - local->conf.phymode == MODE_ATHEROS_TURBO || - local->conf.phymode == MODE_ATHEROS_TURBOG || - (local->conf.phymode == MODE_IEEE80211G && - rate->flags & IEEE80211_RATE_ERP)) - hdrtime = CHAN_UTIL_HDR_SHORT; - else - hdrtime = CHAN_UTIL_HDR_LONG; - - load = hdrtime; - if (!MULTICAST_ADDR(hdr->addr1)) - load += hdrtime; - - load += skb->len * rate->rate_inv; - - /* Divide channel_use by 8 to avoid wrapping around the counter */ - load >>= CHAN_UTIL_SHIFT; - local->channel_use_raw += load; - if (rx->sta) - rx->sta->channel_use_raw += load; - rx->sdata->channel_use_raw += load; - - return TXRX_CONTINUE; -} - - -static void ieee80211_stat_refresh(unsigned long data) -{ - struct ieee80211_local *local = (struct ieee80211_local *) data; - struct list_head *ptr, *n; - - if (!local->stat_time) - return; - - /* go through all stations */ - spin_lock_bh(&local->sta_lock); - list_for_each(ptr, &local->sta_list) { - struct sta_info *sta = - list_entry(ptr, struct sta_info, list); - sta->channel_use = (sta->channel_use_raw / local->stat_time) / - CHAN_UTIL_PER_10MS; - sta->channel_use_raw = 0; - } - spin_unlock_bh(&local->sta_lock); - - /* go through all subinterfaces */ - list_for_each_safe(ptr, n, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - sdata->channel_use = (sdata->channel_use_raw / - local->stat_time) / CHAN_UTIL_PER_10MS; - sdata->channel_use_raw = 0; - - } - - /* hardware interface */ - local->channel_use = (local->channel_use_raw / - local->stat_time) / CHAN_UTIL_PER_10MS; - local->channel_use_raw = 0; - - local->stat_timer.expires = jiffies + HZ * local->stat_time / 100; - add_timer(&local->stat_timer); -} - - -/* This is a version of the rx handler that can be called from hard irq - * context. Post the skb on the queue and schedule the tasklet */ -void ieee80211_rx_irqsafe(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *status) -{ - struct ieee80211_local *local = dev->priv; - - skb->dev = dev; - memcpy(skb->cb, status, sizeof(struct ieee80211_rx_status)); - skb->pkt_type = ieee80211_rx_msg; - skb_queue_tail(&local->skb_queue, skb); - tasklet_schedule(&local->tasklet); -} - - -void ieee80211_tx_status_irqsafe(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_tx_status *status) -{ - struct ieee80211_local *local = dev->priv; - int tmp; - - if (status->tx_filtered || status->excessive_retries) { - /* Need to save a copy of skb->cb somewhere. Storing it in the - * end of the data might not be the most efficient way of doing - * this (since it may require reallocation of packet data), but - * should be good enough for now since tx_filtered or - * excessive_retries should not be triggered that often. */ - if (skb_is_nonlinear(skb)) { - if (skb_linearize(skb, GFP_ATOMIC)) { - printk(KERN_DEBUG "%s: Failed to linearize " - "skb\n", dev->name); - dev_kfree_skb_irq(skb); - return; - } - } - if (skb_tailroom(skb) < sizeof(skb->cb) && - pskb_expand_head(skb, 0, sizeof(skb->cb), GFP_ATOMIC)) { - printk(KERN_DEBUG "%s: Failed to store skb->cb " - "in skb->data for TX filtered frame\n", - dev->name); - dev_kfree_skb_irq(skb); - return; - } - memcpy(skb_put(skb, sizeof(skb->cb)), skb->cb, - sizeof(skb->cb)); - } - - skb->dev = dev; - memcpy(skb->cb, status, sizeof(struct ieee80211_tx_status)); - skb->pkt_type = ieee80211_tx_status_msg; - skb_queue_tail(status->req_tx_status ? - &local->skb_queue : &local->skb_queue_unreliable, skb); - tmp = skb_queue_len(&local->skb_queue) + - skb_queue_len(&local->skb_queue_unreliable); - while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && - (skb = skb_dequeue(&local->skb_queue_unreliable))) { - dev_kfree_skb_irq(skb); - tmp--; - I802_DEBUG_INC(local->tx_status_drop); - } - tasklet_schedule(&local->tasklet); -} - - -static void ieee80211_tasklet_handler(unsigned long data) -{ - struct ieee80211_local *local = (struct ieee80211_local *) data; - struct sk_buff *skb; - struct ieee80211_rx_status rx_status; - struct ieee80211_tx_status tx_status; - - while ((skb = skb_dequeue(&local->skb_queue)) || - (skb = skb_dequeue(&local->skb_queue_unreliable))) { - switch (skb->pkt_type) { - case ieee80211_rx_msg: - /* Make a copy of the RX status because the original - * skb may be freed during processing. Clear skb->type - * in order to not confuse kernel netstack. */ - memcpy(&rx_status, skb->cb, sizeof(rx_status)); - skb->pkt_type = 0; - ieee80211_rx(skb->dev, skb, &rx_status); - break; - case ieee80211_tx_status_msg: - /* Make a copy of the TX status because the original - * skb may be freed during processing. */ - memcpy(&tx_status, skb->cb, sizeof(tx_status)); - skb->pkt_type = 0; - if ((tx_status.tx_filtered || - tx_status.excessive_retries) && - skb->len >= sizeof(skb->cb)) { - /* Restore skb->cb from the copy that was made - * in ieee80211_tx_status_irqsafe() */ - memcpy(skb->cb, - skb->data + skb->len - sizeof(skb->cb), - sizeof(skb->cb)); - skb_trim(skb, skb->len - sizeof(skb->cb)); - } - ieee80211_tx_status(skb->dev, skb, &tx_status); - break; - default: /* should never get here! */ - printk(KERN_ERR "%s: Unknown message type (%d)\n", - local->wdev->name, skb->pkt_type); - dev_kfree_skb(skb); - break; - } - } -} - - -/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to - * make a prepared TX frame (one that has been given to hw) to look like brand - * new IEEE 802.11 frame that is ready to go through TX processing again. */ -static void ieee80211_remove_tx_extra(struct ieee80211_local *local, - struct ieee80211_key *key, - struct sk_buff *skb) -{ - int hdrlen, iv_len, mic_len; - - if (key == NULL) - return; - - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - - switch (key->alg) { - case ALG_WEP: - iv_len = WEP_IV_LEN; - mic_len = WEP_ICV_LEN; - break; - case ALG_TKIP: - iv_len = TKIP_IV_LEN; - mic_len = TKIP_ICV_LEN; - break; - case ALG_CCMP: - iv_len = CCMP_HDR_LEN; - mic_len = CCMP_MIC_LEN; - break; - default: - return; - } - - if (skb->len >= mic_len && key->force_sw_encrypt) - skb_trim(skb, skb->len - mic_len); - if (skb->len >= iv_len && skb->len > hdrlen) { - memmove(skb->data + iv_len, skb->data, hdrlen); - skb_pull(skb, iv_len); - } - - { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 fc = le16_to_cpu(hdr->frame_control); - if ((fc & 0x8C) == 0x88) /* QoS Control Field */ { - fc &= ~(WLAN_FC_STYPE_QOS_DATA << 4); - hdr->frame_control = cpu_to_le16(fc); - memmove(skb->data + 2, skb->data, hdrlen - 2); - skb_pull(skb, 2); - } - } -} - - -void ieee80211_tx_status(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_tx_status *status) -{ - struct sk_buff *skb2; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_local *local = dev->priv; - struct ieee80211_tx_packet_data *pkt_data = - (struct ieee80211_tx_packet_data *) skb->cb; - u16 frag, type; - u32 msg_type; - - if (!status) { - printk(KERN_ERR - "%s: ieee80211_tx_status called with NULL status\n", - dev->name); - dev_kfree_skb(skb); - return; - } - - if (status->excessive_retries) { - struct sta_info *sta; - - - sta = sta_info_get(local, hdr->addr1); - if (sta) { - if (sta->flags & WLAN_STA_PS) { - /* The STA is in power save mode, so assume - * that this TX packet failed because of that. - */ - status->excessive_retries = 0; - status->tx_filtered = 1; - } - sta_info_release(local, sta); - } - } - - if (status->tx_filtered) { - struct sta_info *sta; - sta = sta_info_get(local, hdr->addr1); - if (sta) { - - sta->tx_filtered_count++; - - /* Clear the TX filter mask for this STA when sending - * the next packet. If the STA went to power save mode, - * this will happen when it is waking up for the next - * time. */ - sta->clear_dst_mask = 1; - - /* TODO: Is the WLAN_STA_PS flag always set here or is - * the race between RX and TX status causing some - * packets to be filtered out before 80211.o gets an - * update for PS status? This seems to be the case, so - * no changes are likely to be needed. */ - if (sta->flags & WLAN_STA_PS && - skb_queue_len(&sta->tx_filtered) < - STA_MAX_TX_BUFFER) { - ieee80211_remove_tx_extra(local, sta->key, - skb); - skb_queue_tail(&sta->tx_filtered, skb); - } else if (!(sta->flags & WLAN_STA_PS) && - !pkt_data->control.requeue) { - /* Software retry the packet once */ - pkt_data->control.requeue = 1; - ieee80211_remove_tx_extra(local, sta->key, - skb); - dev_queue_xmit(skb); - } else { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: dropped TX " - "filtered frame queue_len=%d " - "PS=%d @%lu\n", - dev->name, - skb_queue_len( - &sta->tx_filtered), - !!(sta->flags & WLAN_STA_PS), - jiffies); - } - dev_kfree_skb(skb); - } - sta_info_release(local, sta); - return; - } - } else { - rate_control_tx_status(dev, skb, status); - } - -#ifdef IEEE80211_LEDS - if (local->tx_led_counter && (local->tx_led_counter-- == 1)) { - ieee80211_tx_led(0, dev); - } -#endif /* IEEE80211_LEDS */ - /* SNMP counters - * Fragments are passed to low-level drivers as separate skbs, so these - * are actually fragments, not frames. Update frame counters only for - * the first fragment of the frame. */ - - frag = WLAN_GET_SEQ_FRAG(le16_to_cpu(hdr->seq_ctrl)); - type = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_control)); - - if (status->ack) { - if (frag == 0) { - local->dot11TransmittedFrameCount++; - if (MULTICAST_ADDR(hdr->addr1)) - local->dot11MulticastTransmittedFrameCount++; - if (status->retry_count > 0) - local->dot11RetryCount++; - if (status->retry_count > 1) - local->dot11MultipleRetryCount++; - } - - /* This counter shall be incremented for an acknowledged MPDU - * with an individual address in the address 1 field or an MPDU - * with a multicast address in the address 1 field of type Data - * or Management. */ - if (!MULTICAST_ADDR(hdr->addr1) || type == WLAN_FC_TYPE_DATA || - type == WLAN_FC_TYPE_MGMT) - local->dot11TransmittedFragmentCount++; - } else { - if (frag == 0) - local->dot11FailedCount++; - } - - if (!status->req_tx_status) { - dev_kfree_skb(skb); - return; - } - - msg_type = status->ack ? ieee80211_msg_tx_callback_ack : - ieee80211_msg_tx_callback_fail; - - /* skb was the original skb used for TX. Clone it and give the clone - * to netif_rx(). Free original skb. */ - skb2 = skb_copy(skb, GFP_ATOMIC); - if (!skb2) { - dev_kfree_skb(skb); - return; - } - dev_kfree_skb(skb); - skb = skb2; - - /* Send frame to hostapd */ - ieee80211_rx_mgmt(dev, skb, NULL, msg_type); -} - - -/* TODO: implement register/unregister functions for adding TX/RX handlers - * into ordered list */ - -static ieee80211_rx_handler ieee80211_rx_handlers[] = -{ - ieee80211_rx_h_parse_qos, - ieee80211_rx_h_load_stats, - ieee80211_rx_h_monitor, - ieee80211_rx_h_passive_scan, - ieee80211_rx_h_check, - ieee80211_rx_h_sta_process, - ieee80211_rx_h_ccmp_decrypt, - ieee80211_rx_h_tkip_decrypt, - ieee80211_rx_h_wep_weak_iv_detection, - ieee80211_rx_h_wep_decrypt, - ieee80211_rx_h_defragment, - ieee80211_rx_h_ieee80211_rx_h_ps_poll, - ieee80211_rx_h_michael_mic_verify, - /* this must be after decryption - so header is counted in MPDU mic - * must be before pae and data, so QOS_DATA format frames - * are not passed to user space by these functions - */ - ieee80211_rx_h_remove_qos_control, - ieee80211_rx_h_802_1x_pae, - ieee80211_rx_h_drop_unencrypted, - ieee80211_rx_h_data, - ieee80211_rx_h_mgmt, - NULL -}; - -static ieee80211_tx_handler ieee80211_tx_handlers[] = -{ - ieee80211_tx_h_rate_limit, - ieee80211_tx_h_check_assoc, - ieee80211_tx_h_ps_buf, - ieee80211_tx_h_select_key, - ieee80211_tx_h_michael_mic_add, - ieee80211_tx_h_fragment, - ieee80211_tx_h_tkip_encrypt, - ieee80211_tx_h_ccmp_encrypt, - ieee80211_tx_h_wep_encrypt, - ieee80211_tx_h_rate_ctrl, - ieee80211_tx_h_misc, - ieee80211_tx_h_load_stats, - NULL -}; - - -static void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata) -{ - /* Default values for sub-interface parameters */ - sdata->drop_unencrypted = 0; - sdata->eapol = 1; -} - - -static struct net_device *ieee80211_if_add(struct net_device *dev, - char *name, int locked) -{ - struct net_device *wds_dev = NULL, *tmp_dev; - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata = NULL, *sdata_parent; - int alloc_size; - int ret; - int i; - - /* ensure 32-bit alignment of our private data and hw private data */ - alloc_size = sizeof(struct net_device) + 3 + - sizeof(struct ieee80211_sub_if_data) + 3; - - wds_dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL); - if (wds_dev == NULL) - return NULL; - - memset(wds_dev, 0, alloc_size); - wds_dev->priv = local; - ether_setup(wds_dev); - if (strlen(name) == 0) { - i = 0; - do { - sprintf(wds_dev->name, "%s.%d", dev->name, i++); - tmp_dev = dev_get_by_name(wds_dev->name); - if (tmp_dev == NULL) - break; - dev_put(tmp_dev); - } while (i < 10000); - } else { - snprintf(wds_dev->name, IFNAMSIZ, "%s", name); - } - - memcpy(wds_dev->dev_addr, dev->dev_addr, ETH_ALEN); - wds_dev->hard_start_xmit = ieee80211_subif_start_xmit; - wds_dev->do_ioctl = ieee80211_ioctl; - wds_dev->change_mtu = ieee80211_change_mtu; - wds_dev->tx_timeout = ieee80211_tx_timeout; - wds_dev->get_stats = ieee80211_get_stats; - wds_dev->open = ieee80211_open; - wds_dev->stop = ieee80211_stop; - wds_dev->base_addr = dev->base_addr; - wds_dev->irq = dev->irq; - wds_dev->mem_start = dev->mem_start; - wds_dev->mem_end = dev->mem_end; - wds_dev->tx_queue_len = 0; - - sdata = IEEE80211_DEV_TO_SUB_IF(wds_dev); - sdata->type = IEEE80211_SUB_IF_TYPE_NORM; - sdata->master = local->mdev; - sdata->dev = wds_dev; - sdata->local = local; - memset(&sdata->stats, 0, sizeof(struct net_device_stats)); - sdata_parent = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata_parent->type == IEEE80211_SUB_IF_TYPE_NORM) - sdata->bss = &sdata_parent->u.norm; - else { - printk(KERN_DEBUG "%s: could not set BSS pointer for new " - "interface %s\n", dev->name, wds_dev->name); - } - ieee80211_if_sdata_init(sdata); - - if (locked) - ret = register_netdevice(wds_dev); - else - ret = register_netdev(wds_dev); - if (ret) { - kfree(wds_dev); - return NULL; - } - - list_add(&sdata->list, &local->sub_if_list); - - strcpy(name, wds_dev->name); - - return wds_dev; -} - - -int ieee80211_if_add_wds(struct net_device *dev, char *name, - struct ieee80211_if_wds *wds, int locked) -{ - struct net_device *wds_dev = NULL; - struct ieee80211_sub_if_data *sdata = NULL; - - if (strlen(name) != 0) { - wds_dev = dev_get_by_name(name); - if (wds_dev) { - dev_put(wds_dev); - return -EEXIST; - } - } - - wds_dev = ieee80211_if_add(dev, name, locked); - if (wds_dev == NULL) - return -ENOANO; - - sdata = IEEE80211_DEV_TO_SUB_IF(wds_dev); - sdata->type = IEEE80211_SUB_IF_TYPE_WDS; - memcpy(&sdata->u.wds, wds, sizeof(struct ieee80211_if_wds)); - -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG - "%s: Added WDS Link to " MACSTR "\n", - wds_dev->name, MAC2STR(sdata->u.wds.remote_addr)); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - - - ieee80211_proc_init_virtual(wds_dev); - - return 0; -} - - -int ieee80211_if_update_wds(struct net_device *dev, char *name, - struct ieee80211_if_wds *wds, int locked) -{ - struct net_device *wds_dev = NULL; - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata = NULL; - struct sta_info *sta; - struct list_head *ptr; - - list_for_each(ptr, &local->sub_if_list) { - sdata = list_entry(ptr, struct ieee80211_sub_if_data, list); - if (strcmp(name, sdata->dev->name) == 0) { - wds_dev = sdata->dev; - break; - } - } - - if (wds_dev == NULL || sdata->type != IEEE80211_SUB_IF_TYPE_WDS) - return -ENODEV; - - /* Remove STA entry for the old peer */ - sta = sta_info_get(local, sdata->u.wds.remote_addr); - if (sta) { - sta_info_release(local, sta); - sta_info_free(local, sta, 0); - } else { - printk(KERN_DEBUG "%s: could not find STA entry for WDS link " - "%s peer " MACSTR "\n", - dev->name, wds_dev->name, - MAC2STR(sdata->u.wds.remote_addr)); - } - - /* Update WDS link data */ - memcpy(&sdata->u.wds, wds, sizeof(struct ieee80211_if_wds)); - - - return 0; -} - - -static void ieee80211_if_init(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - - spin_lock_init(&local->sub_if_lock); - INIT_LIST_HEAD(&local->sub_if_list); - -} - - -int ieee80211_if_add_vlan(struct net_device *dev, - char *name, - struct ieee80211_if_vlan *vlan, - int locked) -{ - struct net_device *vlan_dev = NULL; - struct ieee80211_sub_if_data *sdata = NULL; - - if (strlen(name) != 0) { - vlan_dev = dev_get_by_name(name); - if (vlan_dev) { - dev_put(vlan_dev); - return -EEXIST; - } - } - - vlan_dev = ieee80211_if_add(dev, name, locked); - if (vlan_dev == NULL) - return -ENOANO; - - sdata = IEEE80211_DEV_TO_SUB_IF(vlan_dev); - sdata->type = IEEE80211_SUB_IF_TYPE_VLAN; - ieee80211_proc_init_virtual(vlan_dev); - return 0; -} - - -static void ieee80211_if_norm_init(struct ieee80211_sub_if_data *sdata) -{ - sdata->type = IEEE80211_SUB_IF_TYPE_NORM; - sdata->u.norm.dtim_period = 2; - sdata->u.norm.force_unicast_rateidx = -1; - sdata->u.norm.max_ratectrl_rateidx = -1; - skb_queue_head_init(&sdata->u.norm.ps_bc_buf); - sdata->bss = &sdata->u.norm; -} - - -int ieee80211_if_add_norm(struct net_device *dev, char *name, u8 *bssid, - int locked) -{ - struct ieee80211_local *local = dev->priv; - struct net_device *norm_dev = NULL; - struct ieee80211_sub_if_data *sdata = NULL; - - if (local->bss_dev_count >= local->conf.bss_count) - return -ENOBUFS; - - if (strlen(name) != 0) { - norm_dev = dev_get_by_name(name); - if (norm_dev) { - dev_put(norm_dev); - return -EEXIST; - } - } - - norm_dev = ieee80211_if_add(dev, name, locked); - if (norm_dev == NULL) - return -ENOANO; - - memcpy(norm_dev->dev_addr, bssid, ETH_ALEN); - sdata = IEEE80211_DEV_TO_SUB_IF(norm_dev); - ieee80211_if_norm_init(sdata); - ieee80211_proc_init_virtual(norm_dev); - spin_lock_bh(&local->sub_if_lock); - local->bss_devs[local->bss_dev_count] = norm_dev; - local->bss_dev_count++; - spin_unlock_bh(&local->sub_if_lock); - - return 0; -} - - -static void ieee80211_addr_inc(u8 *addr) -{ - int pos = 5; - while (pos >= 0) { - addr[pos]++; - if (addr[pos] != 0) - break; - pos--; - } -} - - -int ieee80211_if_add_sta(struct net_device *dev, char *name, int locked) -{ - struct ieee80211_local *local = dev->priv; - struct net_device *sta_dev; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_sta *ifsta; - int i; - - if (local->sta_dev_count >= local->conf.bss_count) - return -ENOBUFS; - - if (strlen(name) != 0) { - sta_dev = dev_get_by_name(name); - if (sta_dev) { - dev_put(sta_dev); - return -EEXIST; - } - } - - sta_dev = ieee80211_if_add(dev, name, locked); - if (sta_dev == NULL) - return -ENOANO; - - sdata = IEEE80211_DEV_TO_SUB_IF(sta_dev); - ifsta = &sdata->u.sta; - sdata->type = IEEE80211_SUB_IF_TYPE_STA; - ieee80211_proc_init_virtual(sta_dev); - - spin_lock_bh(&local->sub_if_lock); - for (i = 0; i < local->conf.bss_count; i++) { - if (local->sta_devs[i] == NULL) { - local->sta_devs[i] = sta_dev; - local->sta_dev_count++; - printk(KERN_DEBUG "%s: using STA entry %d\n", - sta_dev->name, i); - while (i > 0) { - ieee80211_addr_inc(sta_dev->dev_addr); - i--; - } - printk(KERN_DEBUG "%s: MAC address " MACSTR "\n", - sta_dev->name, MAC2STR(sta_dev->dev_addr)); - break; - } - } - spin_unlock_bh(&local->sub_if_lock); - - init_timer(&ifsta->timer); - ifsta->timer.data = (unsigned long) sta_dev; - ifsta->timer.function = ieee80211_sta_timer; - - ifsta->capab = WLAN_CAPABILITY_ESS; - ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | - IEEE80211_AUTH_ALG_SHARED_KEY; - ifsta->create_ibss = 1; - ifsta->wmm_enabled = 1; - - return 0; -} - - -static void ieee80211_if_del(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, int locked) -{ - struct sta_info *sta; - u8 addr[ETH_ALEN]; - int i, j; - struct list_head *ptr, *n; - - memset(addr, 0xff, ETH_ALEN); - for (i = 0; i < NUM_DEFAULT_KEYS; i++) { - if (!sdata->keys[i]) - continue; -#if 0 - /* Low-level driver has probably disabled hw - * already, so there is not really much point - * in disabling the keys at this point. */ - if (local->hw->set_key) - local->hw->set_key(dev, DISABLE_KEY, addr, - local->keys[i], 0); -#endif - kfree(sdata->keys[i]); - } - - switch (sdata->type) { - case IEEE80211_SUB_IF_TYPE_NORM: - /* Remove all virtual interfaces that use this BSS - * as their sdata->bss */ - list_for_each_safe(ptr, n, &local->sub_if_list) { - struct ieee80211_sub_if_data *tsdata = - list_entry(ptr, struct ieee80211_sub_if_data, - list); - - if (tsdata != sdata && tsdata->bss == &sdata->u.norm) { - printk(KERN_DEBUG "%s: removing virtual " - "interface %s because its BSS interface" - " is being removed\n", - sdata->dev->name, tsdata->dev->name); - ieee80211_if_del(local, tsdata, locked); - } - } - - kfree(sdata->u.norm.beacon_head); - kfree(sdata->u.norm.beacon_tail); - spin_lock_bh(&local->sub_if_lock); - for (j = 0; j < local->bss_dev_count; j++) { - if (sdata->dev == local->bss_devs[j]) { - if (j + 1 < local->bss_dev_count) { - memcpy(&local->bss_devs[j], - &local->bss_devs[j + 1], - (local->bss_dev_count - j - 1) * - sizeof(local->bss_devs[0])); - local->bss_devs[local->bss_dev_count - - 1] = NULL; - } else - local->bss_devs[j] = NULL; - local->bss_dev_count--; - break; - } - } - spin_unlock_bh(&local->sub_if_lock); - - if (sdata->dev != local->mdev) { - struct sk_buff *skb; - while ((skb = skb_dequeue(&sdata->u.norm.ps_bc_buf))) { - local->total_ps_buffered--; - dev_kfree_skb(skb); - } - } - - break; - case IEEE80211_SUB_IF_TYPE_WDS: - sta = sta_info_get(local, sdata->u.wds.remote_addr); - if (sta) { - sta_info_release(local, sta); - sta_info_free(local, sta, 0); - } else { -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Someone had deleted my STA " - "entry for the WDS link\n", sdata->dev->name); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - } - break; - case IEEE80211_SUB_IF_TYPE_STA: - del_timer_sync(&sdata->u.sta.timer); - if (local->scan_timer.data == (unsigned long) sdata->dev) - del_timer_sync(&local->scan_timer); - kfree(sdata->u.sta.extra_ie); - sdata->u.sta.extra_ie = NULL; - kfree(sdata->u.sta.assocreq_ies); - sdata->u.sta.assocreq_ies = NULL; - kfree(sdata->u.sta.assocresp_ies); - sdata->u.sta.assocresp_ies = NULL; - if (sdata->u.sta.probe_resp) { - dev_kfree_skb(sdata->u.sta.probe_resp); - sdata->u.sta.probe_resp = NULL; - } - for (i = 0; i < local->conf.bss_count; i++) { - if (local->sta_devs[i] == sdata->dev) { - local->sta_devs[i] = NULL; - local->sta_dev_count--; - break; - } - } - - break; - } - - /* remove all STAs that are bound to this virtual interface */ - sta_info_flush(local, sdata->dev); - - list_del(&sdata->list); - ieee80211_proc_deinit_virtual(sdata->dev); - if (locked) - unregister_netdevice(sdata->dev); - else - unregister_netdev(sdata->dev); - /* Default data device and management device are allocated with the - * master device. All other devices are separately allocated and will - * be freed here. */ - if (sdata->dev != local->mdev && sdata->dev != local->wdev && - sdata->dev != local->apdev) - kfree(sdata->dev); -} - - -static int ieee80211_if_remove(struct net_device *dev, char *name, int id, - int locked) -{ - struct ieee80211_local *local = dev->priv; - struct list_head *ptr, *n; - - /* Make sure not to touch sdata->master since it may - * have already been deleted, etc. */ - - list_for_each_safe(ptr, n, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - - if (sdata->type == id && strcmp(name, sdata->dev->name) == 0) { - ieee80211_if_del(local, sdata, locked); - break; - } - } - - return 0; -} - - -int ieee80211_if_remove_wds(struct net_device *dev, char *name, int locked) -{ - return ieee80211_if_remove(dev, name, IEEE80211_SUB_IF_TYPE_WDS, - locked); -} - - -int ieee80211_if_remove_vlan(struct net_device *dev, char *name, int locked) -{ - return ieee80211_if_remove(dev, name, IEEE80211_SUB_IF_TYPE_VLAN, - locked); -} - - -int ieee80211_if_remove_norm(struct net_device *dev, char *name, int locked) -{ - return ieee80211_if_remove(dev, name, IEEE80211_SUB_IF_TYPE_NORM, - locked); -} - - -int ieee80211_if_remove_sta(struct net_device *dev, char *name, int locked) -{ - return ieee80211_if_remove(dev, name, IEEE80211_SUB_IF_TYPE_STA, - locked); -} - - -int ieee80211_if_flush(struct net_device *dev, int locked) -{ - struct ieee80211_local *local = dev->priv; - struct list_head *ptr, *n; - - list_for_each_safe(ptr, n, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - - if (sdata->dev != local->mdev && - sdata->dev != local->wdev && - sdata->dev != local->apdev) - ieee80211_if_del(local, sdata, locked); - } - - return 0; -} - - -static void ieee80211_precalc_rates(struct ieee80211_hw *hw) -{ - struct ieee80211_hw_modes *mode; - struct ieee80211_rate *rate; - int m, r; - - for (m = 0; m < hw->num_modes; m++) { - mode = &hw->modes[m]; - for (r = 0; r < mode->num_rates; r++) { - rate = &mode->rates[r]; - rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate; - } - } -} - - -struct net_device *ieee80211_alloc_hw(size_t priv_data_len, - void (*setup)(struct net_device *)) -{ - struct net_device *dev, *apdev, *mdev; - struct ieee80211_local *local; - struct ieee80211_sub_if_data *sdata; - int alloc_size; - - /* Ensure 32-bit alignment of our private data and hw private data. - * Each net_device is followed by a sub_if_data which which is used - * for wds/vlan information; it is aligned as well. - * - * Sample memory map looks something like: - * - * 0000 ***************** - * * net_dev * - * 015c ***************** - * * sub_if * - * 017c ***************** - * * local * - * 0b84 ***************** - * * hw_priv * - * 1664 ***************** - * * ap net_dev * - * 17c0 ***************** - * * sub_if * - * ***************** - * * master net_dev* - * ***************** - * * sub_if * - * ***************** - */ - alloc_size = sizeof(struct net_device) + - sizeof(struct ieee80211_sub_if_data) + 3 + - sizeof(struct ieee80211_local) + 3 + - priv_data_len + 3 + - sizeof(struct net_device) + 3 + - sizeof(struct ieee80211_sub_if_data) + 3 + - sizeof(struct net_device) + 3 + - sizeof(struct ieee80211_sub_if_data) + 3 + - 4096; - mdev = (struct net_device *) kzalloc(alloc_size, GFP_KERNEL); - if (mdev == NULL) - return NULL; - - mdev->priv = (struct net_device *) - (((long) mdev + - sizeof(struct net_device) + - sizeof(struct ieee80211_sub_if_data) + 3) - & ~3); - local = mdev->priv; - local->hw_priv = (void *) - (((long) local + sizeof(struct ieee80211_local) + 3) & ~3); - apdev = (struct net_device *) - (((long) local->hw_priv + priv_data_len + 3) & ~3); - dev = (struct net_device *) - (((long) apdev + - sizeof(struct net_device) + - sizeof(struct ieee80211_sub_if_data) + 3) - & ~3); - dev->priv = local; - - ether_setup(dev); - memcpy(dev->name, "wlan%d", 7); - - dev->hard_start_xmit = ieee80211_subif_start_xmit; - dev->do_ioctl = ieee80211_ioctl; - dev->change_mtu = ieee80211_change_mtu; - dev->tx_timeout = ieee80211_tx_timeout; - dev->get_stats = ieee80211_get_stats; - dev->open = ieee80211_open; - dev->stop = ieee80211_stop; - dev->tx_queue_len = 0; - dev->set_mac_address = ieee80211_set_mac_address; - - local->wdev = dev; - local->mdev = mdev; - local->rx_handlers = ieee80211_rx_handlers; - local->tx_handlers = ieee80211_tx_handlers; - - local->bridge_packets = 1; - - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - local->short_retry_limit = 7; - local->long_retry_limit = 4; - local->conf.calib_int = 60; - local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP; - local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN; - local->conf.bss_count = 1; - memset(local->conf.bssid_mask, 0xff, ETH_ALEN); - local->bss_devs = kmalloc(sizeof(struct net_device *), GFP_KERNEL); - if (local->bss_devs == NULL) - goto fail; - local->bss_devs[0] = local->wdev; - local->bss_dev_count = 1; - local->sta_devs = kmalloc(sizeof(struct net_device *), GFP_KERNEL); - if (local->sta_devs == NULL) - goto fail; - local->sta_devs[0] = NULL; - - local->scan.in_scan = 0; - local->hw_modes = (unsigned int) -1; - - init_timer(&local->scan.timer); /* clear it out */ - - spin_lock_init(&local->generic_lock); - init_timer(&local->rate_limit_timer); - local->rate_limit_timer.function = ieee80211_rate_limit; - local->rate_limit_timer.data = (unsigned long) local; - init_timer(&local->stat_timer); - local->stat_timer.function = ieee80211_stat_refresh; - local->stat_timer.data = (unsigned long) local; - ieee80211_rx_bss_list_init(dev); - - sta_info_init(local); - - ieee80211_if_init(dev); - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - sdata->dev = dev; - sdata->master = mdev; - sdata->local = local; - ieee80211_if_sdata_init(sdata); - ieee80211_if_norm_init(sdata); - list_add_tail(&sdata->list, &local->sub_if_list); - - if (strlen(dev->name) + 2 >= sizeof(dev->name)) - goto fail; - - apdev = (struct net_device *) - (((long) local->hw_priv + priv_data_len + 3) & ~3); - local->apdev = apdev; - ether_setup(apdev); - apdev->priv = local; - apdev->hard_start_xmit = ieee80211_mgmt_start_xmit; - apdev->change_mtu = ieee80211_change_mtu_apdev; - apdev->get_stats = ieee80211_get_stats; - apdev->open = ieee80211_open; - apdev->stop = ieee80211_stop; - apdev->type = ARPHRD_IEEE80211_PRISM; - apdev->hard_header_parse = header_parse_80211; - apdev->tx_queue_len = 0; - sprintf(apdev->name, "%sap", dev->name); - - sdata = IEEE80211_DEV_TO_SUB_IF(apdev); - sdata->type = IEEE80211_SUB_IF_TYPE_MGMT; - sdata->dev = apdev; - sdata->master = mdev; - sdata->local = local; - list_add_tail(&sdata->list, &local->sub_if_list); - - ether_setup(mdev); - mdev->hard_start_xmit = ieee80211_master_start_xmit; - mdev->do_ioctl = ieee80211_ioctl; - mdev->change_mtu = ieee80211_change_mtu; - mdev->tx_timeout = ieee80211_tx_timeout; - mdev->get_stats = ieee80211_get_stats; - mdev->open = ieee80211_open; - mdev->stop = ieee80211_stop; - mdev->type = ARPHRD_IEEE80211; - mdev->hard_header_parse = header_parse_80211; - sprintf(mdev->name, "%s.11", dev->name); - - sdata = IEEE80211_DEV_TO_SUB_IF(mdev); - sdata->type = IEEE80211_SUB_IF_TYPE_NORM; - sdata->dev = mdev; - sdata->master = mdev; - sdata->local = local; - list_add_tail(&sdata->list, &local->sub_if_list); - - tasklet_init(&local->tasklet, - ieee80211_tasklet_handler, - (unsigned long) local); - skb_queue_head_init(&local->skb_queue); - skb_queue_head_init(&local->skb_queue_unreliable); - - if (setup) - setup(mdev); - - return mdev; - - fail: - ieee80211_free_hw(mdev); - return NULL; -} - -int ieee80211_register_hw(struct net_device *dev, struct ieee80211_hw *hw) -{ - struct ieee80211_local *local = dev->priv; - int result; - - if (!hw) - return -1; - - if (hw->version != IEEE80211_VERSION) { - printk("ieee80211_register_hw - version mismatch: 80211.o " - "version %d, low-level driver version %d\n", - IEEE80211_VERSION, hw->version); - return -1; - } - - local->conf.mode = IW_MODE_MASTER; - local->conf.beacon_int = 1000; - - ieee80211_update_hw(dev, hw); /* Don't care about the result. */ - - sta_info_start(local); - - result = register_netdev(local->wdev); - if (result < 0) - return -1; - - result = register_netdev(local->apdev); - if (result < 0) - goto fail_2nd_dev; - - if (hw->fraglist) - dev->features |= NETIF_F_FRAGLIST; - result = register_netdev(dev); - if (result < 0) - goto fail_3rd_dev; - - if (rate_control_initialize(local) < 0) { - printk(KERN_DEBUG "%s: Failed to initialize rate control " - "algorithm\n", dev->name); - goto fail_rate; - } - - /* TODO: add rtnl locking around device creation and qdisc install */ - ieee80211_install_qdisc(dev); - - ieee80211_wep_init(local); - ieee80211_proc_init_interface(local); - return 0; - -fail_rate: - unregister_netdev(dev); -fail_3rd_dev: - unregister_netdev(local->apdev); -fail_2nd_dev: - unregister_netdev(local->wdev); - sta_info_stop(local); - return result; -} - -int ieee80211_update_hw(struct net_device *dev, struct ieee80211_hw *hw) -{ - struct ieee80211_local *local = dev->priv; - - local->hw = hw; - - /* Backwards compatibility for low-level drivers that do not set number - * of TX queues. */ - if (hw->queues == 0) - hw->queues = 1; - - memcpy(local->apdev->dev_addr, dev->dev_addr, ETH_ALEN); - local->apdev->base_addr = dev->base_addr; - local->apdev->irq = dev->irq; - local->apdev->mem_start = dev->mem_start; - local->apdev->mem_end = dev->mem_end; - - memcpy(local->wdev->dev_addr, dev->dev_addr, ETH_ALEN); - local->wdev->base_addr = dev->base_addr; - local->wdev->irq = dev->irq; - local->wdev->mem_start = dev->mem_start; - local->wdev->mem_end = dev->mem_end; - - if (!hw->modes || !hw->modes->channels || !hw->modes->rates || - !hw->modes->num_channels || !hw->modes->num_rates) - return -1; - - ieee80211_precalc_rates(hw); - local->conf.phymode = hw->modes[0].mode; - local->curr_rates = hw->modes[0].rates; - local->num_curr_rates = hw->modes[0].num_rates; - ieee80211_prepare_rates(dev); - - local->conf.freq = local->hw->modes[0].channels[0].freq; - local->conf.channel = local->hw->modes[0].channels[0].chan; - local->conf.channel_val = local->hw->modes[0].channels[0].val; - /* FIXME: Invoke config to allow driver to set the channel. */ - - return 0; -} - -void ieee80211_unregister_hw(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - struct list_head *ptr, *n; - int i; - - tasklet_disable(&local->tasklet); - /* TODO: skb_queue should be empty here, no need to do anything? */ - - if (local->rate_limit) - del_timer_sync(&local->rate_limit_timer); - if (local->stat_time) - del_timer_sync(&local->stat_timer); - if (local->scan_timer.data) - del_timer_sync(&local->scan_timer); - ieee80211_rx_bss_list_deinit(dev); - - list_for_each_safe(ptr, n, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - ieee80211_if_del(local, sdata, 0); - } - - sta_info_stop(local); - - for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) - if (local->fragments[i].skb) - dev_kfree_skb(local->fragments[i].skb); - - for (i = 0; i < NUM_IEEE80211_MODES; i++) { - kfree(local->supp_rates[i]); - kfree(local->basic_rates[i]); - } - - kfree(local->conf.ssid); - kfree(local->conf.generic_elem); - - ieee80211_proc_deinit_interface(local); - - skb_queue_purge(&local->skb_queue); - skb_queue_purge(&local->skb_queue_unreliable); - - rate_control_free(local); -} - -void ieee80211_free_hw(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - - kfree(local->sta_devs); - kfree(local->bss_devs); - kfree(dev); -} - -/* Perform netif operations on all configured interfaces */ -int ieee80211_netif_oper(struct net_device *sdev, Netif_Oper op) -{ - struct ieee80211_local *local = sdev->priv; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sdev); - struct net_device *dev = sdata->master; - - switch (op) { - case NETIF_ATTACH: - netif_device_attach(dev); - break; - case NETIF_DETACH: - netif_device_detach(dev); - break; - case NETIF_START: - netif_start_queue(dev); - break; - case NETIF_STOP: - break; - case NETIF_WAKE: - if (local->scan.in_scan == 0) { - netif_wake_queue(dev); -#if 1 - if (/* FIX: 802.11 qdisc in use */ 1) - __netif_schedule(dev); -#endif - } - break; - case NETIF_IS_STOPPED: - if (netif_queue_stopped(dev)) - return 1; - break; - case NETIF_UPDATE_TX_START: - dev->trans_start = jiffies; - break; - } - - return 0; -} - - -void * ieee80211_dev_hw_data(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - return local->hw_priv; -} - - -void * ieee80211_dev_stats(struct net_device *dev) -{ - struct ieee80211_sub_if_data *sdata; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - return &(sdata->stats); -} - - -int ieee80211_rate_control_register(struct rate_control_ops *ops) -{ - struct rate_control_algs *alg; - - alg = kmalloc(sizeof(*alg), GFP_KERNEL); - if (alg == NULL) { - return -1; - } - memset(alg, 0, sizeof(*alg)); - alg->next = ieee80211_rate_ctrl_algs; - alg->ops = ops; - ieee80211_rate_ctrl_algs = alg; - - return 0; -} - - -void ieee80211_rate_control_unregister(struct rate_control_ops *ops) -{ - struct rate_control_algs *alg, *prev; - - prev = NULL; - alg = ieee80211_rate_ctrl_algs; - while (alg) { - if (alg->ops == ops) { - if (prev) - prev->next = alg->next; - else - ieee80211_rate_ctrl_algs = alg->next; - kfree(alg); - break; - } - prev = alg; - alg = alg->next; - } -} - - -static int rate_control_initialize(struct ieee80211_local *local) -{ - struct rate_control_algs *algs; - for (algs = ieee80211_rate_ctrl_algs; algs; algs = algs->next) { - local->rate_ctrl = algs->ops; - local->rate_ctrl_priv = rate_control_alloc(local); - if (local->rate_ctrl_priv) { - printk(KERN_DEBUG "%s: Selected rate control " - "algorithm '%s'\n", local->wdev->name, - local->rate_ctrl->name); - return 0; - } - } - - printk(KERN_WARNING "%s: Failed to select rate control algorithm\n", - local->wdev->name); - return -1; -} - - -static int __init ieee80211_init(void) -{ - struct sk_buff *skb; - if (sizeof(struct ieee80211_tx_packet_data) > (sizeof(skb->cb))) { - printk("80211: ieee80211_tx_packet_data is bigger " - "than the skb->cb (%d > %d)\n", - (int) sizeof(struct ieee80211_tx_packet_data), - (int) sizeof(skb->cb)); - return -EINVAL; - } - if (sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)) { - printk("80211: ieee80211_rx_status is bigger " - "than the skb->cb (%d > %d)\n", - (int) sizeof(struct ieee80211_rx_status), - (int) sizeof(skb->cb)); - return -EINVAL; - } - - ieee80211_proc_init(); - { - int ret = ieee80211_wme_register(); - if (ret) { - printk(KERN_DEBUG "ieee80211_init: failed to " - "initialize WME (err=%d)\n", ret); - ieee80211_proc_deinit(); - return ret; - } - } - - return 0; -} - - -static void __exit ieee80211_exit(void) -{ - ieee80211_wme_unregister(); - ieee80211_proc_deinit(); -} - - -EXPORT_SYMBOL(ieee80211_alloc_hw); -EXPORT_SYMBOL(ieee80211_register_hw); -EXPORT_SYMBOL(ieee80211_update_hw); -EXPORT_SYMBOL(ieee80211_unregister_hw); -EXPORT_SYMBOL(ieee80211_free_hw); -EXPORT_SYMBOL(ieee80211_rx); -EXPORT_SYMBOL(ieee80211_tx_status); -EXPORT_SYMBOL(ieee80211_beacon_get); -EXPORT_SYMBOL(ieee80211_get_buffered_bc); -EXPORT_SYMBOL(ieee80211_netif_oper); -EXPORT_SYMBOL(ieee80211_dev_hw_data); -EXPORT_SYMBOL(ieee80211_dev_stats); -EXPORT_SYMBOL(ieee80211_get_hw_conf); -EXPORT_SYMBOL(ieee80211_set_aid_for_sta); -EXPORT_SYMBOL(ieee80211_rx_irqsafe); -EXPORT_SYMBOL(ieee80211_tx_status_irqsafe); -EXPORT_SYMBOL(ieee80211_get_hdrlen); -EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); -EXPORT_SYMBOL(ieee80211_rate_control_register); -EXPORT_SYMBOL(ieee80211_rate_control_unregister); -EXPORT_SYMBOL(sta_info_get); -EXPORT_SYMBOL(sta_info_release); -EXPORT_SYMBOL(ieee80211_radar_status); - -module_init(ieee80211_init); -module_exit(ieee80211_exit); diff --git a/target/linux/package/ieee80211-dscape/src/ieee80211_i.h b/target/linux/package/ieee80211-dscape/src/ieee80211_i.h deleted file mode 100644 index 7127f8d67b..0000000000 --- a/target/linux/package/ieee80211-dscape/src/ieee80211_i.h +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Copyright 2002-2005, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef IEEE80211_I_H -#define IEEE80211_I_H - -/* ieee80211.o internal definitions, etc. These are not included into - * low-level drivers. */ - -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - -#define IEEE80211_MAX_SSID_LEN 32 - -struct ieee80211_local; - -#include "ieee80211_key.h" -#include "sta_info.h" - -#define BIT(x) (1 << (x)) - -#define IEEE80211_ALIGN32_PAD(a) ((4 - ((a) & 3)) & 3) - - -/* Maximum number of broadcast/multicast frames to buffer when some of the - * associated stations are using power saving. */ -#define AP_MAX_BC_BUFFER 128 - -/* Maximum number of frames buffered to all STAs, including multicast frames. - * Note: increasing this limit increases the potential memory requirement. Each - * frame can be up to about 2 kB long. */ -#define TOTAL_MAX_TX_BUFFER 512 - - -#define MAC2STR(a) ((a)[0] & 0xff), ((a)[1] & 0xff), ((a)[2] & 0xff), \ - ((a)[3] & 0xff), ((a)[4] & 0xff), ((a)[5] & 0xff) -#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" - -#define MULTICAST_ADDR(a) ((a)[0] & 0x01) - - -/* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent - * reception of at least three fragmented frames. This limit can be increased - * by changing this define, at the cost of slower frame reassembly and - * increased memory use (about 2 kB of RAM per entry). */ -#define IEEE80211_FRAGMENT_MAX 4 - -struct ieee80211_fragment_entry { - unsigned long first_frag_time; - unsigned int seq; - unsigned int rx_queue; - unsigned int last_frag; - struct sk_buff *skb; - int ccmp; /* Whether fragments were encrypted with CCMP */ - u8 last_pn[6]; /* PN of the last fragment if CCMP was used */ -}; - - -struct ieee80211_sta_bss { - struct list_head list; - struct ieee80211_sta_bss *hnext; - atomic_t users; - - u8 bssid[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - size_t ssid_len; - u16 capability; /* host byte order */ - int hw_mode; - int channel; - int freq; - int rssi; - u8 *wpa_ie; - size_t wpa_ie_len; - u8 *rsn_ie; - size_t rsn_ie_len; - u8 *wmm_ie; - size_t wmm_ie_len; -#define IEEE80211_MAX_SUPP_RATES 32 - u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; - size_t supp_rates_len; - int beacon_int; - u64 timestamp; - - int probe_resp; - unsigned long last_update; - -}; - - -typedef enum { - TXRX_CONTINUE, TXRX_DROP, TXRX_QUEUED -} ieee80211_txrx_result; - -struct ieee80211_txrx_data { - struct sk_buff *skb; - struct net_device *dev; - struct ieee80211_local *local; - struct ieee80211_sub_if_data *sdata; - struct sta_info *sta; - u16 fc, ethertype; - struct ieee80211_key *key; - unsigned int fragmented:1; /* whether the MSDU was fragmented */ - union { - struct { - struct ieee80211_tx_control *control; - int unicast:1; - int ps_buffered:1; - int short_preamble:1; - int probe_last_frag:1; - struct ieee80211_rate *rate; - /* use this rate (if set) for last fragment; rate can - * be set to lower rate for the first fragments, e.g., - * when using CTS protection with IEEE 802.11g. */ - struct ieee80211_rate *last_frag_rate; - int last_frag_rateidx; - int mgmt_interface; - - /* Extra fragments (in addition to the first fragment - * in skb) */ - int num_extra_frag; - struct sk_buff **extra_frag; - } tx; - struct { - struct ieee80211_rx_status *status; - int sent_ps_buffered; - int queue; - } rx; - } u; -#ifdef CONFIG_HOSTAPD_WPA_TESTING - int wpa_test; -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ -}; - -struct ieee80211_passive_scan { - unsigned int in_scan:1; /* this must be cleared before calling - * netif_oper(WAKEUP) */ - unsigned int our_mode_only:1; /* only scan our physical mode a/b/g/etc - */ - int interval; /* time in seconds between scans */ - int time; /* time in microseconds to scan for */ - int channel; /* channel to be scanned */ - int tries; - - int mode_idx; - int chan_idx; - - int freq; - int rx_packets; - int rx_beacon; - int txrx_count; - - struct timer_list timer; - - struct sk_buff *skb; /* skb to transmit before changing channels, - * maybe null for none */ - struct ieee80211_tx_control tx_control; - - unsigned int num_scans; -}; - -typedef ieee80211_txrx_result (*ieee80211_tx_handler) -(struct ieee80211_txrx_data *tx); - -typedef ieee80211_txrx_result (*ieee80211_rx_handler) -(struct ieee80211_txrx_data *rx); - -struct ieee80211_if_norm { - u8 *beacon_head, *beacon_tail; - int beacon_head_len, beacon_tail_len; - - /* TODO: sta_aid could be replaced by 2008-bit large bitfield of - * that could be used in TIM element generation. This would also - * make TIM element generation a bit faster. */ - /* AID mapping to station data. NULL, if AID is free. AID is in the - * range 1..2007 and sta_aid[i] corresponds to AID i+1. */ - struct sta_info *sta_aid[MAX_AID_TABLE_SIZE]; - int max_aid; /* largest aid currently in use */ - atomic_t num_sta_ps; /* number of stations in PS mode */ - struct sk_buff_head ps_bc_buf; - int dtim_period, dtim_count; - int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ - int max_ratectrl_rateidx; /* max TX rateidx for rate control */ - int num_beacons; /* number of TXed beacon frames for this BSS */ -}; - -struct ieee80211_if_wds { - u8 remote_addr[ETH_ALEN]; - struct sta_info *sta; -}; - -struct ieee80211_if_vlan { - u8 id; -}; - -struct ieee80211_if_sta { - enum { - IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, - IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, - IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED - } state; - struct timer_list timer; - u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - size_t ssid_len; - u16 aid; - u16 ap_capab, capab; - u8 *extra_ie; /* to be added to the end of AssocReq */ - size_t extra_ie_len; - - /* The last AssocReq/Resp IEs */ - u8 *assocreq_ies, *assocresp_ies; - size_t assocreq_ies_len, assocresp_ies_len; - - int auth_tries, assoc_tries; - - int ssid_set:1; - int bssid_set:1; - int prev_bssid_set:1; - int authenticated:1; - int associated:1; - int probereq_poll:1; - int use_protection:1; - int create_ibss:1; - int mixed_cell:1; - int wmm_enabled:1; - - int key_mgmt; - unsigned long last_probe; - -#define IEEE80211_AUTH_ALG_OPEN BIT(0) -#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) -#define IEEE80211_AUTH_ALG_LEAP BIT(2) - unsigned int auth_algs; /* bitfield of allowed auth algs */ - int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ - int auth_transaction; - - unsigned long ibss_join_req; - struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ - u32 supp_rates_bits; - - int wmm_last_param_set; -}; - - -#define IEEE80211_SUB_IF_TYPE_NORM 0x00000000 -#define IEEE80211_SUB_IF_TYPE_MGMT 0x00000001 -#define IEEE80211_SUB_IF_TYPE_STA 0x00000002 -#define IEEE80211_SUB_IF_TYPE_WDS 0x5A580211 -#define IEEE80211_SUB_IF_TYPE_VLAN 0x00080211 - -struct ieee80211_sub_if_data { - struct list_head list; - unsigned int type; - - struct net_device *dev; - struct net_device *master; - struct ieee80211_local *local; - - struct net_device_stats stats; - int drop_unencrypted; - int eapol; /* 0 = process EAPOL frames as normal data frames, - * 1 = send EAPOL frames through wlan#ap to hostapd - * (default) */ - int ieee802_1x; /* IEEE 802.1X PAE - drop packet to/from unauthorized - * port */ - -#define NUM_DEFAULT_KEYS 4 - struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; - struct ieee80211_key *default_key; - - struct ieee80211_if_norm *bss; /* BSS that this device belongs to */ - - union { - struct ieee80211_if_norm norm; - struct ieee80211_if_wds wds; - struct ieee80211_if_vlan vlan; - struct ieee80211_if_sta sta; - } u; - int channel_use; - int channel_use_raw; -}; - -#define IEEE80211_DEV_TO_SUB_IF(dev) ((struct ieee80211_sub_if_data *) \ - (((long)dev + sizeof(struct net_device) + 3) & ~3)) - - -struct ieee80211_local { - struct ieee80211_hw *hw; - void *hw_priv; - struct net_device *mdev; /* wlan#.11 - "master" 802.11 device */ - struct net_device *wdev; /* wlan# - default Ethernet (data) devide */ - struct net_device *apdev; /* wlan#ap - management frames (hostapd) */ - int open_count; - struct ieee80211_conf conf; - - /* Tasklet and skb queue to process calls from IRQ mode. All frames - * added to skb_queue will be processed, but frames in - * skb_queue_unreliable may be dropped if the total length of these - * queues increases over the limit. */ -#define IEEE80211_IRQSAFE_QUEUE_LIMIT 128 - struct tasklet_struct tasklet; - struct sk_buff_head skb_queue; - struct sk_buff_head skb_queue_unreliable; - enum { - ieee80211_rx_msg = 1, - ieee80211_tx_status_msg = 2 - } ieee80211_msg_enum; - - spinlock_t generic_lock; - /* Station data structures */ - spinlock_t sta_lock; /* mutex for STA data structures */ - int num_sta; /* number of stations in sta_list */ - struct list_head sta_list; - struct sta_info *sta_hash[STA_HASH_SIZE]; - struct timer_list sta_cleanup; - - /* Current rate table. This is a pointer to hw->modes structure. */ - struct ieee80211_rate *curr_rates; - int num_curr_rates; - - void *rate_ctrl_priv; - struct rate_control_ops *rate_ctrl; - - int next_mode; /* MODE_IEEE80211* - * The mode preference for next channel change. This is - * used to select .11g vs. .11b channels (or 4.9 GHz vs. - * .11a) when the channel number is not unique. */ - - /* Supported and basic rate filters for different modes. These are - * pointers to -1 terminated lists and rates in 100 kbps units. */ - int *supp_rates[NUM_IEEE80211_MODES]; - int *basic_rates[NUM_IEEE80211_MODES]; - - int rts_threshold; - int cts_protect_erp_frames; - int fragmentation_threshold; - int short_retry_limit; /* dot11ShortRetryLimit */ - int long_retry_limit; /* dot11LongRetryLimit */ - int short_preamble; /* use short preamble with IEEE 802.11b */ - - u32 wep_iv; - int key_tx_rx_threshold; /* number of times any key can be used in TX - * or RX before generating a rekey - * notification; 0 = notification disabled. */ - - /* Fragment table for host-based reassembly */ - struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; - unsigned int fragment_next; - - int bridge_packets; /* bridge packets between associated stations and - * deliver multicast frames both back to wireless - * media and to the local net stack */ - - struct ieee80211_passive_scan scan; - - - ieee80211_rx_handler *rx_handlers; - ieee80211_tx_handler *tx_handlers; - - spinlock_t sub_if_lock; /* mutex for STA data structures */ - struct list_head sub_if_list; - struct net_device **bss_devs; /* pointer to IF_TYPE_NORM devices for - * quick access to BSS data */ - int bss_dev_count; /* number of used entries in bss_devs; note: the - * total size of bss_devs array is stored in - * conf.bss_count */ - struct net_device **sta_devs; /* pointer to IF_TYPE_STA devices */ - int sta_dev_count; /* number of used entries in sta_devs */ - int sta_scanning; - int scan_hw_mode_idx; - int scan_channel_idx; - enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; - unsigned long last_scan_completed; - struct timer_list scan_timer; - int scan_oper_channel; - int scan_oper_channel_val; - int scan_oper_power_level; - int scan_oper_freq; - int scan_oper_phymode; - int scan_oper_antenna_max; - u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; - size_t scan_ssid_len; - int scan_skip_11b; - struct list_head sta_bss_list; - struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE]; - spinlock_t sta_bss_lock; -#define IEEE80211_SCAN_MATCH_SSID BIT(0) -#define IEEE80211_SCAN_WPA_ONLY BIT(1) -#define IEEE80211_SCAN_EXTRA_INFO BIT(2) - int scan_flags; - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - u32 wpa_trigger; -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - /* SNMP counters */ - /* dot11CountersTable */ - u32 dot11TransmittedFragmentCount; - u32 dot11MulticastTransmittedFrameCount; - u32 dot11FailedCount; - u32 dot11RetryCount; - u32 dot11MultipleRetryCount; - u32 dot11FrameDuplicateCount; - u32 dot11ReceivedFragmentCount; - u32 dot11MulticastReceivedFrameCount; - u32 dot11TransmittedFrameCount; - u32 dot11WEPUndecryptableCount; - - int tx_led_counter; - - u32 channel_use; - u32 channel_use_raw; - u32 stat_time; - struct timer_list stat_timer; - - u8 bssid[ETH_ALEN]; /* BSSID for STA modes (Adhoc/Managed) */ - struct timer_list rate_limit_timer; - u32 rate_limit; - u32 rate_limit_burst; - u32 rate_limit_bucket; - struct proc_dir_entry *proc, *proc_sta, *proc_iface; - - struct work_struct sta_proc_add; - - enum { - STA_ANTENNA_SEL_AUTO = 0, - STA_ANTENNA_SEL_SW_CTRL = 1, - STA_ANTENNA_SEL_SW_CTRL_DEBUG = 2 - } sta_antenna_sel; - - int rate_ctrl_num_up, rate_ctrl_num_down; - -#ifdef CONFIG_IEEE80211_DEBUG_COUNTERS - /* TX/RX handler statistics */ - unsigned int tx_handlers_drop; - unsigned int tx_handlers_queued; - unsigned int tx_handlers_drop_unencrypted; - unsigned int tx_handlers_drop_fragment; - unsigned int tx_handlers_drop_wep; - unsigned int tx_handlers_drop_rate_limit; - unsigned int tx_handlers_drop_not_assoc; - unsigned int tx_handlers_drop_unauth_port; - unsigned int rx_handlers_drop; - unsigned int rx_handlers_queued; - unsigned int rx_handlers_drop_nullfunc; - unsigned int rx_handlers_drop_defrag; - unsigned int rx_handlers_drop_short; - unsigned int rx_handlers_drop_passive_scan; - unsigned int tx_expand_skb_head; - unsigned int tx_expand_skb_head_cloned; - unsigned int rx_expand_skb_head; - unsigned int rx_expand_skb_head2; - unsigned int rx_handlers_fragments; - unsigned int tx_status_drop; - unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; - unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; -#define I802_DEBUG_INC(c) (c)++ -#else /* CONFIG_IEEE80211_DEBUG_COUNTERS */ -#define I802_DEBUG_INC(c) do { } while (0) -#endif /* CONFIG_IEEE80211_DEBUG_COUNTERS */ - - - int default_wep_only; /* only default WEP keys are used with this - * interface; this is used to decide when hwaccel - * can be used with default keys */ - int total_ps_buffered; /* total number of all buffered unicast and - * multicast packets for power saving stations - */ - int allow_broadcast_always; /* whether to allow TX of broadcast frames - * even when there are no associated STAs - */ - - int wifi_wme_noack_test; - unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ - - unsigned int hw_modes; /* bitfield of allowed hardware modes; - * (1 << MODE_*) */ -}; - - -/* ieee80211.c */ -int ieee80211_hw_config(struct net_device *dev); -struct ieee80211_key_conf * -ieee80211_key_data2conf(struct ieee80211_local *local, - struct ieee80211_key *data); -void ieee80211_rx_mgmt(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *status, u32 msg_type); -void ieee80211_prepare_rates(struct net_device *dev); -void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); -int ieee80211_if_add_wds(struct net_device *dev, - char *name, - struct ieee80211_if_wds *wds, int locked); -int ieee80211_if_add_vlan(struct net_device *dev, char *name, - struct ieee80211_if_vlan *vlan, int locked); -int ieee80211_if_add_norm(struct net_device *dev, char *name, u8 *bssid, - int locked); - -int ieee80211_if_remove_wds(struct net_device *dev, char *name, int locked); -int ieee80211_if_remove_vlan(struct net_device *dev, char *name, int locked); -int ieee80211_if_remove_norm(struct net_device *dev, char *name, int locked); -int ieee80211_if_flush(struct net_device *dev, int locked); -int ieee80211_if_update_wds(struct net_device *dev, char *name, - struct ieee80211_if_wds *wds, int locked); - -/* ieee80211_ioctl.c */ -int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -/* Set hw encryption from ieee80211 */ -int ieee80211_set_hw_encryption(struct net_device *dev, - struct sta_info *sta, u8 addr[ETH_ALEN], - struct ieee80211_key *key); - -/* ieee80211_scan.c */ -void ieee80211_init_scan(struct net_device *dev); -void ieee80211_stop_scan(struct net_device *dev); - - - -/* Least common multiple of the used rates (in 100 kbps). This is used to - * calculate rate_inv values for each rate so that only integers are needed. */ -#define CHAN_UTIL_RATE_LCM 95040 -/* 1 usec is 1/8 * (95040/10) = 1188 */ -#define CHAN_UTIL_PER_USEC 1188 -/* Amount of bits to shift the result right to scale the total utilization - * to values that will not wrap around 32-bit integers. */ -#define CHAN_UTIL_SHIFT 9 -/* Theoretical maximum of channel utilization counter in 10 ms (stat_time=1): - * (CHAN_UTIL_PER_USEC * 10000) >> CHAN_UTIL_SHIFT = 23203. So dividing the - * raw value with about 23 should give utilization in 10th of a percentage - * (1/1000). However, utilization is only estimated and not all intervals - * between frames etc. are calculated. 18 seems to give numbers that are closer - * to the real maximum. */ -#define CHAN_UTIL_PER_10MS 18 -#define CHAN_UTIL_HDR_LONG (202 * CHAN_UTIL_PER_USEC) -#define CHAN_UTIL_HDR_SHORT (40 * CHAN_UTIL_PER_USEC) - - - -/* ieee80211.c */ -int ieee80211_if_add_sta(struct net_device *dev, char *name, int locked); -int ieee80211_if_remove_sta(struct net_device *dev, char *name, int locked); -/* ieee80211_ioctl.c */ -int ieee80211_set_compression(struct ieee80211_local *local, - struct net_device *dev, struct sta_info *sta); -/* ieee80211_sta.c */ -void ieee80211_sta_timer(unsigned long ptr); -void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status); -int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len); -int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len); -int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid); -int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); -int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len); -void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status); -void ieee80211_rx_bss_list_init(struct net_device *dev); -void ieee80211_rx_bss_list_deinit(struct net_device *dev); -int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); -struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, - struct sk_buff *skb, u8 *bssid, - u8 *addr); -int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason); -int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); - - -#endif /* IEEE80211_I_H */ diff --git a/target/linux/package/ieee80211-dscape/src/ieee80211_ioctl.c b/target/linux/package/ieee80211-dscape/src/ieee80211_ioctl.c deleted file mode 100644 index a44b02e8ee..0000000000 --- a/target/linux/package/ieee80211-dscape/src/ieee80211_ioctl.c +++ /dev/null @@ -1,2832 +0,0 @@ -/* - * Copyright 2002-2005, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "ieee80211_i.h" -#include "hostapd_ioctl.h" -#include "rate_control.h" -#include "wpa.h" -#include "aes_ccm.h" - - -static int ieee80211_regdom = 0x10; /* FCC */ -MODULE_PARM(ieee80211_regdom, "i"); -MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain; 64=MKK"); - -/* - * If firmware is upgraded by the vendor, additional channels can be used based - * on the new Japanese regulatory rules. This is indicated by setting - * ieee80211_japan_5ghz module parameter to one when loading the 80211 kernel - * module. - */ -static int ieee80211_japan_5ghz /* = 0 */; -MODULE_PARM(ieee80211_japan_5ghz, "i"); -MODULE_PARM_DESC(ieee80211_japan_5ghz, "Vendor-updated firmware for 5 GHz"); - - -static int ieee80211_ioctl_set_beacon(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len, - int flag) -{ - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_norm *norm; - u8 **b_head, **b_tail; - int *b_head_len, *b_tail_len; - int len; - - len = ((char *) param->u.beacon.data - (char *) param) + - param->u.beacon.head_len + param->u.beacon.tail_len; - - if (param_len > len) - param_len = len; - else if (param_len != len) - return -EINVAL; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_SUB_IF_TYPE_NORM) - return -EINVAL; - norm = &sdata->u.norm; - - switch (flag) { - case 0: - b_head = &norm->beacon_head; - b_tail = &norm->beacon_tail; - b_head_len = &norm->beacon_head_len; - b_tail_len = &norm->beacon_tail_len; - break; - default: - printk(KERN_DEBUG "%s: unknown beacon flag %d\n", - dev->name, flag); - return -EINVAL; - } - - kfree(*b_head); - kfree(*b_tail); - *b_head = NULL; - *b_tail = NULL; - - *b_head_len = param->u.beacon.head_len; - *b_tail_len = param->u.beacon.tail_len; - - *b_head = kmalloc(*b_head_len, GFP_KERNEL); - if (*b_head) - memcpy(*b_head, param->u.beacon.data, *b_head_len); - else { - printk(KERN_DEBUG "%s: failed to allocate beacon_head\n", - dev->name); - return -ENOMEM; - } - - if (*b_tail_len > 0) { - *b_tail = kmalloc(*b_tail_len, GFP_KERNEL); - if (*b_tail) - memcpy(*b_tail, param->u.beacon.data + (*b_head_len), - (*b_tail_len)); - else { - printk(KERN_DEBUG "%s: failed to allocate " - "beacon_tail\n", dev->name); - return -ENOMEM; - } - } - - return 0; -} - - -static int ieee80211_ioctl_get_hw_features(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - struct ieee80211_local *local = dev->priv; - u8 *pos = param->u.hw_features.data; - int left = param_len - (pos - (u8 *) param); - int mode, i; - struct hostapd_ioctl_hw_modes_hdr *hdr; - struct ieee80211_rate_data *rate; - struct ieee80211_channel_data *chan; - - param->u.hw_features.flags = 0; - if (local->hw->data_nullfunc_ack) - param->u.hw_features.flags |= HOSTAP_HW_FLAG_NULLFUNC_OK; - - param->u.hw_features.num_modes = local->hw->num_modes; - for (mode = 0; mode < local->hw->num_modes; mode++) { - int clen, rlen; - struct ieee80211_hw_modes *m = &local->hw->modes[mode]; - clen = m->num_channels * sizeof(struct ieee80211_channel_data); - rlen = m->num_rates * sizeof(struct ieee80211_rate_data); - if (left < sizeof(*hdr) + clen + rlen) - return -E2BIG; - left -= sizeof(*hdr) + clen + rlen; - - hdr = (struct hostapd_ioctl_hw_modes_hdr *) pos; - hdr->mode = m->mode; - hdr->num_channels = m->num_channels; - hdr->num_rates = m->num_rates; - - pos = (u8 *) (hdr + 1); - chan = (struct ieee80211_channel_data *) pos; - for (i = 0; i < m->num_channels; i++) { - chan[i].chan = m->channels[i].chan; - chan[i].freq = m->channels[i].freq; - chan[i].flag = m->channels[i].flag; - } - pos += clen; - - rate = (struct ieee80211_rate_data *) pos; - for (i = 0; i < m->num_rates; i++) { - rate[i].rate = m->rates[i].rate; - rate[i].flags = m->rates[i].flags; - } - pos += rlen; - } - - return 0; -} - - -static int ieee80211_ioctl_scan(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - - if (local->hw->passive_scan == NULL) - return -EOPNOTSUPP; - - if ((param->u.scan.now == 1) && (local->scan.in_scan == 1)) - return -EBUSY; - - if (param->u.scan.our_mode_only >= 0) - local->scan.our_mode_only = param->u.scan.our_mode_only; - if (param->u.scan.interval >= 0) - local->scan.interval = param->u.scan.interval; - if (param->u.scan.listen >= 0) - local->scan.time = param->u.scan.listen; - if (param->u.scan.channel > 0) - local->scan.channel = param->u.scan.channel; - if (param->u.scan.now == 1) { - local->scan.in_scan = 0; - mod_timer(&local->scan.timer, jiffies); - } - - param->u.scan.our_mode_only = local->scan.our_mode_only; - param->u.scan.interval = local->scan.interval; - param->u.scan.listen = local->scan.time; - if (local->scan.in_scan == 1) - param->u.scan.last_rx = -1; - else { - param->u.scan.last_rx = local->scan.rx_packets; - local->scan.rx_packets = -1; - } - param->u.scan.channel = local->hw->modes[local->scan.mode_idx]. - channels[local->scan.chan_idx].chan; - - return 0; -} - - -static int ieee80211_ioctl_flush(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - sta_info_flush(local, NULL); - return 0; -} - - - - -static int ieee80211_ioctl_add_sta(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - u32 rates; - int i, j; - struct ieee80211_sub_if_data *sdata; - int add_key_entry = 1; - - sta = sta_info_get(local, param->sta_addr); - - if (sta == NULL) { - sta = sta_info_add(local, dev, param->sta_addr); - if (sta == NULL) - return -ENOMEM; - } - - if (sta->dev != dev) { - /* Binding STA to a new interface, so remove all references to - * the old BSS. */ - sta_info_remove_aid_ptr(sta); - } - - /* TODO - * We "steal" the device in case someone owns it - * This will hurt WDS links and such when we have a - * WDS link and a client associating from the same station - */ - sta->dev = dev; - sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); - - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - sta->aid = param->u.add_sta.aid; - if (sta->aid > MAX_AID_TABLE_SIZE) - sta->aid = 0; - if (sta->aid > 0 && sdata->bss) - sdata->bss->sta_aid[sta->aid - 1] = sta; - if (sdata->bss && sta->aid > sdata->bss->max_aid) - sdata->bss->max_aid = sta->aid; - - rates = 0; - for (i = 0; i < sizeof(param->u.add_sta.supp_rates); i++) { - int rate = (param->u.add_sta.supp_rates[i] & 0x7f) * 5; - if (local->conf.phymode == MODE_ATHEROS_TURBO || - local->conf.phymode == MODE_ATHEROS_TURBOG) - rate *= 2; - for (j = 0; j < local->num_curr_rates; j++) { - if (local->curr_rates[j].rate == rate) - rates |= BIT(j); - } - - } - sta->supp_rates = rates; - - rate_control_rate_init(local, sta); - - - - if (param->u.add_sta.wds_flags & 0x01) - sta->flags |= WLAN_STA_WDS; - else - sta->flags &= ~WLAN_STA_WDS; - - if (add_key_entry && sta->key == NULL && sdata->default_key == NULL && - local->hw->set_key) { - struct ieee80211_key_conf conf; - /* Add key cache entry with NULL key type because this may used - * for TX filtering. */ - memset(&conf, 0, sizeof(conf)); - conf.hw_key_idx = HW_KEY_IDX_INVALID; - conf.alg = ALG_NULL; - conf.force_sw_encrypt = 1; - if (local->hw->set_key(dev, SET_KEY, sta->addr, &conf, - sta->aid)) { - sta->key_idx_compression = HW_KEY_IDX_INVALID; - } else { - sta->key_idx_compression = conf.hw_key_idx; - } - } - - sta_info_release(local, sta); - - return 0; -} - - -static int ieee80211_ioctl_remove_sta(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - - sta = sta_info_get(local, param->sta_addr); - if (sta) { - sta_info_release(local, sta); - sta_info_free(local, sta, 1); - } - - return sta ? 0 : -ENOENT; -} - - -static int ieee80211_ioctl_get_dot11counterstable(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_low_level_stats stats; - - memset(&stats, 0, sizeof(stats)); - if (local->hw->get_stats) - local->hw->get_stats(dev, &stats); - param->u.dot11CountersTable.dot11TransmittedFragmentCount = - local->dot11TransmittedFragmentCount; - param->u.dot11CountersTable.dot11MulticastTransmittedFrameCount = - local->dot11MulticastTransmittedFrameCount; - param->u.dot11CountersTable.dot11ReceivedFragmentCount = - local->dot11ReceivedFragmentCount; - param->u.dot11CountersTable.dot11MulticastReceivedFrameCount = - local->dot11MulticastReceivedFrameCount; - param->u.dot11CountersTable.dot11TransmittedFrameCount = - local->dot11TransmittedFrameCount; - param->u.dot11CountersTable.dot11FCSErrorCount = - stats.dot11FCSErrorCount; - param->u.dot11CountersTable.dot11ACKFailureCount = - stats.dot11ACKFailureCount; - param->u.dot11CountersTable.dot11RTSFailureCount = - stats.dot11RTSFailureCount; - param->u.dot11CountersTable.dot11RTSSuccessCount = - stats.dot11RTSSuccessCount; - - return 0; -} - -static int ieee80211_ioctl_get_info_sta(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - struct ieee80211_sub_if_data *sdata; - struct net_device_stats *stats; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - stats = ieee80211_dev_stats(sdata->master); - param->u.get_info_sta.rx_bytes = stats->rx_bytes; - param->u.get_info_sta.tx_bytes = stats->tx_bytes; - /* go through all STAs and get STA with lowest max. rate */ - param->u.get_info_sta.current_tx_rate = - local->curr_rates[sta_info_min_txrate_get(local)].rate; - return 0; - } - - sta = sta_info_get(local, param->sta_addr); - - if (!sta) - return -ENOENT; - - param->u.get_info_sta.inactive_msec = - jiffies_to_msecs(jiffies - sta->last_rx); - param->u.get_info_sta.rx_packets = sta->rx_packets; - param->u.get_info_sta.tx_packets = sta->tx_packets; - param->u.get_info_sta.rx_bytes = sta->rx_bytes; - param->u.get_info_sta.tx_bytes = sta->tx_bytes; - param->u.get_info_sta.channel_use = sta->channel_use; - param->u.get_info_sta.flags = sta->flags; - if (sta->txrate >= 0 && sta->txrate < local->num_curr_rates) - param->u.get_info_sta.current_tx_rate = - local->curr_rates[sta->txrate].rate; - param->u.get_info_sta.num_ps_buf_frames = - skb_queue_len(&sta->ps_tx_buf); - param->u.get_info_sta.tx_retry_failed = sta->tx_retry_failed; - param->u.get_info_sta.tx_retry_count = sta->tx_retry_count; - param->u.get_info_sta.last_rssi = sta->last_rssi; - param->u.get_info_sta.last_ack_rssi = sta->last_ack_rssi[2]; - - sta_info_release(local, sta); - - return 0; -} - - -static int ieee80211_ioctl_set_flags_sta(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - - sta = sta_info_get(local, param->sta_addr); - if (sta) { - sta->flags |= param->u.set_flags_sta.flags_or; - sta->flags &= param->u.set_flags_sta.flags_and; - if (local->hw->set_port_auth && - (param->u.set_flags_sta.flags_or & WLAN_STA_AUTHORIZED) && - local->hw->set_port_auth(local->mdev, sta->addr, 1)) - printk(KERN_DEBUG "%s: failed to set low-level driver " - "PAE state (authorized) for " MACSTR "\n", - dev->name, MAC2STR(sta->addr)); - if (local->hw->set_port_auth && - !(param->u.set_flags_sta.flags_and & WLAN_STA_AUTHORIZED) - && local->hw->set_port_auth(local->mdev, sta->addr, 0)) - printk(KERN_DEBUG "%s: failed to set low-level driver " - "PAE state (unauthorized) for " MACSTR "\n", - dev->name, MAC2STR(sta->addr)); - sta_info_release(local, sta); - } - - return sta ? 0 : -ENOENT; -} - - -int ieee80211_set_hw_encryption(struct net_device *dev, - struct sta_info *sta, u8 addr[ETH_ALEN], - struct ieee80211_key *key) -{ - struct ieee80211_key_conf *keyconf = NULL; - struct ieee80211_local *local = dev->priv; - int rc = 0; - - /* default to sw encryption; this will be cleared by low-level - * driver if the hw supports requested encryption */ - if (key) - key->force_sw_encrypt = 1; - - if (key && local->hw->set_key && - (!local->conf.sw_encrypt || !local->conf.sw_decrypt) && - (keyconf = ieee80211_key_data2conf(local, key)) != NULL) { - if (local->hw->set_key(dev, SET_KEY, addr, - keyconf, sta ? sta->aid : 0)) { - rc = HOSTAP_CRYPT_ERR_KEY_SET_FAILED; - key->force_sw_encrypt = 1; - key->hw_key_idx = HW_KEY_IDX_INVALID; - } else { - key->force_sw_encrypt = - keyconf->force_sw_encrypt; - key->hw_key_idx = - keyconf->hw_key_idx; - - } - } - kfree(keyconf); - - return rc; -} - - -static int ieee80211_ioctl_set_encryption(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - struct ieee80211_local *local = dev->priv; - int alg, ret = 0; - struct sta_info *sta; - struct ieee80211_key **key; - int set_tx_key = 0, try_hwaccel = 1; - struct ieee80211_key_conf *keyconf; - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - param->u.crypt.err = 0; - param->u.crypt.alg[HOSTAP_CRYPT_ALG_NAME_LEN - 1] = '\0'; - - if (param_len < - (int) ((char *) param->u.crypt.key - (char *) param) + - param->u.crypt.key_len) { - printk(KERN_DEBUG "%s: set_encrypt - invalid param_lem\n", - dev->name); - return -EINVAL; - } - - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - sta = NULL; - if (param->u.crypt.idx >= NUM_DEFAULT_KEYS) { - printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", - dev->name, param->u.crypt.idx); - return -EINVAL; - } - key = &sdata->keys[param->u.crypt.idx]; - if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) - set_tx_key = 1; - - /* Disable hwaccel for default keys when the interface is not - * the default one. - * TODO: consider adding hwaccel support for these; at least - * Atheros key cache should be able to handle this since AP is - * only transmitting frames with default keys. */ - /* FIX: hw key cache can be used when only one virtual - * STA is associated with each AP. If more than one STA - * is associated to the same AP, software encryption - * must be used. This should be done automatically - * based on configured station devices. For the time - * being, this can be only set at compile time. */ - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - if (0 /* FIX: more than one STA per AP */) - try_hwaccel = 0; - } else - if (sdata->type != IEEE80211_SUB_IF_TYPE_NORM || - dev != local->wdev) - try_hwaccel = 0; - } else { - if (param->u.crypt.idx != 0) { - printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for " - "individual key\n", dev->name); - return -EINVAL; - } - - sta = sta_info_get(local, param->sta_addr); - if (sta == NULL) { - param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: set_encrypt - unknown addr " - MACSTR "\n", - dev->name, MAC2STR(param->sta_addr)); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - - return -ENOENT; - } - - key = &sta->key; - } - - if (strcmp(param->u.crypt.alg, "none") == 0) { - alg = ALG_NONE; - } else if (strcmp(param->u.crypt.alg, "WEP") == 0) { - alg = ALG_WEP; - } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { - if (param->u.crypt.key_len != ALG_TKIP_KEY_LEN) { - printk(KERN_DEBUG "%s: set_encrypt - invalid TKIP key " - "length %d\n", dev->name, - param->u.crypt.key_len); - ret = -EINVAL; - goto done; - } - alg = ALG_TKIP; - } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { - if (param->u.crypt.key_len != ALG_CCMP_KEY_LEN) { - printk(KERN_DEBUG "%s: set_encrypt - invalid CCMP key " - "length %d\n", dev->name, - param->u.crypt.key_len); - ret = -EINVAL; - goto done; - } - alg = ALG_CCMP; - } else { - param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ALG; - printk(KERN_DEBUG "%s: set_encrypt - unknown alg\n", - dev->name); - ret = -EINVAL; - goto done; - } - - /* FIX: - * Cannot configure default hwaccel keys with WEP algorithm, if - * any of the virtual interfaces is using static WEP - * configuration because hwaccel would otherwise try to decrypt - * these frames. - * - * For now, just disable WEP hwaccel for broadcast when there is - * possibility of conflict with default keys. This can maybe later be - * optimized by using non-default keys (at least with Atheros ar521x). - */ - if (!sta && alg == ALG_WEP && !local->default_wep_only && - local->conf.mode != IW_MODE_ADHOC && - local->conf.mode != IW_MODE_INFRA) { - try_hwaccel = 0; - } - - if (local->hw->device_hides_wep) { - /* Software encryption cannot be used with devices that hide - * encryption from the host system, so always try to use - * hardware acceleration with such devices. */ - try_hwaccel = 1; - } - - if (local->hw->no_tkip_wmm_hwaccel && alg == ALG_TKIP) { - if (sta && (sta->flags & WLAN_STA_WME)) { - /* Hardware does not support hwaccel with TKIP when using WMM. - */ - try_hwaccel = 0; - } - else if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - sta = sta_info_get(local, sdata->u.sta.bssid); - if (sta) { - if (sta->flags & WLAN_STA_WME) { - try_hwaccel = 0; - } - sta_info_release(local, sta); - sta = NULL; - } - } - } - - - if (alg == ALG_NONE) { - keyconf = NULL; - if (try_hwaccel && *key && local->hw->set_key && - (keyconf = ieee80211_key_data2conf(local, *key)) != NULL && - local->hw->set_key(dev, DISABLE_KEY, param->sta_addr, - keyconf, sta ? sta->aid : 0)) { - param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED; - printk(KERN_DEBUG "%s: set_encrypt - low-level disable" - " failed\n", dev->name); - ret = -EINVAL; - } - kfree(keyconf); - - if (sdata->default_key == *key) - sdata->default_key = NULL; - kfree(*key); - *key = NULL; - } else { - if (*key == NULL || (*key)->keylen < param->u.crypt.key_len) { - kfree(*key); - *key = kmalloc(sizeof(struct ieee80211_key) + - param->u.crypt.key_len, GFP_ATOMIC); - if (*key == NULL) { - ret = -ENOMEM; - goto done; - } - } - memset(*key, 0, sizeof(struct ieee80211_key) + - param->u.crypt.key_len); - /* default to sw encryption; low-level driver sets these if the - * requested encryption is supported */ - (*key)->hw_key_idx = HW_KEY_IDX_INVALID; - (*key)->force_sw_encrypt = 1; - - (*key)->alg = alg; - (*key)->keyidx = param->u.crypt.idx; - (*key)->keylen = param->u.crypt.key_len; - memcpy((*key)->key, param->u.crypt.key, - param->u.crypt.key_len); - if (set_tx_key) - (*key)->default_tx_key = 1; - - if (alg == ALG_CCMP) { - /* Initialize AES key state here as an optimization - * so that it does not need to be initialized for every - * packet. */ - ieee80211_aes_key_setup_encrypt( - (*key)->u.ccmp.aes_state, (*key)->key); - } - - if (try_hwaccel && - (alg == ALG_WEP || alg == ALG_TKIP || alg == ALG_CCMP)) - param->u.crypt.err = ieee80211_set_hw_encryption( - dev, sta, param->sta_addr, *key); - } - - if (set_tx_key || (sta == NULL && sdata->default_key == NULL)) { - sdata->default_key = *key; - if (local->hw->set_key_idx && - local->hw->set_key_idx(dev, param->u.crypt.idx)) - printk(KERN_DEBUG "%s: failed to set TX key idx for " - "low-level driver\n", dev->name); - } - - done: - if (sta) - sta_info_release(local, sta); - - return ret; -} - -static int ieee80211_ioctl_get_encryption(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - struct ieee80211_local *local = dev->priv; - int ret = 0; - struct sta_info *sta; - struct ieee80211_key **key; - int max_key_len; - struct ieee80211_sub_if_data *sdata; - u8 *pos; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - param->u.crypt.err = 0; - - max_key_len = param_len - - (int) ((char *) param->u.crypt.key - (char *) param); - if (max_key_len < 0) - return -EINVAL; - - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - sta = NULL; - if (param->u.crypt.idx > NUM_DEFAULT_KEYS) { - param->u.crypt.idx = sdata->default_key ? - sdata->default_key->keyidx : 0; - return 0; - } else - key = &sdata->keys[param->u.crypt.idx]; - } else { - sta = sta_info_get(local, param->sta_addr); - if (sta == NULL) { - param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; - return -EINVAL; - } - - key = &sta->key; - } - - - memset(param->u.crypt.seq_counter, 0, HOSTAP_SEQ_COUNTER_SIZE); - if (*key == NULL) { - memcpy(param->u.crypt.alg, "none", 5); - param->u.crypt.key_len = 0; - param->u.crypt.idx = 0xff; - } else { - switch ((*key)->alg) { - case ALG_WEP: - memcpy(param->u.crypt.alg, "WEP", 4); - break; - case ALG_TKIP: - { - u32 iv32; - u16 iv16; - - memcpy(param->u.crypt.alg, "TKIP", 5); - if (local->hw->get_sequence_counter) { - /* Get transmit counter from low level driver */ - if (local->hw->get_sequence_counter(dev, - param->sta_addr, - (*key)->keyidx, - IEEE80211_SEQ_COUNTER_TX, - &iv32, - &iv16)) { - /* Error getting value from device */ - return -EIO; - } - } else { - /* Get it from our own local data */ - iv32 = (*key)->u.tkip.iv32; - iv16 = (*key)->u.tkip.iv16; - } - pos = param->u.crypt.seq_counter; - *pos++ = iv16 & 0xff; - *pos++ = (iv16 >> 8) & 0xff; - *pos++ = iv32 & 0xff; - *pos++ = (iv32 >> 8) & 0xff; - *pos++ = (iv32 >> 16) & 0xff; - *pos++ = (iv32 >> 24) & 0xff; - break; - } - case ALG_CCMP: - { - u8 *pn; - memcpy(param->u.crypt.alg, "CCMP", 5); - pos = param->u.crypt.seq_counter; - pn = (*key)->u.ccmp.tx_pn; - *pos++ = pn[5]; - *pos++ = pn[4]; - *pos++ = pn[3]; - *pos++ = pn[2]; - *pos++ = pn[1]; - *pos++ = pn[0]; - break; - } - default: - memcpy(param->u.crypt.alg, "unknown", 8); - break; - } - - if (max_key_len < (*key)->keylen) - ret = -E2BIG; - else { - param->u.crypt.key_len = (*key)->keylen; - memcpy(param->u.crypt.key, (*key)->key, - (*key)->keylen); - } - } - - if (sta) - sta_info_release(local, sta); - - return ret; -} - - -#ifdef CONFIG_HOSTAPD_WPA_TESTING -static int ieee80211_ioctl_wpa_trigger(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - local->wpa_trigger = param->u.wpa_trigger.trigger; - return 0; - } - - sta = sta_info_get(local, param->sta_addr); - if (sta == NULL) { - printk(KERN_DEBUG "%s: wpa_trigger - unknown addr\n", - dev->name); - return -EINVAL; - } - - sta->wpa_trigger = param->u.wpa_trigger.trigger; - - sta_info_release(local, sta); - return 0; -} -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - -static int ieee80211_ioctl_set_rate_sets(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - struct ieee80211_local *local = dev->priv; - u16 *pos = (u16 *) param->u.set_rate_sets.data; - int left = param_len - ((u8 *) pos - (u8 *) param); - int i, mode, num_supp, num_basic, *supp, *basic, *prev; - - mode = param->u.set_rate_sets.mode; - num_supp = param->u.set_rate_sets.num_supported_rates; - num_basic = param->u.set_rate_sets.num_basic_rates; - - if (left < (num_supp + num_basic) * 2) { - printk(KERN_WARNING "%s: invalid length in hostapd set rate " - "sets ioctl (%d != %d)\n", dev->name, left, - (num_supp + num_basic) * 2); - return -EINVAL; - } - - supp = (int *) kmalloc((num_supp + 1) * sizeof(int), GFP_KERNEL); - basic = (int *) kmalloc((num_basic + 1) * sizeof(int), GFP_KERNEL); - - if (!supp || !basic) { - kfree(supp); - kfree(basic); - return -ENOMEM; - } - - for (i = 0; i < num_supp; i++) - supp[i] = *pos++; - supp[i] = -1; - - for (i = 0; i < num_basic; i++) - basic[i] = *pos++; - basic[i] = -1; - - if (num_supp == 0) { - kfree(supp); - supp = NULL; - } - - if (num_basic == 0) { - kfree(basic); - basic = NULL; - } - - prev = local->supp_rates[mode]; - local->supp_rates[mode] = supp; - kfree(prev); - - prev = local->basic_rates[mode]; - local->basic_rates[mode] = basic; - kfree(prev); - - if (mode == local->conf.phymode) { - /* TODO: should update STA TX rates and remove STAs if they - * do not have any remaining supported rates after the change - */ - ieee80211_prepare_rates(dev); - } - - return 0; -} - - -static int ieee80211_ioctl_add_if(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - u8 *pos = param->u.if_info.data; - int left = param_len - ((u8 *) pos - (u8 *) param); - - if (param->u.if_info.type == HOSTAP_IF_WDS) { - struct ieee80211_if_wds iwds; - struct hostapd_if_wds *wds = - (struct hostapd_if_wds *) param->u.if_info.data; - - if (left < sizeof(struct ieee80211_if_wds)) - return -EPROTO; - - memcpy(iwds.remote_addr, wds->remote_addr, ETH_ALEN); - - return ieee80211_if_add_wds(dev, param->u.if_info.name, - &iwds, 1); - } else if (param->u.if_info.type == HOSTAP_IF_VLAN) { - struct hostapd_if_vlan *vlan = (struct hostapd_if_vlan *) pos; - struct ieee80211_if_vlan ivlan; - - if (left < sizeof(struct hostapd_if_vlan)) - return -EPROTO; - - ivlan.id = vlan->id; - - return ieee80211_if_add_vlan(dev, param->u.if_info.name, - &ivlan, 1); - } else if (param->u.if_info.type == HOSTAP_IF_BSS) { - struct hostapd_if_bss *bss = - (struct hostapd_if_bss *) param->u.if_info.data; - - if (left < sizeof(struct hostapd_if_bss)) - return -EPROTO; - - return ieee80211_if_add_norm(dev, param->u.if_info.name, - bss->bssid, 1); - } else if (param->u.if_info.type == HOSTAP_IF_STA) { -#if 0 - struct hostapd_if_sta *sta = - (struct hostapd_if_sta *) param->u.if_info.data; -#endif - - if (left < sizeof(struct hostapd_if_sta)) - return -EPROTO; - - return ieee80211_if_add_sta(dev, param->u.if_info.name, 1); - } else - return -EINVAL; - - return 0; -} - - -static int ieee80211_ioctl_remove_if(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - if (param->u.if_info.type == HOSTAP_IF_WDS) { - return ieee80211_if_remove_wds(dev, param->u.if_info.name, 1); - } else if (param->u.if_info.type == HOSTAP_IF_VLAN) { - return ieee80211_if_remove_vlan(dev, param->u.if_info.name, 1); - } else if (param->u.if_info.type == HOSTAP_IF_BSS) { - return ieee80211_if_remove_norm(dev, param->u.if_info.name, 1); - } else if (param->u.if_info.type == HOSTAP_IF_STA) { - return ieee80211_if_remove_sta(dev, param->u.if_info.name, 1); - } else { - return -EINVAL; - } -} - - -static int ieee80211_ioctl_update_if(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - u8 *pos = param->u.if_info.data; - int left = param_len - ((u8 *) pos - (u8 *) param); - - if (param->u.if_info.type == HOSTAP_IF_WDS) { - struct ieee80211_if_wds iwds; - struct hostapd_if_wds *wds = - (struct hostapd_if_wds *) param->u.if_info.data; - - if (left < sizeof(struct ieee80211_if_wds)) - return -EPROTO; - - memcpy(iwds.remote_addr, wds->remote_addr, ETH_ALEN); - - return ieee80211_if_update_wds(dev, param->u.if_info.name, - &iwds, 1); - } else { - return -EOPNOTSUPP; - } -} - - -static int ieee80211_ioctl_flush_ifs(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - return ieee80211_if_flush(dev, 1); -} - - -static int ieee80211_ioctl_scan_req(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - u8 *pos = param->u.scan_req.ssid; - int left = param_len - ((u8 *) pos - (u8 *) param); - int len = param->u.scan_req.ssid_len; - - if (left < len || len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; - - return ieee80211_sta_req_scan(dev, pos, len); -} - - -static int ieee80211_ioctl_sta_get_state(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - return -EINVAL; - param->u.sta_get_state.state = sdata->u.sta.state; - return 0; -} - - -static int ieee80211_ioctl_mlme(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - return -EINVAL; - switch (param->u.mlme.cmd) { - case MLME_STA_DEAUTH: - ieee80211_sta_deauthenticate(dev, param->u.mlme.reason_code); - break; - case MLME_STA_DISASSOC: - ieee80211_sta_disassociate(dev, param->u.mlme.reason_code); - break; - } - return 0; -} - - -static int ieee80211_ioctl_get_load_stats(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - - param->u.get_load_stats.channel_use = local->channel_use; -/* if (param->u.get_load_stats.flags & LOAD_STATS_CLEAR) - local->channel_use = 0; */ /* now it's not raw counter */ - - return 0; -} - - -static int ieee80211_ioctl_set_sta_vlan(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - - sta = sta_info_get(local, param->sta_addr); - if (sta) { - struct net_device *new_vlan_dev; - new_vlan_dev = - dev_get_by_name(param->u.set_sta_vlan.vlan_name); - if (new_vlan_dev) { -#if 0 - printk("%s: Station " MACSTR " moved to vlan: %s\n", - dev->name, MAC2STR(param->sta_addr), - new_vlan_dev->name); -#endif - sta->dev = new_vlan_dev; - sta->vlan_id = param->u.set_sta_vlan.vlan_id; - dev_put(new_vlan_dev); - } - sta_info_release(local, sta); - } - - return sta ? 0 : -ENOENT; -} - - -static int -ieee80211_ioctl_set_generic_info_elem(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - struct ieee80211_local *local = dev->priv; - u8 *pos = param->u.set_generic_info_elem.data; - int left = param_len - ((u8 *) pos - (u8 *) param); - int len = param->u.set_generic_info_elem.len; - - if (left < len) - return -EINVAL; - - { - struct ieee80211_sub_if_data *sdata; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) - return ieee80211_sta_set_extra_ie(dev, pos, len); - } - kfree(local->conf.generic_elem); - local->conf.generic_elem = kmalloc(len, GFP_KERNEL); - if (local->conf.generic_elem == NULL) - return -ENOMEM; - memcpy(local->conf.generic_elem, pos, len); - local->conf.generic_elem_len = len; - - return ieee80211_hw_config(dev); -} - - -static int ieee80211_ioctl_set_regulatory_domain(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev); - conf->regulatory_domain = param->u.set_regulatory_domain.rd; - return 0; -} - - -static int ieee80211_ioctl_set_adm_status(struct net_device *dev, - int val) -{ - struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev); - conf->adm_status = val; - return ieee80211_hw_config(dev); -} - -static int -ieee80211_ioctl_set_tx_queue_params(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_tx_queue_params qparam; - - if (!local->hw->conf_tx) { - printk(KERN_DEBUG "%s: low-level driver does not support TX " - "queue configuration\n", dev->name); - return -EOPNOTSUPP; - } - - memset(&qparam, 0, sizeof(qparam)); - qparam.aifs = param->u.tx_queue_params.aifs; - qparam.cw_min = param->u.tx_queue_params.cw_min; - qparam.cw_max = param->u.tx_queue_params.cw_max; - qparam.burst_time = param->u.tx_queue_params.burst_time; - - return local->hw->conf_tx(dev, param->u.tx_queue_params.queue, - &qparam); -} - - -static int ieee80211_ioctl_get_tx_stats(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_tx_queue_stats stats; - int ret, i; - - if (!local->hw->get_tx_stats) - return -EOPNOTSUPP; - - memset(&stats, 0, sizeof(stats)); - ret = local->hw->get_tx_stats(dev, &stats); - if (ret) - return ret; - - for (i = 0; i < 4; i++) { - param->u.get_tx_stats.data[i].len = stats.data[i].len; - param->u.get_tx_stats.data[i].limit = stats.data[i].limit; - param->u.get_tx_stats.data[i].count = stats.data[i].count; - } - - return 0; -} - - -static int ieee80211_ioctl_set_bss(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev); - int i, bss_count; - int new_count = param->u.set_bss.bss_count; - struct net_device **bss_devs, **prev; - struct net_device **sta_devs, **prev_sta_devs; - - bss_count = 0; - for (i = 0; i < conf->bss_count; i++) { - if (local->bss_devs[i]) - bss_count++; - } - - if (new_count < bss_count) { - printk(KERN_DEBUG "%s: invalid BSS count %d (in use: %d)\n", - dev->name, new_count, bss_count); - return -EINVAL; - } - - bss_devs = kmalloc(new_count * sizeof(struct net_device *), - GFP_KERNEL); - if (bss_devs == NULL) - return -ENOMEM; - sta_devs = kmalloc(new_count * sizeof(struct net_device *), - GFP_KERNEL); - if (sta_devs == NULL) { - kfree(bss_devs); - return -ENOMEM; - } - - spin_lock_bh(&local->sub_if_lock); - memcpy(bss_devs, local->bss_devs, - bss_count * sizeof(struct net_device *)); - memset(&bss_devs[bss_count], 0, - (new_count - bss_count) * sizeof(struct net_device *)); - - memcpy(conf->bssid_mask, param->u.set_bss.bssid_mask, ETH_ALEN); - - prev = local->bss_devs; - local->bss_devs = bss_devs; - conf->bss_count = new_count; - - memcpy(sta_devs, local->sta_devs, - bss_count * sizeof(struct net_device *)); - memset(&sta_devs[bss_count], 0, - (new_count - bss_count) * sizeof(struct net_device *)); - prev_sta_devs = local->sta_devs; - local->sta_devs = sta_devs; - - spin_unlock_bh(&local->sub_if_lock); - kfree(prev); - kfree(prev_sta_devs); - - return ieee80211_hw_config(dev); -} - - -static int ieee80211_ioctl_set_channel_flag(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_hw_modes *mode = NULL; - struct ieee80211_channel *chan = NULL; - int i; - - for (i = 0; i < local->hw->num_modes; i++) { - mode = &local->hw->modes[i]; - if (mode->mode == param->u.set_channel_flag.mode) - break; - mode = NULL; - } - - if (!mode) - return -ENOENT; - - for (i = 0; i < mode->num_channels; i++) { - chan = &mode->channels[i]; - if (chan->chan == param->u.set_channel_flag.chan) - break; - chan = NULL; - } - - if (!chan) - return -ENOENT; - - chan->flag = param->u.set_channel_flag.flag; - chan->power_level = param->u.set_channel_flag.power_level; - chan->antenna_max = param->u.set_channel_flag.antenna_max; - - return 0; -} - - -static int ieee80211_ioctl_set_quiet_params(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev); - conf->quiet_duration = param->u.quiet.duration; - conf->quiet_offset = param->u.quiet.offset; - conf->quiet_period = param->u.quiet.period; - return 0; -} - - -static int ieee80211_ioctl_set_radar_params(struct net_device *dev, - struct prism2_hostapd_param *param) -{ - /* struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev); */ - return 0; -} - - -static int ieee80211_ioctl_priv_hostapd(struct net_device *dev, - struct iw_point *p) -{ - struct prism2_hostapd_param *param; - int ret = 0; - - if (p->length < sizeof(struct prism2_hostapd_param) || - p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) { - printk(KERN_DEBUG "%s: hostapd ioctl: ptr=%p len=%d min=%d " - "max=%d\n", dev->name, p->pointer, p->length, - (int)sizeof(struct prism2_hostapd_param), - PRISM2_HOSTAPD_MAX_BUF_SIZE); - return -EINVAL; - } - - param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL); - if (param == NULL) - return -ENOMEM; - - if (copy_from_user(param, p->pointer, p->length)) { - ret = -EFAULT; - goto out; - } - - switch (param->cmd) { - case PRISM2_HOSTAPD_FLUSH: - ret = ieee80211_ioctl_flush(dev, param); - break; - case PRISM2_HOSTAPD_ADD_STA: - ret = ieee80211_ioctl_add_sta(dev, param); - break; - case PRISM2_HOSTAPD_REMOVE_STA: - ret = ieee80211_ioctl_remove_sta(dev, param); - break; - case PRISM2_HOSTAPD_GET_INFO_STA: - ret = ieee80211_ioctl_get_info_sta(dev, param); - break; - case PRISM2_SET_ENCRYPTION: - ret = ieee80211_ioctl_set_encryption(dev, param, p->length); - break; - case PRISM2_GET_ENCRYPTION: - ret = ieee80211_ioctl_get_encryption(dev, param, p->length); - break; - case PRISM2_HOSTAPD_SET_FLAGS_STA: - ret = ieee80211_ioctl_set_flags_sta(dev, param); - break; - case PRISM2_HOSTAPD_SET_BEACON: - ret = ieee80211_ioctl_set_beacon(dev, param, p->length, 0); - break; - case PRISM2_HOSTAPD_GET_HW_FEATURES: - ret = ieee80211_ioctl_get_hw_features(dev, param, p->length); - break; - case PRISM2_HOSTAPD_SCAN: - ret = ieee80211_ioctl_scan(dev, param); - break; -#ifdef CONFIG_HOSTAPD_WPA_TESTING - case PRISM2_HOSTAPD_WPA_TRIGGER: - ret = ieee80211_ioctl_wpa_trigger(dev, param); - break; -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - case PRISM2_HOSTAPD_SET_RATE_SETS: - ret = ieee80211_ioctl_set_rate_sets(dev, param, p->length); - break; - case PRISM2_HOSTAPD_ADD_IF: - ret = ieee80211_ioctl_add_if(dev, param, p->length); - break; - case PRISM2_HOSTAPD_REMOVE_IF: - ret = ieee80211_ioctl_remove_if(dev, param); - break; - case PRISM2_HOSTAPD_GET_DOT11COUNTERSTABLE: - ret = ieee80211_ioctl_get_dot11counterstable(dev, param); - break; - case PRISM2_HOSTAPD_GET_LOAD_STATS: - ret = ieee80211_ioctl_get_load_stats(dev, param); - break; - case PRISM2_HOSTAPD_SET_STA_VLAN: - ret = ieee80211_ioctl_set_sta_vlan(dev, param); - break; - case PRISM2_HOSTAPD_SET_GENERIC_INFO_ELEM: - ret = ieee80211_ioctl_set_generic_info_elem(dev, param, - p->length); - break; - case PRISM2_HOSTAPD_SET_CHANNEL_FLAG: - ret = ieee80211_ioctl_set_channel_flag(dev, param); - break; - case PRISM2_HOSTAPD_SET_REGULATORY_DOMAIN: - ret = ieee80211_ioctl_set_regulatory_domain(dev, param); - break; - case PRISM2_HOSTAPD_SET_TX_QUEUE_PARAMS: - ret = ieee80211_ioctl_set_tx_queue_params(dev, param); - break; - case PRISM2_HOSTAPD_SET_BSS: - ret = ieee80211_ioctl_set_bss(dev, param); - break; - case PRISM2_HOSTAPD_GET_TX_STATS: - ret = ieee80211_ioctl_get_tx_stats(dev, param); - break; - case PRISM2_HOSTAPD_UPDATE_IF: - ret = ieee80211_ioctl_update_if(dev, param, p->length); - break; - case PRISM2_HOSTAPD_SCAN_REQ: - ret = ieee80211_ioctl_scan_req(dev, param, p->length); - break; - case PRISM2_STA_GET_STATE: - ret = ieee80211_ioctl_sta_get_state(dev, param); - break; - case PRISM2_HOSTAPD_MLME: - ret = ieee80211_ioctl_mlme(dev, param); - break; - case PRISM2_HOSTAPD_FLUSH_IFS: - ret = ieee80211_ioctl_flush_ifs(dev, param); - break; - case PRISM2_HOSTAPD_SET_RADAR_PARAMS: - ret = ieee80211_ioctl_set_radar_params(dev, param); - break; - case PRISM2_HOSTAPD_SET_QUIET_PARAMS: - ret = ieee80211_ioctl_set_quiet_params(dev, param); - break; - default: - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(p->pointer, param, p->length)) - ret = -EFAULT; - - out: - kfree(param); - - return ret; -} - - -static int ieee80211_ioctl_giwname(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) -{ - struct ieee80211_local *local = dev->priv; - - switch (local->conf.phymode) { - case MODE_IEEE80211A: - strcpy(name, "IEEE 802.11a"); - break; - case MODE_IEEE80211B: - strcpy(name, "IEEE 802.11b"); - break; - case MODE_IEEE80211G: - strcpy(name, "IEEE 802.11g"); - break; - case MODE_ATHEROS_TURBO: - strcpy(name, "5GHz Turbo"); - break; - default: - strcpy(name, "IEEE 802.11"); - break; - } - - return 0; -} - - -static int ieee80211_ioctl_giwrange(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct iw_range *range = (struct iw_range *) extra; - - data->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 14; - range->retry_capa = IW_RETRY_LIMIT; - range->retry_flags = IW_RETRY_LIMIT; - range->min_retry = 0; - range->max_retry = 255; - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - return 0; -} - - -struct ieee80211_channel_range { - short start_freq; - short end_freq; - unsigned char power_level; - unsigned char antenna_max; -}; - -static const struct ieee80211_channel_range ieee80211_fcc_channels[] = { - { 2412, 2462, 27, 6 } /* IEEE 802.11b/g, channels 1..11 */, - { 5180, 5240, 17, 6 } /* IEEE 802.11a, channels 36..48 */, - { 5260, 5320, 23, 6 } /* IEEE 802.11a, channels 52..64 */, - { 5745, 5825, 30, 6 } /* IEEE 802.11a, channels 149..165, outdoor */, - { 0 } -}; - -static const struct ieee80211_channel_range ieee80211_mkk_channels[] = { - { 2412, 2472, 20, 6 } /* IEEE 802.11b/g, channels 1..13 */, - { 5170, 5240, 20, 6 } /* IEEE 802.11a, channels 34..48 */, - { 5260, 5320, 20, 6 } /* IEEE 802.11a, channels 52..64 */, - { 0 } -}; - - -static const struct ieee80211_channel_range *channel_range = - ieee80211_fcc_channels; - - -static void ieee80211_unmask_channel(struct net_device *dev, int mode, - struct ieee80211_channel *chan) -{ - int i; - - chan->flag = 0; - - if (ieee80211_regdom == 64 && - (mode == MODE_ATHEROS_TURBO || mode == MODE_ATHEROS_TURBOG)) { - /* Do not allow Turbo modes in Japan. */ - return; - } - - for (i = 0; channel_range[i].start_freq; i++) { - const struct ieee80211_channel_range *r = &channel_range[i]; - if (r->start_freq <= chan->freq && r->end_freq >= chan->freq) { - if (ieee80211_regdom == 64 && !ieee80211_japan_5ghz && - chan->freq >= 5260 && chan->freq <= 5320) { - /* - * Skip new channels in Japan since the - * firmware was not marked having been upgraded - * by the vendor. - */ - continue; - } - - if (ieee80211_regdom == 0x10 && - (chan->freq == 5190 || chan->freq == 5210 || - chan->freq == 5230)) { - /* Skip MKK channels when in FCC domain. */ - continue; - } - - chan->flag |= IEEE80211_CHAN_W_SCAN | - IEEE80211_CHAN_W_ACTIVE_SCAN | - IEEE80211_CHAN_W_IBSS; - chan->power_level = r->power_level; - chan->antenna_max = r->antenna_max; - - if (ieee80211_regdom == 64 && - (chan->freq == 5170 || chan->freq == 5190 || - chan->freq == 5210 || chan->freq == 5230)) { - /* - * New regulatory rules in Japan have backwards - * compatibility with old channels in 5.15-5.25 - * GHz band, but the station is not allowed to - * use active scan on these old channels. - */ - chan->flag &= ~IEEE80211_CHAN_W_ACTIVE_SCAN; - } - - if (ieee80211_regdom == 64 && - (chan->freq == 5260 || chan->freq == 5280 || - chan->freq == 5300 || chan->freq == 5320)) { - /* - * IBSS is not allowed on 5.25-5.35 GHz band - * due to radar detection requirements. - */ - chan->flag &= ~IEEE80211_CHAN_W_IBSS; - } - - break; - } - } -} - - -static int ieee80211_unmask_channels(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - int m, c; - - for (m = 0; m < local->hw->num_modes; m++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[m]; - for (c = 0; c < mode->num_channels; c++) { - ieee80211_unmask_channel(dev, mode->mode, - &mode->channels[c]); - } - } - return 0; -} - - -static int ieee80211_init_client(struct net_device *dev) -{ - if (ieee80211_regdom == 0x40) - channel_range = ieee80211_mkk_channels; - ieee80211_unmask_channels(dev); - ieee80211_ioctl_set_adm_status(dev, 1); - return 0; -} - - -static int ieee80211_is_client_mode(int iw_mode) -{ - return (iw_mode == IW_MODE_INFRA || iw_mode == IW_MODE_ADHOC); -} - - -static int ieee80211_ioctl_siwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - struct ieee80211_local *local = dev->priv; - - if (!ieee80211_is_client_mode(local->conf.mode) && - ieee80211_is_client_mode(*mode)) { - ieee80211_init_client(dev); - } - if (local->conf.mode != *mode) { - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(dev); - sta_info_flush(local, NULL); - if (local->conf.mode == IW_MODE_ADHOC && - sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - /* Clear drop_unencrypted when leaving adhoc mode since - * only adhoc mode is using automatic setting for this - * in 80211.o. */ - sdata->drop_unencrypted = 0; - } - if (*mode == IW_MODE_MASTER) { - /* AP mode does not currently use ACM bits to limit - * TX, so clear the bitfield here. */ - local->wmm_acm = 0; - } - } - local->conf.mode = *mode; - return ieee80211_hw_config(dev); -} - - -static int ieee80211_ioctl_giwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - if (local->conf.mode == IW_MODE_ADHOC) - *mode = IW_MODE_ADHOC; - else - *mode = IW_MODE_INFRA; - } else - *mode = local->conf.mode; - return 0; -} - - -int ieee80211_ioctl_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - struct ieee80211_local *local = dev->priv; - int m, c, nfreq, set = 0; - - /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ - if (freq->e == 0) - nfreq = -1; - else { - int i, div = 1000000; - for (i = 0; i < freq->e; i++) - div /= 10; - if (div > 0) - nfreq = freq->m / div; - else - return -EINVAL; - } - - for (m = 0; m < local->hw->num_modes; m++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[m]; - for (c = 0; c < mode->num_channels; c++) { - struct ieee80211_channel *chan = &mode->channels[c]; - if (chan->flag & IEEE80211_CHAN_W_SCAN && - ((freq->e == 0 && chan->chan == freq->m) || - (freq->e > 0 && nfreq == chan->freq)) && - (local->hw_modes & (1 << mode->mode))) { - /* Use next_mode as the mode preference to - * resolve non-unique channel numbers. */ - if (set && mode->mode != local->next_mode) - continue; - - local->conf.channel = chan->chan; - local->conf.channel_val = chan->val; - local->conf.power_level = chan->power_level; - local->conf.freq = chan->freq; - local->conf.phymode = mode->mode; - local->conf.antenna_max = chan->antenna_max; - set++; - } - } - } - - if (set) { - local->sta_scanning = 0; /* Abort possible scan */ - return ieee80211_hw_config(dev); - } - - return -EINVAL; -} - - -static int ieee80211_ioctl_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - struct ieee80211_local *local = dev->priv; - - /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level - * driver for the current channel with firmware-based management */ - - freq->m = local->conf.freq; - freq->e = 6; - - return 0; -} - - -static int ieee80211_ioctl_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata; - size_t len = data->length; - - /* iwconfig uses nul termination in SSID.. */ - if (len > 0 && ssid[len - 1] == '\0') - len--; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) - return ieee80211_sta_set_ssid(dev, ssid, len); - - kfree(local->conf.ssid); - local->conf.ssid = kmalloc(len + 1, GFP_KERNEL); - if (local->conf.ssid == NULL) - return -ENOMEM; - memcpy(local->conf.ssid, ssid, len); - local->conf.ssid[len] = '\0'; - local->conf.ssid_len = len; - return ieee80211_hw_config(dev); -} - - -static int ieee80211_ioctl_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid) -{ - struct ieee80211_local *local = dev->priv; - size_t len; - - struct ieee80211_sub_if_data *sdata; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - int res = ieee80211_sta_get_ssid(dev, ssid, &len); - if (res == 0) - data->length = len; - return res; - } - - len = local->conf.ssid_len; - if (len > IW_ESSID_MAX_SIZE) - len = IW_ESSID_MAX_SIZE; - memcpy(ssid, local->conf.ssid, len); - data->length = len; - return 0; -} - - -static int ieee80211_ioctl_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - int changed_bssid = 0; - if (memcmp(local->conf.client_bssid, (u8 *) &ap_addr->sa_data, - ETH_ALEN) != 0) - changed_bssid = 1; - memcpy(local->conf.client_bssid, (u8 *) &ap_addr->sa_data, - ETH_ALEN); - if (changed_bssid && ieee80211_hw_config(dev)) { - printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", dev->name); - } - return ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data); - } - - return -EOPNOTSUPP; -} - - -static int ieee80211_ioctl_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - ap_addr->sa_family = ARPHRD_ETHER; - memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN); - return 0; - } - - return -EOPNOTSUPP; -} - - -static int ieee80211_ioctl_siwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct ieee80211_local *local = dev->priv; - u8 *ssid = NULL; - size_t ssid_len = 0; - - if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { - ssid = local->conf.ssid; - ssid_len = local->conf.ssid_len; - } - return ieee80211_sta_req_scan(dev, ssid, ssid_len); -} - - -static int ieee80211_ioctl_giwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - int res; - struct ieee80211_local *local = dev->priv; - if (local->sta_scanning) - return -EAGAIN; - res = ieee80211_sta_scan_results(dev, extra, IW_SCAN_MAX_DATA); - if (res >= 0) { - data->length = res; - return 0; - } - data->length = 0; - return res; -} - - -static int ieee80211_ioctl_siwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct ieee80211_local *local = dev->priv; - - if (rts->disabled) - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) - return -EINVAL; - else - local->rts_threshold = rts->value; - - /* If the wlan card performs RTS/CTS in hardware/firmware, - * configure it here */ - - if (local->hw->set_rts_threshold) { - local->hw->set_rts_threshold(dev, local->rts_threshold); - } - - return 0; -} - -static int ieee80211_ioctl_giwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct ieee80211_local *local = dev->priv; - - rts->value = local->rts_threshold; - rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD); - rts->fixed = 1; - - return 0; -} - - -static int ieee80211_ioctl_siwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct ieee80211_local *local = dev->priv; - - if (frag->disabled) - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - else if (frag->value < 256 || - frag->value > IEEE80211_MAX_FRAG_THRESHOLD) - return -EINVAL; - else { - /* Fragment length must be even, so strip LSB. */ - local->fragmentation_threshold = frag->value & ~0x1; - } - - /* If the wlan card performs fragmentation in hardware/firmware, - * configure it here */ - - if (local->hw->set_frag_threshold) { - local->hw->set_frag_threshold( - dev, local->fragmentation_threshold); - } - - return 0; -} - -static int ieee80211_ioctl_giwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct ieee80211_local *local = dev->priv; - - frag->value = local->fragmentation_threshold; - frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD); - frag->fixed = 1; - - return 0; -} - - -static int ieee80211_ioctl_siwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *retry, char *extra) -{ - struct ieee80211_local *local = dev->priv; - - if (retry->disabled || - (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) - return -EINVAL; - - if (retry->flags & IW_RETRY_MAX) - local->long_retry_limit = retry->value; - else if (retry->flags & IW_RETRY_MIN) - local->short_retry_limit = retry->value; - else { - local->long_retry_limit = retry->value; - local->short_retry_limit = retry->value; - } - - if (local->hw->set_retry_limit) { - return local->hw->set_retry_limit( - dev, local->short_retry_limit, - local->long_retry_limit); - } - - return 0; -} - - -static int ieee80211_ioctl_giwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *retry, char *extra) -{ - struct ieee80211_local *local = dev->priv; - - retry->disabled = 0; - if ((retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) - return -EINVAL; - if (retry->flags & IW_RETRY_MAX) { - retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - retry->value = local->long_retry_limit; - } else { - retry->flags = IW_RETRY_LIMIT; - retry->value = local->short_retry_limit; - if (local->long_retry_limit != local->short_retry_limit) - retry->flags |= IW_RETRY_MIN; - } - - return 0; -} - - -static void ieee80211_ioctl_unmask_channels(struct ieee80211_local *local) -{ - int m, c; - - for (m = 0; m < local->hw->num_modes; m++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[m]; - for (c = 0; c < mode->num_channels; c++) { - struct ieee80211_channel *chan = &mode->channels[c]; - chan->flag |= IEEE80211_CHAN_W_SCAN; - } - } -} - - -static int ieee80211_ioctl_test_mode(struct net_device *dev, int mode) -{ - struct ieee80211_local *local = dev->priv; - int ret = -EOPNOTSUPP; - - if (mode == IEEE80211_TEST_UNMASK_CHANNELS) { - ieee80211_ioctl_unmask_channels(local); - ret = 0; - } - - if (local->hw->test_mode) - ret = local->hw->test_mode(dev, mode); - - return ret; -} - - -static int ieee80211_ioctl_clear_keys(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_key_conf key; - struct list_head *ptr; - int i; - u8 addr[ETH_ALEN]; - struct ieee80211_key_conf *keyconf; - - memset(addr, 0xff, ETH_ALEN); - list_for_each(ptr, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - for (i = 0; i < NUM_DEFAULT_KEYS; i++) { - keyconf = NULL; - if (sdata->keys[i] && - !sdata->keys[i]->force_sw_encrypt && - local->hw->set_key && - (keyconf = ieee80211_key_data2conf(local, - sdata->keys[i])) - != NULL) - local->hw->set_key(dev, DISABLE_KEY, addr, - keyconf, 0); - kfree(keyconf); - kfree(sdata->keys[i]); - sdata->keys[i] = NULL; - } - sdata->default_key = NULL; - } - - spin_lock_bh(&local->sta_lock); - list_for_each(ptr, &local->sta_list) { - struct sta_info *sta = - list_entry(ptr, struct sta_info, list); - keyconf = NULL; - if (sta->key && !sta->key->force_sw_encrypt && - local->hw->set_key && - (keyconf = ieee80211_key_data2conf(local, sta->key)) - != NULL) - local->hw->set_key(dev, DISABLE_KEY, sta->addr, - keyconf, sta->aid); - kfree(keyconf); - kfree(sta->key); - sta->key = NULL; - } - spin_unlock_bh(&local->sta_lock); - - - memset(&key, 0, sizeof(key)); - if (local->hw->set_key && - local->hw->set_key(dev, REMOVE_ALL_KEYS, NULL, - &key, 0)) - printk(KERN_DEBUG "%s: failed to remove hwaccel keys\n", - dev->name); - - return 0; -} - - -static int -ieee80211_ioctl_force_unicast_rate(struct net_device *dev, - struct ieee80211_sub_if_data *sdata, - int rate) -{ - struct ieee80211_local *local = dev->priv; - int i; - - if (sdata->type != IEEE80211_SUB_IF_TYPE_NORM) - return -ENOENT; - - if (rate == 0) { - sdata->u.norm.force_unicast_rateidx = -1; - return 0; - } - - for (i = 0; i < local->num_curr_rates; i++) { - if (local->curr_rates[i].rate == rate) { - sdata->u.norm.force_unicast_rateidx = i; - return 0; - } - } - return -EINVAL; -} - - -static int -ieee80211_ioctl_max_ratectrl_rate(struct net_device *dev, - struct ieee80211_sub_if_data *sdata, - int rate) -{ - struct ieee80211_local *local = dev->priv; - int i; - - if (sdata->type != IEEE80211_SUB_IF_TYPE_NORM) - return -ENOENT; - - if (rate == 0) { - sdata->u.norm.max_ratectrl_rateidx = -1; - return 0; - } - - for (i = 0; i < local->num_curr_rates; i++) { - if (local->curr_rates[i].rate == rate) { - sdata->u.norm.max_ratectrl_rateidx = i; - return 0; - } - } - return -EINVAL; -} - - -static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local, - struct ieee80211_key *key) -{ - struct ieee80211_key_conf *keyconf; - u8 addr[ETH_ALEN]; - - if (key == NULL || key->alg != ALG_WEP || !key->force_sw_encrypt || - local->hw->device_hides_wep) - return; - - memset(addr, 0xff, ETH_ALEN); - keyconf = ieee80211_key_data2conf(local, key); - if (keyconf && local->hw->set_key && - local->hw->set_key(local->mdev, SET_KEY, addr, keyconf, 0) == 0) { - key->force_sw_encrypt = keyconf->force_sw_encrypt; - key->hw_key_idx = keyconf->hw_key_idx; - } - kfree(keyconf); -} - - -static void ieee80211_key_disable_hwaccel(struct ieee80211_local *local, - struct ieee80211_key *key) -{ - struct ieee80211_key_conf *keyconf; - u8 addr[ETH_ALEN]; - - if (key == NULL || key->alg != ALG_WEP || key->force_sw_encrypt || - local->hw->device_hides_wep) - return; - - memset(addr, 0xff, ETH_ALEN); - keyconf = ieee80211_key_data2conf(local, key); - if (keyconf && local->hw->set_key) - local->hw->set_key(local->mdev, DISABLE_KEY, addr, keyconf, 0); - kfree(keyconf); - key->force_sw_encrypt = 1; -} - - -static int ieee80211_ioctl_default_wep_only(struct ieee80211_local *local, - int value) -{ - int i; - struct list_head *ptr; - - local->default_wep_only = value; - list_for_each(ptr, &local->sub_if_list) { - struct ieee80211_sub_if_data *sdata = - list_entry(ptr, struct ieee80211_sub_if_data, list); - for (i = 0; i < NUM_DEFAULT_KEYS; i++) { - if (value) { - ieee80211_key_enable_hwaccel(local, - sdata->keys[i]); - } else { - ieee80211_key_disable_hwaccel(local, - sdata->keys[i]); - } - } - } - - return 0; -} - - -static int ieee80211_ioctl_prism2_param(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, char *extra) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata; - int *i = (int *) extra; - int param = *i; - int value = *(i + 1); - int ret = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - switch (param) { - case PRISM2_PARAM_HOST_ENCRYPT: - case PRISM2_PARAM_HOST_DECRYPT: - /* TODO: implement these; return success now to prevent - * hostapd from aborting */ - break; - - case PRISM2_PARAM_BEACON_INT: - local->conf.beacon_int = value; - if (ieee80211_hw_config(dev)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_AP_BRIDGE_PACKETS: - local->bridge_packets = value; - break; - - case PRISM2_PARAM_AP_AUTH_ALGS: - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - sdata->u.sta.auth_algs = value; - } else - ret = -EOPNOTSUPP; - break; - - case PRISM2_PARAM_DTIM_PERIOD: - if (value < 1) - ret = -EINVAL; - else if (sdata->type != IEEE80211_SUB_IF_TYPE_NORM) - ret = -ENOENT; - else - sdata->u.norm.dtim_period = value; - break; - - case PRISM2_PARAM_IEEE_802_1X: - sdata->ieee802_1x = value; - if (local->hw->set_ieee8021x && - local->hw->set_ieee8021x(dev, value)) - printk(KERN_DEBUG "%s: failed to set IEEE 802.1X (%d) " - "for low-level driver\n", dev->name, value); - break; - - case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: - local->cts_protect_erp_frames = value; - break; - - case PRISM2_PARAM_DROP_UNENCRYPTED: - sdata->drop_unencrypted = value; - break; - - case PRISM2_PARAM_PREAMBLE: - local->short_preamble = value; - break; - - case PRISM2_PARAM_RATE_LIMIT_BURST: - local->rate_limit_burst = value; - local->rate_limit_bucket = value; - break; - - case PRISM2_PARAM_RATE_LIMIT: - /* number of packets (tokens) allowed per second */ - if (!local->rate_limit && value) { - if (!local->rate_limit_burst) local->rate_limit_burst = - value; - local->rate_limit_bucket = local->rate_limit_burst; - local->rate_limit_timer.expires = jiffies + HZ; - add_timer(&local->rate_limit_timer); - } else if (local->rate_limit && !value) { - del_timer_sync(&local->rate_limit_timer); - } - local->rate_limit = value; - break; - - case PRISM2_PARAM_STAT_TIME: - if (!local->stat_time && value) { - local->stat_timer.expires = jiffies + HZ * value / 100; - add_timer(&local->stat_timer); - } else if (local->stat_time && !value) { - del_timer_sync(&local->stat_timer); - } - local->stat_time = value; - break; - case PRISM2_PARAM_SHORT_SLOT_TIME: - local->conf.short_slot_time = value; - if (ieee80211_hw_config(dev)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_PRIVACY_INVOKED: - if (local->hw->set_privacy_invoked) - ret = local->hw->set_privacy_invoked(dev, value); - break; - - case PRISM2_PARAM_TEST_MODE: - ret = ieee80211_ioctl_test_mode(dev, value); - break; - - case PRISM2_PARAM_NEXT_MODE: - local->next_mode = value; - break; - - case PRISM2_PARAM_CLEAR_KEYS: - ret = ieee80211_ioctl_clear_keys(dev); - break; - - case PRISM2_PARAM_ADM_STATUS: - ret = ieee80211_ioctl_set_adm_status(dev, value); - break; - - case PRISM2_PARAM_ANTENNA_SEL: - local->conf.antenna_sel = value; - if (ieee80211_hw_config(dev)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_CALIB_INT: - local->conf.calib_int = value; - if (ieee80211_hw_config(dev)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_ANTENNA_MODE: - local->conf.antenna_mode = value; - if (ieee80211_hw_config(dev)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_BROADCAST_SSID: - if ((value < 0) || (value > 1)) - ret = -EINVAL; - else - local->conf.ssid_hidden = value; - break; - - case PRISM2_PARAM_STA_ANTENNA_SEL: - local->sta_antenna_sel = value; - break; - - case PRISM2_PARAM_FORCE_UNICAST_RATE: - ret = ieee80211_ioctl_force_unicast_rate(dev, sdata, value); - break; - - case PRISM2_PARAM_MAX_RATECTRL_RATE: - ret = ieee80211_ioctl_max_ratectrl_rate(dev, sdata, value); - break; - - case PRISM2_PARAM_RATE_CTRL_NUM_UP: - local->rate_ctrl_num_up = value; - break; - - case PRISM2_PARAM_RATE_CTRL_NUM_DOWN: - local->rate_ctrl_num_down = value; - break; - - case PRISM2_PARAM_TX_POWER_REDUCTION: - if (value < 0) - ret = -EINVAL; - else - local->conf.tx_power_reduction = value; - break; - - case PRISM2_PARAM_EAPOL: - sdata->eapol = value; - break; - - case PRISM2_PARAM_KEY_TX_RX_THRESHOLD: - local->key_tx_rx_threshold = value; - break; - - case PRISM2_PARAM_KEY_INDEX: - if (value < 0 || value >= NUM_DEFAULT_KEYS) - ret = -EINVAL; - else if (sdata->keys[value] == NULL) - ret = -ENOENT; - else - sdata->default_key = sdata->keys[value]; - break; - - case PRISM2_PARAM_DEFAULT_WEP_ONLY: - ret = ieee80211_ioctl_default_wep_only(local, value); - break; - - case PRISM2_PARAM_WIFI_WME_NOACK_TEST: - local->wifi_wme_noack_test = value; - break; - - - - case PRISM2_PARAM_ALLOW_BROADCAST_ALWAYS: - local->allow_broadcast_always = value; - break; - - case PRISM2_PARAM_SCAN_FLAGS: - local->scan_flags = value; - break; - - case PRISM2_PARAM_MIXED_CELL: - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - ret = -EINVAL; - else - sdata->u.sta.mixed_cell = !!value; - break; - - case PRISM2_PARAM_KEY_MGMT: - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - ret = -EINVAL; - else - sdata->u.sta.key_mgmt = value; - break; - - case PRISM2_PARAM_HW_MODES: - local->hw_modes = value; - break; - - case PRISM2_PARAM_CREATE_IBSS: - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - ret = -EINVAL; - else - sdata->u.sta.create_ibss = !!value; - break; - case PRISM2_PARAM_WMM_ENABLED: - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - ret = -EINVAL; - else - sdata->u.sta.wmm_enabled = !!value; - break; - case PRISM2_PARAM_RADAR_DETECT: - local->conf.radar_detect = value; - break; - case PRISM2_PARAM_SPECTRUM_MGMT: - local->conf.spect_mgmt = value; - break; - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - - -static int ieee80211_ioctl_get_prism2_param(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, char *extra) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata; - int *param = (int *) extra; - int ret = 0; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - switch (*param) { - case PRISM2_PARAM_BEACON_INT: - *param = local->conf.beacon_int; - break; - - case PRISM2_PARAM_AP_BRIDGE_PACKETS: - *param = local->bridge_packets; - break; - - case PRISM2_PARAM_AP_AUTH_ALGS: - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - *param = sdata->u.sta.auth_algs; - } else - ret = -EOPNOTSUPP; - break; - - case PRISM2_PARAM_DTIM_PERIOD: - if (sdata->type != IEEE80211_SUB_IF_TYPE_NORM) - ret = -ENOENT; - else - *param = sdata->u.norm.dtim_period; - break; - - case PRISM2_PARAM_IEEE_802_1X: - *param = sdata->ieee802_1x; - break; - - case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: - *param = local->cts_protect_erp_frames; - break; - - case PRISM2_PARAM_DROP_UNENCRYPTED: - *param = sdata->drop_unencrypted; - break; - - case PRISM2_PARAM_PREAMBLE: - *param = local->short_preamble; - break; - - case PRISM2_PARAM_RATE_LIMIT_BURST: - *param = local->rate_limit_burst; - break; - - case PRISM2_PARAM_RATE_LIMIT: - *param = local->rate_limit; - break; - - case PRISM2_PARAM_STAT_TIME: - *param = local->stat_time; - break; - case PRISM2_PARAM_SHORT_SLOT_TIME: - *param = local->conf.short_slot_time; - break; - - case PRISM2_PARAM_NEXT_MODE: - *param = local->next_mode; - break; - - case PRISM2_PARAM_ANTENNA_SEL: - *param = local->conf.antenna_sel; - break; - - case PRISM2_PARAM_CALIB_INT: - *param = local->conf.calib_int; - break; - - case PRISM2_PARAM_ANTENNA_MODE: - *param = local->conf.antenna_mode; - break; - - case PRISM2_PARAM_BROADCAST_SSID: - *param = local->conf.ssid_hidden; - break; - - case PRISM2_PARAM_STA_ANTENNA_SEL: - *param = local->sta_antenna_sel; - break; - - case PRISM2_PARAM_RATE_CTRL_NUM_UP: - *param = local->rate_ctrl_num_up; - break; - - case PRISM2_PARAM_RATE_CTRL_NUM_DOWN: - *param = local->rate_ctrl_num_down; - break; - - case PRISM2_PARAM_TX_POWER_REDUCTION: - *param = local->conf.tx_power_reduction; - break; - - case PRISM2_PARAM_EAPOL: - *param = sdata->eapol; - break; - - case PRISM2_PARAM_KEY_TX_RX_THRESHOLD: - *param = local->key_tx_rx_threshold; - break; - - case PRISM2_PARAM_KEY_INDEX: - if (sdata->default_key == NULL) - ret = -ENOENT; - else if (sdata->default_key == sdata->keys[0]) - *param = 0; - else if (sdata->default_key == sdata->keys[1]) - *param = 1; - else if (sdata->default_key == sdata->keys[2]) - *param = 2; - else if (sdata->default_key == sdata->keys[3]) - *param = 3; - else - ret = -ENOENT; - break; - - case PRISM2_PARAM_DEFAULT_WEP_ONLY: - *param = local->default_wep_only; - break; - - case PRISM2_PARAM_WIFI_WME_NOACK_TEST: - *param = local->wifi_wme_noack_test; - break; - - - - case PRISM2_PARAM_ALLOW_BROADCAST_ALWAYS: - *param = local->allow_broadcast_always; - break; - - case PRISM2_PARAM_SCAN_FLAGS: - *param = local->scan_flags; - break; - - case PRISM2_PARAM_HW_MODES: - *param = local->hw_modes; - break; - - case PRISM2_PARAM_CREATE_IBSS: - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - ret = -EINVAL; - else - *param = !!sdata->u.sta.create_ibss; - break; - - case PRISM2_PARAM_MIXED_CELL: - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - ret = -EINVAL; - else - *param = !!sdata->u.sta.mixed_cell; - break; - - case PRISM2_PARAM_KEY_MGMT: - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - ret = -EINVAL; - else - *param = sdata->u.sta.key_mgmt; - break; - case PRISM2_PARAM_WMM_ENABLED: - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - ret = -EINVAL; - else - *param = !!sdata->u.sta.wmm_enabled; - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - - -static int ieee80211_ioctl_test_param(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, char *extra) -{ - struct ieee80211_local *local = dev->priv; - int *i = (int *) extra; - int param = *i; - int value = *(i + 1); - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (local->hw->test_param) - return local->hw->test_param(local->mdev, param, value); - - return -EOPNOTSUPP; -} - - -static const struct iw_priv_args ieee80211_ioctl_priv[] = { - { PRISM2_IOCTL_PRISM2_PARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "param" }, - { PRISM2_IOCTL_GET_PRISM2_PARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param" }, - { PRISM2_IOCTL_TEST_PARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "test_param" }, -}; - - -static int ieee80211_ioctl_giwpriv(struct net_device *dev, - struct iw_point *data) -{ - - if (!data->pointer || - !access_ok(VERIFY_WRITE, data->pointer, - sizeof(ieee80211_ioctl_priv))) - return -EINVAL; - - data->length = sizeof(ieee80211_ioctl_priv) / - sizeof(ieee80211_ioctl_priv[0]); - if (copy_to_user(data->pointer, ieee80211_ioctl_priv, - sizeof(ieee80211_ioctl_priv))) - return -EINVAL; - return 0; -} - - -int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct iwreq *wrq = (struct iwreq *) rq; - int ret = 0; - char ssid[IW_ESSID_MAX_SIZE + 1]; - - switch (cmd) { - case SIOCGIWNAME: - ret = ieee80211_ioctl_giwname(dev, NULL, (char *) &wrq->u, - NULL); - break; - case SIOCSIWESSID: - if (!wrq->u.essid.pointer) - ret = -EINVAL; - else if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) - ret = -E2BIG; - else { - if (copy_from_user(ssid, wrq->u.essid.pointer, - wrq->u.essid.length)) { - ret = -EFAULT; - break; - } - ret = ieee80211_ioctl_siwessid(dev, NULL, - &wrq->u.essid, ssid); - } - break; - case SIOCGIWESSID: - if (!wrq->u.essid.pointer) { - ret = -EINVAL; - } else { - memset(ssid, 0, IW_ESSID_MAX_SIZE + 1); - ret = ieee80211_ioctl_giwessid(dev, NULL, - &wrq->u.essid, ssid); - if (copy_to_user(wrq->u.essid.pointer, ssid, - wrq->u.essid.length)) { - ret = -EFAULT; - break; - } - } - break; - - case SIOCGIWRANGE: - { - struct iw_range range; - if (!access_ok(VERIFY_WRITE, wrq->u.data.pointer, - sizeof(range))) { - ret = -EFAULT; - break; - } - ret = ieee80211_ioctl_giwrange(dev, NULL, &wrq->u.data, - (char *) &range); - if (ret) - break; - if (copy_to_user(wrq->u.data.pointer, &range, sizeof(range))) - ret = -EFAULT; - break; - } - - case SIOCSIWAP: - ret = ieee80211_ioctl_siwap(dev, NULL, &wrq->u.ap_addr, NULL); - break; - case SIOCGIWAP: - ret = ieee80211_ioctl_giwap(dev, NULL, &wrq->u.ap_addr, NULL); - break; - case SIOCSIWSCAN: - ret = ieee80211_ioctl_siwscan(dev, NULL, &wrq->u.data, NULL); - break; - case SIOCGIWSCAN: - { - char *buf = kmalloc(IW_SCAN_MAX_DATA, GFP_KERNEL); - if (buf == NULL) { - ret = -ENOMEM; - break; - } - ret = ieee80211_ioctl_giwscan(dev, NULL, &wrq->u.data, buf); - if (ret == 0 && - copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) - ret = -EFAULT; - kfree(buf); - break; - } - - case SIOCSIWFREQ: - ret = ieee80211_ioctl_siwfreq(dev, NULL, &wrq->u.freq, NULL); - break; - case SIOCGIWFREQ: - ret = ieee80211_ioctl_giwfreq(dev, NULL, &wrq->u.freq, NULL); - break; - case SIOCSIWMODE: - ret = ieee80211_ioctl_siwmode(dev, NULL, &wrq->u.mode, NULL); - break; - case SIOCGIWMODE: - ret = ieee80211_ioctl_giwmode(dev, NULL, &wrq->u.mode, NULL); - break; - - case SIOCSIWRTS: - ret = ieee80211_ioctl_siwrts(dev, NULL, &wrq->u.rts, NULL); - break; - case SIOCGIWRTS: - ret = ieee80211_ioctl_giwrts(dev, NULL, &wrq->u.rts, NULL); - break; - - case SIOCSIWFRAG: - ret = ieee80211_ioctl_siwfrag(dev, NULL, &wrq->u.frag, NULL); - break; - case SIOCGIWFRAG: - ret = ieee80211_ioctl_giwfrag(dev, NULL, &wrq->u.frag, NULL); - break; - - case SIOCSIWRETRY: - ret = ieee80211_ioctl_siwretry(dev, NULL, &wrq->u.retry, NULL); - break; - case SIOCGIWRETRY: - ret = ieee80211_ioctl_giwretry(dev, NULL, &wrq->u.retry, NULL); - break; - - case PRISM2_IOCTL_PRISM2_PARAM: - ret = ieee80211_ioctl_prism2_param(dev, NULL, &wrq->u, - (char *) &wrq->u); - break; - case PRISM2_IOCTL_GET_PRISM2_PARAM: - ret = ieee80211_ioctl_get_prism2_param(dev, NULL, &wrq->u, - (char *) &wrq->u); - break; - case PRISM2_IOCTL_TEST_PARAM: - ret = ieee80211_ioctl_test_param(dev, NULL, &wrq->u, - (char *) &wrq->u); - break; - case PRISM2_IOCTL_HOSTAPD: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = ieee80211_ioctl_priv_hostapd(dev, &wrq->u.data); - break; - case SIOCGIWPRIV: - ret = ieee80211_ioctl_giwpriv(dev, &wrq->u.data); - break; - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} diff --git a/target/linux/package/ieee80211-dscape/src/ieee80211_key.h b/target/linux/package/ieee80211-dscape/src/ieee80211_key.h deleted file mode 100644 index 7a2415dec4..0000000000 --- a/target/linux/package/ieee80211-dscape/src/ieee80211_key.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2002-2004, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef IEEE80211_KEY_H -#define IEEE80211_KEY_H - -/* ALG_TKIP - * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block: - * Temporal Encryption Key (128 bits) - * Temporal Authenticator Tx MIC Key (64 bits) - * Temporal Authenticator Rx MIC Key (64 bits) - */ - -#define WEP_IV_LEN 4 -#define WEP_ICV_LEN 4 - -#define ALG_TKIP_KEY_LEN 32 -/* Starting offsets for each key */ -#define ALG_TKIP_TEMP_ENCR_KEY 0 -#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16 -#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24 -#define TKIP_IV_LEN 8 -#define TKIP_ICV_LEN 4 - -#define ALG_CCMP_KEY_LEN 16 -#define CCMP_HDR_LEN 8 -#define CCMP_MIC_LEN 8 -#define CCMP_TK_LEN 16 -#define CCMP_PN_LEN 6 - -#define NUM_RX_DATA_QUEUES 17 - -struct ieee80211_key { - int hw_key_idx; /* filled and used by low-level driver */ - ieee80211_key_alg alg; - union { - struct { - /* last used TSC */ - u32 iv32; - u16 iv16; - u16 p1k[5]; - int tx_initialized; - - /* last received RSC */ - u32 iv32_rx[NUM_RX_DATA_QUEUES]; - u16 iv16_rx[NUM_RX_DATA_QUEUES]; - u16 p1k_rx[NUM_RX_DATA_QUEUES][5]; - int rx_initialized[NUM_RX_DATA_QUEUES]; - } tkip; - struct { - u8 tx_pn[6]; - /* TODO: for WME make this replay counter per AC */ - u8 rx_pn[NUM_RX_DATA_QUEUES][6]; -#ifndef AES_STATE_LEN -#define AES_STATE_LEN 44 -#endif - u32 aes_state[AES_STATE_LEN]; - u32 replays; /* dot11RSNAStatsCCMPReplays */ - } ccmp; - } u; - int tx_rx_count; /* number of times this key has been used */ - int keylen; - - /* if the low level driver can provide hardware acceleration it should - * clear this flag */ - int force_sw_encrypt:1; - int keyidx:8; /* WEP key index */ - int default_tx_key:1; /* This key is the new default TX key - * (used only for broadcast keys). */ - - u8 key[0]; -}; - -#endif /* IEEE80211_KEY_H */ diff --git a/target/linux/package/ieee80211-dscape/src/ieee80211_led.c b/target/linux/package/ieee80211-dscape/src/ieee80211_led.c deleted file mode 100644 index de3f52cc7f..0000000000 --- a/target/linux/package/ieee80211-dscape/src/ieee80211_led.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#ifdef CONFIG_OAP_LEDS_WLAN -extern void leds_wlan_set(int unit, int tx, int state); -#endif - -void ieee80211_rx_led(int state, struct net_device *dev) { -#ifdef CONFIG_OAP_LEDS_WLAN - static unsigned int count = 0; - - if (state == 2) { - leds_wlan_set(0, 0, (++count) & 1); - } -#endif -} - -void ieee80211_tx_led(int state, struct net_device *dev) { -#ifdef CONFIG_OAP_LEDS_WLAN - leds_wlan_set(0, 1, state); -#endif -} - diff --git a/target/linux/package/ieee80211-dscape/src/ieee80211_proc.c b/target/linux/package/ieee80211-dscape/src/ieee80211_proc.c deleted file mode 100644 index 1f74f29942..0000000000 --- a/target/linux/package/ieee80211-dscape/src/ieee80211_proc.c +++ /dev/null @@ -1,777 +0,0 @@ -/* - * Copyright 2003-2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_PROC_FS - -#include -#include -#include -#include "ieee80211_i.h" -#include "sta_info.h" -#include "ieee80211_proc.h" -#include "rate_control.h" - - -static struct proc_dir_entry *ieee80211_proc; - -#define PROC_LIMIT (PAGE_SIZE - 80) - - -static char * ieee80211_proc_key(char *p, struct ieee80211_key *key, - int idx, int def_key) -{ - int i; - u8 *tpn, *rpn; - - if (!key) - return p; - - p += sprintf(p, "key[%d]%s len=%d sw_encrypt=%d idx=%d hwidx=%d " - "tx_rx_count=%d", - idx, def_key ? "*" : "", key->keylen, - key->force_sw_encrypt, key->keyidx, key->hw_key_idx, - key->tx_rx_count); - switch (key->alg) { - case ALG_WEP: - p += sprintf(p, " alg=WEP"); - break; - case ALG_TKIP: - p += sprintf(p, " alg=TKIP iv(tx)=%08x %04x", - key->u.tkip.iv32, key->u.tkip.iv16); - for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { - if (key->u.tkip.iv32_rx[i] == 0 && - key->u.tkip.iv16_rx[i] == 0) - continue; - p += sprintf(p, " iv(rx %d)=%08x %04x", i, - key->u.tkip.iv32_rx[i], - key->u.tkip.iv16_rx[i]); - } - break; - case ALG_CCMP: - tpn = key->u.ccmp.tx_pn; - p += sprintf(p, " alg=CCMP PN(tx)=%02x%02x%02x%02x%02x%02x", - tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); - for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { - rpn = key->u.ccmp.rx_pn[i]; - if (memcmp(rpn, "\x00\x00\x00\x00\x00\x00", 6) == 0) - continue; - p += sprintf(p, " PN(rx %d)=%02x%02x%02x%02x%02x%02x", - i, rpn[0], rpn[1], rpn[2], rpn[3], rpn[4], - rpn[5]); - } - p += sprintf(p, " replays=%u", key->u.ccmp.replays); - break; - default: - break; - } - - p += sprintf(p, " key="); - for (i = 0; i < key->keylen; i++) - p += sprintf(p, "%02x", key->key[i]); - p += sprintf(p, "\n"); - return p; -} - - -static char * ieee80211_proc_sub_if_norm(char *p, - struct ieee80211_if_norm *norm) -{ - p += sprintf(p, "type=norm\n"); - if (norm->beacon_head) - p += sprintf(p, "beacon_head_len=%d\n", norm->beacon_head_len); - if (norm->beacon_tail) - p += sprintf(p, "beacon_tail_len=%d\n", norm->beacon_tail_len); - p += sprintf(p, - "max_aid=%d\n" - "num_sta_ps=%d\n" - "num_buffered_multicast=%u\n" - "dtim_period=%d\n" - "dtim_count=%d\n" - "num_beacons=%d\n" - "force_unicast_rateidx=%d\n" - "max_ratectrl_rateidx=%d\n", - norm->max_aid, atomic_read(&norm->num_sta_ps), - skb_queue_len(&norm->ps_bc_buf), - norm->dtim_period, norm->dtim_count, norm->num_beacons, - norm->force_unicast_rateidx, norm->max_ratectrl_rateidx); - return p; -} - - -static char * ieee80211_proc_sub_if_sta(char *p, - struct ieee80211_if_sta *ifsta) -{ - p += sprintf(p, "type=sta\n"); - p += sprintf(p, - "state=%d\n" - "bssid=" MACSTR "\n" - "prev_bssid=" MACSTR "\n" - "ssid_len=%zd\n" - "aid=%d\n" - "ap_capab=0x%x\n" - "capab=0x%x\n" - "extra_ie_len=%zd\n" - "auth_tries=%d\n" - "assoc_tries=%d\n" - "flags=%s%s%s%s%s%s%s\n" - "auth_algs=0x%x\n" - "auth_alg=%d\n" - "auth_transaction=%d\n", - ifsta->state, - MAC2STR(ifsta->bssid), - MAC2STR(ifsta->prev_bssid), - ifsta->ssid_len, - ifsta->aid, - ifsta->ap_capab, - ifsta->capab, - ifsta->extra_ie_len, - ifsta->auth_tries, - ifsta->assoc_tries, - ifsta->ssid_set ? "[SSID]" : "", - ifsta->bssid_set ? "[BSSID]" : "", - ifsta->prev_bssid_set ? "[prev BSSID" : "", - ifsta->authenticated ? "[AUTH]" : "", - ifsta->associated ? "[ASSOC]" : "", - ifsta->probereq_poll ? "[PROBEREQ POLL]" : "", - ifsta->use_protection ? "[CTS prot]" : "", - ifsta->auth_algs, - ifsta->auth_alg, - ifsta->auth_transaction); - return p; -} - - -static char * ieee80211_proc_sub_if(char *p, - struct ieee80211_sub_if_data *sdata) -{ - if (sdata == NULL) - return p; - - if (sdata->bss) - p += sprintf(p, "bss=%p\n", sdata->bss); - - switch (sdata->type) { - case IEEE80211_SUB_IF_TYPE_NORM: - p = ieee80211_proc_sub_if_norm(p, &sdata->u.norm); - break; - case IEEE80211_SUB_IF_TYPE_WDS: - p += sprintf(p, "type=wds\n"); - p += sprintf(p, "wds.peer=" MACSTR "\n", - MAC2STR(sdata->u.wds.remote_addr)); - break; - case IEEE80211_SUB_IF_TYPE_VLAN: - p += sprintf(p, "type=vlan\n"); - p += sprintf(p, "vlan.id=%d\n", sdata->u.vlan.id); - break; - case IEEE80211_SUB_IF_TYPE_STA: - p = ieee80211_proc_sub_if_sta(p, &sdata->u.sta); - break; - } - p += sprintf(p, "channel_use=%d\n", sdata->channel_use); - p += sprintf(p, "drop_unencrypted=%d\n", sdata->drop_unencrypted); - p += sprintf(p, "eapol=%d\n", sdata->eapol); - p += sprintf(p, "ieee802_1x=%d\n", sdata->ieee802_1x); - - return p; -} - - -static int ieee80211_proc_iface_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct net_device *dev = (struct net_device *) data; - struct ieee80211_sub_if_data *sdata; - int i; - - if (off != 0) { - *eof = 1; - return 0; - } - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (!sdata) - return -1; - - p = ieee80211_proc_sub_if(p, sdata); - - for (i = 0; i < NUM_DEFAULT_KEYS; i++) { - if (sdata->keys[i] == NULL) - continue; - - p = ieee80211_proc_key(p, sdata->keys[i], i, - sdata->keys[i] == sdata->default_key); - } - - return (p - page); -} - - -static int ieee80211_proc_sta_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct sta_info *sta = (struct sta_info *) data; - struct ieee80211_local *local; - int inactive, i; - - if (off != 0) { - *eof = 1; - return 0; - } - - if (!sta || !sta->dev) - return -1; - - p += sprintf(p, "users=%d\n", atomic_read(&sta->users)); - p += sprintf(p, "aid=%d\n", sta->aid); - p += sprintf(p, "flags=0x%x %s%s%s%s%s%s%s%s%s%s\n", sta->flags, - sta->flags & WLAN_STA_AUTH ? "[AUTH]" : "", - sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : "", - sta->flags & WLAN_STA_PS ? "[PS]" : "", - sta->flags & WLAN_STA_TIM ? "[TIM]" : "", - sta->flags & WLAN_STA_PERM ? "[PERM]" : "", - sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : "", - sta->flags & WLAN_STA_SHORT_PREAMBLE ? - "[SHORT PREAMBLE]" : "", - sta->flags & WLAN_STA_WME ? "[WME]" : "", - sta->flags & WLAN_STA_WDS ? "[WDS]" : "", - sta->flags & WLAN_STA_XR ? "[XR]" : ""); - p += sprintf(p, "key_idx_compression=%d\n", - sta->key_idx_compression); - p += sprintf(p, "dev=%s\n", sta->dev->name); - if (sta->vlan_id > 0) - p += sprintf(p, "vlan_id=%d\n", sta->vlan_id); - p += sprintf(p, "rx_packets=%lu\ntx_packets=%lu\nrx_bytes=%lu\n" - "tx_bytes=%lu\nrx_duplicates=%lu\nrx_fragments=%lu\n" - "rx_dropped=%lu\ntx_fragments=%lu\ntx_filtered=%lu\n", - sta->rx_packets, sta->tx_packets, - sta->rx_bytes, sta->tx_bytes, - sta->num_duplicates, sta->rx_fragments, sta->rx_dropped, - sta->tx_fragments, sta->tx_filtered_count); - p = ieee80211_proc_key(p, sta->key, 0, 1); - - local = (struct ieee80211_local *) sta->dev->priv; - if (sta->txrate >= 0 && sta->txrate < local->num_curr_rates) { - p += sprintf(p, "txrate=%d\n", - local->curr_rates[sta->txrate].rate); - } - if (sta->last_txrate >= 0 && - sta->last_txrate < local->num_curr_rates) { - p += sprintf(p, "last_txrate=%d\n", - local->curr_rates[sta->last_txrate].rate); - } - p += sprintf(p, "num_ps_buf_frames=%u\n", - skb_queue_len(&sta->ps_tx_buf)); - p += sprintf(p, "tx_retry_failed=%lu\n", sta->tx_retry_failed); - p += sprintf(p, "tx_retry_count=%lu\n", sta->tx_retry_count); - p += sprintf(p, "last_rssi=%d\n", sta->last_rssi); - p += sprintf(p, "last_ack_rssi=%d %d %d\n", - sta->last_ack_rssi[0], sta->last_ack_rssi[1], - sta->last_ack_rssi[2]); - if (sta->last_ack) - p += sprintf(p, "last_ack_ms=%d\n", - jiffies_to_msecs(jiffies - sta->last_ack)); - inactive = jiffies - sta->last_rx; - p += sprintf(p, "inactive_msec=%d\n", jiffies_to_msecs(inactive)); - p += sprintf(p, "channel_use=%d\n", sta->channel_use); - p += sprintf(p, "wep_weak_iv_count=%d\n", sta->wep_weak_iv_count); -#ifdef CONFIG_IEEE80211_DEBUG_COUNTERS - p += sprintf(p, "wme_rx_queue="); - for (i = 0; i < NUM_RX_DATA_QUEUES; i++) - p += sprintf(p, "%u ", sta->wme_rx_queue[i]); - p += sprintf(p, "\n"); - - p += sprintf(p, "wme_tx_queue="); - for (i = 0; i < NUM_RX_DATA_QUEUES; i++) - p += sprintf(p, "%u ", sta->wme_tx_queue[i]); - p += sprintf(p, "\n"); -#endif /* CONFIG_IEEE80211_DEBUG_COUNTERS */ - p += sprintf(p, "last_seq_ctrl="); - for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { - p += sprintf(p, "%x ", sta->last_seq_ctrl[i]); - } - p += sprintf(p, "\n"); - - p += rate_control_status_sta(local, sta, p); - - return (p - page); -} - - -static int ieee80211_proc_counters_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ieee80211_local *local = (struct ieee80211_local *) data; - struct ieee80211_low_level_stats stats; - - if (off != 0) { - *eof = 1; - return 0; - } - - p += sprintf(p, - "TransmittedFragmentCount=%u\n" - "MulticastTransmittedFrameCount=%u\n" - "FailedCount=%u\n" - "RetryCount=%u\n" - "MultipleRetryCount=%d\n" - "FrameDuplicateCount=%d\n" - "ReceivedFragmentCount=%u\n" - "MulticastReceivedFrameCount=%u\n" - "TransmittedFrameCount=%u\n" - "WEPUndecryptableCount=%u\n", - local->dot11TransmittedFragmentCount, - local->dot11MulticastTransmittedFrameCount, - local->dot11FailedCount, - local->dot11RetryCount, - local->dot11MultipleRetryCount, - local->dot11FrameDuplicateCount, - local->dot11ReceivedFragmentCount, - local->dot11MulticastReceivedFrameCount, - local->dot11TransmittedFrameCount, - local->dot11WEPUndecryptableCount); - - memset(&stats, 0, sizeof(stats)); - if (local->hw->get_stats && - local->hw->get_stats(local->mdev, &stats) == 0) { - p += sprintf(p, - "ACKFailureCount=%u\n" - "RTSFailureCount=%u\n" - "FCSErrorCount=%u\n" - "RTSSuccessCount=%u\n", - stats.dot11ACKFailureCount, - stats.dot11RTSFailureCount, - stats.dot11FCSErrorCount, - stats.dot11RTSSuccessCount); - } - - return (p - page); -} - - -static int ieee80211_proc_debug_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ieee80211_local *local = (struct ieee80211_local *) data; - int i; - - if (off != 0) { - *eof = 1; - return 0; - } - -#ifdef CONFIG_IEEE80211_DEBUG_COUNTERS - p += sprintf(p, - "tx_handlers_drop=%u\n" - "tx_handlers_queued=%u\n" - "tx_handlers_drop_unencrypted=%u\n" - "tx_handlers_drop_fragment=%u\n" - "tx_handlers_drop_wep=%u\n" - "tx_handlers_drop_rate_limit=%u\n" - "tx_handlers_drop_not_assoc=%u\n" - "tx_handlers_drop_unauth_port=%u\n" - "rx_handlers_drop=%u\n" - "rx_handlers_queued=%u\n" - "rx_handlers_drop_nullfunc=%u\n" - "rx_handlers_drop_defrag=%u\n" - "rx_handlers_drop_short=%u\n" - "rx_handlers_drop_passive_scan=%u\n" - "tx_expand_skb_head=%u\n" - "tx_expand_skb_head_cloned=%u\n" - "rx_expand_skb_head=%u\n" - "rx_expand_skb_head2=%u\n" - "rx_handlers_fragments=%u\n" - "tx_status_drop=%u\n", - local->tx_handlers_drop, - local->tx_handlers_queued, - local->tx_handlers_drop_unencrypted, - local->tx_handlers_drop_fragment, - local->tx_handlers_drop_wep, - local->tx_handlers_drop_rate_limit, - local->tx_handlers_drop_not_assoc, - local->tx_handlers_drop_unauth_port, - local->rx_handlers_drop, - local->rx_handlers_queued, - local->rx_handlers_drop_nullfunc, - local->rx_handlers_drop_defrag, - local->rx_handlers_drop_short, - local->rx_handlers_drop_passive_scan, - local->tx_expand_skb_head, - local->tx_expand_skb_head_cloned, - local->rx_expand_skb_head, - local->rx_expand_skb_head2, - local->rx_handlers_fragments, - local->tx_status_drop); - { - int i; - p += sprintf(p, "wme_rx_queue="); - for (i = 0; i < NUM_RX_DATA_QUEUES; i++) - p += sprintf(p, " %u", local->wme_rx_queue[i]); - p += sprintf(p, "\n"); - - p += sprintf(p, "wme_tx_queue="); - for (i = 0; i < NUM_RX_DATA_QUEUES; i++) - p += sprintf(p, " %u", local->wme_tx_queue[i]); - p += sprintf(p, "\n"); - } -#endif /* CONFIG_IEEE80211_DEBUG_COUNTERS */ - - p += sprintf(p, "num_scans=%u\n", local->scan.num_scans); - - p += sprintf(p, - "conf.bss_count=%d\n" - "bss_dev_count=%u\n", - local->conf.bss_count, local->bss_dev_count); - for (i = 0; i < local->conf.bss_count; i++) { - p += sprintf(p, "bss_dev[%d]=%p (%s)\n", - i, local->bss_devs[i], - (i < local->bss_dev_count && local->bss_devs[i]) ? - local->bss_devs[i]->name : "N/A"); - } - - return (p - page); -} - - -static const char * ieee80211_mode_str_short(int mode) -{ - switch (mode) { - case MODE_IEEE80211A: - return "802.11a"; - case MODE_IEEE80211B: - return "802.11b"; - case MODE_IEEE80211G: - return "802.11g"; - case MODE_ATHEROS_TURBO: - return "AtherosTurbo"; - default: - return "UNKNOWN"; - } -} - - -static const char * ieee80211_mode_str(int mode) -{ - switch (mode) { - case MODE_IEEE80211A: - return "IEEE 802.11a"; - case MODE_IEEE80211B: - return "IEEE 802.11b"; - case MODE_IEEE80211G: - return "IEEE 802.11g"; - case MODE_ATHEROS_TURBO: - return "Atheros Turbo (5 GHz)"; - default: - return "UNKNOWN"; - } -} - - -static int ieee80211_proc_info_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ieee80211_local *local = (struct ieee80211_local *) data; - int m; - struct ieee80211_hw_modes *mode; - - if (off != 0) { - *eof = 1; - return 0; - } - - p += sprintf(p, "hw_name=%s\n", local->hw->name); - p += sprintf(p, "modes="); - for (m = 0; m < local->hw->num_modes; m++) { - mode = &local->hw->modes[m]; - p += sprintf(p, "[%s]", ieee80211_mode_str_short(mode->mode)); - } - p += sprintf(p, "\n"); - if (local->rate_ctrl && local->rate_ctrl_priv) - p+= sprintf(p, "rate_ctrl_alg=%s\n", local->rate_ctrl->name); - return (p - page); -} - - -static int ieee80211_proc_config_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ieee80211_local *local = (struct ieee80211_local *) data; - - if (off != 0) { - *eof = 1; - return 0; - } - - p += sprintf(p, - "low_level_driver=%s\n" - "channel=%d\n" - "freq=%d\n" - "mode=%s\n" - "802.11h=%d\n" - "wep_iv=0x%06x\n" - "antenna_sel=%d\n" - "calib_int=%d\n" - "tx_power_reduction=%d.%d dBm\n" - "bridge_packets=%d\n" - "key_tx_rx_threshold=%d\n" - "rts_threshold=%d\n" - "fragmentation_threshold=%d\n" - "short_retry_limit=%d\n" - "long_retry_limit=%d\n" - "total_ps_buffered=%d\n", - local->hw->name ? local->hw->name : "N/A", - local->conf.channel, - local->conf.freq, - ieee80211_mode_str(local->conf.phymode), - local->conf.radar_detect, - local->wep_iv & 0xffffff, - local->conf.antenna_sel, - local->conf.calib_int, - local->conf.tx_power_reduction / 10, - local->conf.tx_power_reduction % 10, - local->bridge_packets, - local->key_tx_rx_threshold, - local->rts_threshold, - local->fragmentation_threshold, - local->short_retry_limit, - local->long_retry_limit, - local->total_ps_buffered); - - return (p - page); -} - - -static int ieee80211_proc_channels_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ieee80211_local *local = (struct ieee80211_local *) data; - int m, c; - struct ieee80211_hw_modes *mode; - struct ieee80211_channel *chan; - - if (off != 0) { - *eof = 1; - return 0; - } - - p += sprintf(p, "MODE CHAN FREQ TXPOWER ANTMAX FLAGS\n"); - for (m = 0; m < local->hw->num_modes; m++) { - mode = &local->hw->modes[m]; - for (c = 0; c < mode->num_channels; c++) { - chan = &mode->channels[c]; - p += sprintf(p, "%d %d %d %d %d %s%s%s\n", - mode->mode, chan->chan, chan->freq, - chan->power_level, chan->antenna_max, - chan->flag & IEEE80211_CHAN_W_SCAN ? - "[W_SCAN]" : "", - chan->flag & IEEE80211_CHAN_W_ACTIVE_SCAN - ? "[W_ACTIVE_SCAN]" : "", - chan->flag & IEEE80211_CHAN_W_IBSS ? - "[W_IBSS]" : ""); - } - } - return (p - page); -} - - -static int ieee80211_proc_rates_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ieee80211_local *local = (struct ieee80211_local *) data; - int r; - struct ieee80211_rate *rate; - - if (off != 0) { - *eof = 1; - return 0; - } - - p += sprintf(p, "RATE VAL VAL2 MIN_RSSI_ACK MIN_RSSI_ACK_DELTA " - "FLAGS\n"); - for (r = 0; r < local->num_curr_rates; r++) { - rate = &local->curr_rates[r]; - p += sprintf(p, "%d %d %d %d %d 0x%x %s%s%s%s%s%s%s%s\n", - rate->rate, rate->val, rate->val2, - rate->min_rssi_ack, rate->min_rssi_ack_delta, - rate->flags, - rate->flags & IEEE80211_RATE_ERP ? "[ERP]" : "", - rate->flags & IEEE80211_RATE_BASIC ? - "[BASIC]" : "", - rate->flags & IEEE80211_RATE_PREAMBLE2 ? - "[PREAMBLE2]" : "", - rate->flags & IEEE80211_RATE_SUPPORTED ? - "[SUPPORTED]" : "", - rate->flags & IEEE80211_RATE_OFDM ? "[OFDM]" : "", - rate->flags & IEEE80211_RATE_CCK ? "[CCK]" : "", - rate->flags & IEEE80211_RATE_TURBO ? - "[TURBO]" : "", - rate->flags & IEEE80211_RATE_MANDATORY ? - "[MANDATORY]" : ""); - } - return (p - page); -} - - -static int ieee80211_proc_multicast_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ieee80211_local *local = (struct ieee80211_local *) data; - - if (off != 0) { - *eof = 1; - return 0; - } - - return rate_control_status_global(local, p); - -} - - -void ieee80211_proc_init_sta(struct ieee80211_local *local, - struct sta_info *sta) -{ - char buf[30]; - struct proc_dir_entry *entry; - - sprintf(buf, MACSTR, MAC2STR(sta->addr)); - - if (!local->proc_sta) - return; - - entry = create_proc_read_entry(buf, 0, local->proc_sta, - ieee80211_proc_sta_read, sta); - if (entry) { - entry->mode &= ~(S_IRWXG | S_IRWXO); - sta->proc_entry_added = 1; - } -} - - -void ieee80211_proc_deinit_sta(struct ieee80211_local *local, - struct sta_info *sta) -{ - char buf[30]; - sprintf(buf, MACSTR, MAC2STR(sta->addr)); - if (local->proc_sta) { - remove_proc_entry(buf, local->proc_sta); - sta->proc_entry_added = 0; - } -} - - -void ieee80211_proc_init_virtual(struct net_device *dev) -{ - struct proc_dir_entry *entry; - struct ieee80211_local *local = (struct ieee80211_local *) dev->priv; - - if (!local->proc_iface) - return; - - entry = create_proc_read_entry(dev->name, 0, local->proc_iface, - ieee80211_proc_iface_read, dev); - if (entry) - entry->mode &= ~(S_IRWXG | S_IRWXO); -} - - -void ieee80211_proc_deinit_virtual(struct net_device *dev) -{ - struct ieee80211_local *local = (struct ieee80211_local *) dev->priv; - - if (local->proc_iface) - remove_proc_entry(dev->name, local->proc_iface); -} - - -void ieee80211_proc_init_interface(struct ieee80211_local *local) -{ - if (!ieee80211_proc) - return; - - local->proc = proc_mkdir(local->wdev->name, ieee80211_proc); - if (!local->proc) - return; - - local->proc_sta = proc_mkdir("sta", local->proc); - local->proc_iface = proc_mkdir("iface", local->proc); - create_proc_read_entry("counters", 0, local->proc, - ieee80211_proc_counters_read, local); - create_proc_read_entry("config", 0, local->proc, - ieee80211_proc_config_read, local); - create_proc_read_entry("channels", 0, local->proc, - ieee80211_proc_channels_read, local); - create_proc_read_entry("rates", 0, local->proc, - ieee80211_proc_rates_read, local); - create_proc_read_entry("multicast", 0, local->proc, - ieee80211_proc_multicast_read, local); - create_proc_read_entry("debug", 0, local->proc, - ieee80211_proc_debug_read, local); - create_proc_read_entry("info", 0, local->proc, - ieee80211_proc_info_read, local); - ieee80211_proc_init_virtual(local->wdev); -} - - -void ieee80211_proc_deinit_interface(struct ieee80211_local *local) -{ - if (!local->proc) - return; - - ieee80211_proc_deinit_virtual(local->wdev); - remove_proc_entry("iface", local->proc); - remove_proc_entry("sta", local->proc); - remove_proc_entry("counters", local->proc); - remove_proc_entry("debug", local->proc); - remove_proc_entry("config", local->proc); - remove_proc_entry("channels", local->proc); - remove_proc_entry("rates", local->proc); - remove_proc_entry("multicast", local->proc); - remove_proc_entry("info", local->proc); - local->proc = NULL; - remove_proc_entry(local->wdev->name, ieee80211_proc); -} - - -void ieee80211_proc_init(void) -{ - if (proc_net == NULL) { - ieee80211_proc = NULL; - return; - } - - ieee80211_proc = proc_mkdir("ieee80211", proc_net); - if (!ieee80211_proc) - printk(KERN_WARNING "Failed to mkdir /proc/net/ieee80211\n"); -} - - -void ieee80211_proc_deinit(void) -{ - if (!ieee80211_proc) - return; - - ieee80211_proc = NULL; - remove_proc_entry("ieee80211", proc_net); -} - -#endif /* CONFIG_PROC_FS */ diff --git a/target/linux/package/ieee80211-dscape/src/ieee80211_proc.h b/target/linux/package/ieee80211-dscape/src/ieee80211_proc.h deleted file mode 100644 index a8e49e9763..0000000000 --- a/target/linux/package/ieee80211-dscape/src/ieee80211_proc.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2003-2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef IEEE80211_PROC_H -#define IEEE80211_PROC_H - -#ifdef CONFIG_PROC_FS - -void ieee80211_proc_init_sta(struct ieee80211_local *local, - struct sta_info *sta); -void ieee80211_proc_deinit_sta(struct ieee80211_local *local, - struct sta_info *sta); -void ieee80211_proc_init_virtual(struct net_device *dev); -void ieee80211_proc_deinit_virtual(struct net_device *dev); -void ieee80211_proc_init_interface(struct ieee80211_local *local); -void ieee80211_proc_deinit_interface(struct ieee80211_local *local); -void ieee80211_proc_init(void); -void ieee80211_proc_deinit(void); - -#else /* CONFIG_PROC_FS */ - -static inline void ieee80211_proc_init_sta(struct ieee80211_local *local, - struct sta_info *sta) {} -static inline void ieee80211_proc_deinit_sta(struct ieee80211_local *local, - struct sta_info *sta) {} -static inline void ieee80211_proc_init_virtual(struct net_device *dev) {} -static inline void ieee80211_proc_deinit_virtual(struct net_device *dev) {} -static inline void -ieee80211_proc_init_interface(struct ieee80211_local *local) {} -static inline void -ieee80211_proc_deinit_interface(struct ieee80211_local *local) {} -static inline void ieee80211_proc_init(void) {} -static inline void ieee80211_proc_deinit(void) {} -#endif /* CONFIG_PROC_FS */ - -#endif /* IEEE80211_PROC_H */ diff --git a/target/linux/package/ieee80211-dscape/src/ieee80211_scan.c b/target/linux/package/ieee80211-dscape/src/ieee80211_scan.c deleted file mode 100644 index 7d4effe829..0000000000 --- a/target/linux/package/ieee80211-dscape/src/ieee80211_scan.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2002-2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include "ieee80211_i.h" -#include "rate_control.h" - - -/* Maximum number of seconds to wait for the traffic load to get below - * threshold before forcing a passive scan. */ -#define MAX_SCAN_WAIT 60 -/* Threshold (pkts/sec TX or RX) for delaying passive scan */ -#define SCAN_TXRX_THRESHOLD 75 - -static void get_channel_params(struct ieee80211_local *local, int channel, - struct ieee80211_hw_modes **mode, - struct ieee80211_channel **chan) -{ - int m; - - for (m = 0; m < local->hw->num_modes; m++) { - *mode = &local->hw->modes[m]; - if ((*mode)->mode == local->conf.phymode) - break; - } - local->scan.mode_idx = m; - local->scan.chan_idx = 0; - do { - *chan = &(*mode)->channels[local->scan.chan_idx]; - if ((*chan)->chan == channel) { - return; - } - local->scan.chan_idx++; - } while (local->scan.chan_idx < (*mode)->num_channels); - *chan = NULL; -} - - -static void next_chan_same_mode(struct ieee80211_local *local, - struct ieee80211_hw_modes **mode, - struct ieee80211_channel **chan) -{ - int m, prev; - - for (m = 0; m < local->hw->num_modes; m++) { - *mode = &local->hw->modes[m]; - if ((*mode)->mode == local->conf.phymode) - break; - } - local->scan.mode_idx = m; - - /* Select next channel - scan only channels marked with W_SCAN flag */ - prev = local->scan.chan_idx; - do { - local->scan.chan_idx++; - if (local->scan.chan_idx >= (*mode)->num_channels) - local->scan.chan_idx = 0; - *chan = &(*mode)->channels[local->scan.chan_idx]; - if ((*chan)->flag & IEEE80211_CHAN_W_SCAN) - break; - } while (local->scan.chan_idx != prev); -} - - -static void next_chan_all_modes(struct ieee80211_local *local, - struct ieee80211_hw_modes **mode, - struct ieee80211_channel **chan) -{ - int prev, prev_m; - - if (local->scan.mode_idx >= local->hw->num_modes) { - local->scan.mode_idx = 0; - local->scan.chan_idx = 0; - } - - /* Select next channel - scan only channels marked with W_SCAN flag */ - prev = local->scan.chan_idx; - prev_m = local->scan.mode_idx; - do { - *mode = &local->hw->modes[local->scan.mode_idx]; - local->scan.chan_idx++; - if (local->scan.chan_idx >= (*mode)->num_channels) { - local->scan.chan_idx = 0; - local->scan.mode_idx++; - if (local->scan.mode_idx >= local->hw->num_modes) - local->scan.mode_idx = 0; - *mode = &local->hw->modes[local->scan.mode_idx]; - } - *chan = &(*mode)->channels[local->scan.chan_idx]; - if ((*chan)->flag & IEEE80211_CHAN_W_SCAN) - break; - } while (local->scan.chan_idx != prev || - local->scan.mode_idx != prev_m); -} - - -static void ieee80211_scan_start(struct net_device *dev, - struct ieee80211_scan_conf *conf) -{ - struct ieee80211_local *local = dev->priv; - int old_mode_idx = local->scan.mode_idx; - int old_chan_idx = local->scan.chan_idx; - struct ieee80211_hw_modes *mode = NULL; - struct ieee80211_channel *chan = NULL; - int ret; - - if (local->hw->passive_scan == 0) { - printk(KERN_DEBUG "%s: Scan handler called, yet the hardware " - "does not support passive scanning. Disabled.\n", - dev->name); - return; - } - - if ((local->scan.tries < MAX_SCAN_WAIT && - local->scan.txrx_count > SCAN_TXRX_THRESHOLD)) { - local->scan.tries++; - /* Count TX/RX packets during one second interval and allow - * scan to start only if the number of packets is below the - * threshold. */ - local->scan.txrx_count = 0; - local->scan.timer.expires = jiffies + HZ; - add_timer(&local->scan.timer); - return; - } - - if (local->scan.skb == NULL) { - printk(KERN_DEBUG "%s: Scan start called even though scan.skb " - "is not set\n", dev->name); - } - - if (local->scan.our_mode_only) { - if (local->scan.channel > 0) { - get_channel_params(local, local->scan.channel, &mode, - &chan); - } else - next_chan_same_mode(local, &mode, &chan); - } - else - next_chan_all_modes(local, &mode, &chan); - - conf->scan_channel = chan->chan; - conf->scan_freq = chan->freq; - conf->scan_channel_val = chan->val; - conf->scan_phymode = mode->mode; - conf->scan_power_level = chan->power_level; - conf->scan_antenna_max = chan->antenna_max; - conf->scan_time = 2 * local->hw->channel_change_time + - local->scan.time; /* 10ms scan time+hardware changes */ - conf->skb = local->scan.skb ? - skb_clone(local->scan.skb, GFP_ATOMIC) : NULL; - conf->tx_control = &local->scan.tx_control; -#if 0 - printk(KERN_DEBUG "%s: Doing scan on mode: %d freq: %d chan: %d " - "for %d ms\n", - dev->name, conf->scan_phymode, conf->scan_freq, - conf->scan_channel, conf->scan_time); -#endif - local->scan.rx_packets = 0; - local->scan.rx_beacon = 0; - local->scan.freq = chan->freq; - local->scan.in_scan = 1; - - ieee80211_netif_oper(dev, NETIF_STOP); - - ret = local->hw->passive_scan(dev, IEEE80211_SCAN_START, conf); - - if (ret == 0) { - long usec = local->hw->channel_change_time + - local->scan.time; - usec += 1000000L / HZ - 1; - usec /= 1000000L / HZ; - local->scan.timer.expires = jiffies + usec; - } else { - local->scan.in_scan = 0; - if (conf->skb) - dev_kfree_skb(conf->skb); - ieee80211_netif_oper(dev, NETIF_WAKE); - if (ret == -EAGAIN) { - local->scan.timer.expires = jiffies + - (local->scan.interval * HZ / 100); - local->scan.mode_idx = old_mode_idx; - local->scan.chan_idx = old_chan_idx; - } else { - printk(KERN_DEBUG "%s: Got unknown error from " - "passive_scan %d\n", dev->name, ret); - local->scan.timer.expires = jiffies + - (local->scan.interval * HZ); - } - local->scan.in_scan = 0; - } - - add_timer(&local->scan.timer); -} - - -static void ieee80211_scan_stop(struct net_device *dev, - struct ieee80211_scan_conf *conf) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_hw_modes *mode; - struct ieee80211_channel *chan; - int wait; - - if (local->hw->passive_scan == NULL) - return; - - if (local->scan.mode_idx >= local->hw->num_modes) { - local->scan.mode_idx = 0; - local->scan.chan_idx = 0; - } - - mode = &local->hw->modes[local->scan.mode_idx]; - - if (local->scan.chan_idx >= mode->num_channels) { - local->scan.chan_idx = 0; - } - - chan = &mode->channels[local->scan.chan_idx]; - - local->hw->passive_scan(dev, IEEE80211_SCAN_END, conf); - -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Did scan on mode: %d freq: %d chan: %d " - "GOT: %d Beacon: %d (%d)\n", - dev->name, - mode->mode, chan->freq, chan->chan, - local->scan.rx_packets, local->scan.rx_beacon, - local->scan.tries); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - local->scan.num_scans++; - - local->scan.in_scan = 0; - ieee80211_netif_oper(dev, NETIF_WAKE); - - local->scan.tries = 0; - /* Use random interval of scan.interval .. 2 * scan.interval */ - wait = (local->scan.interval * HZ * ((net_random() & 127) + 128)) / - 128; - local->scan.timer.expires = jiffies + wait; - - add_timer(&local->scan.timer); -} - - -static void ieee80211_scan_handler(unsigned long uldev) -{ - struct net_device *dev = (struct net_device *) uldev; - struct ieee80211_local *local = dev->priv; - struct ieee80211_scan_conf conf; - - if (local->scan.interval == 0 && !local->scan.in_scan) { - /* Passive scanning is disabled - keep the timer always - * running to make code cleaner. */ - local->scan.timer.expires = jiffies + 10 * HZ; - add_timer(&local->scan.timer); - return; - } - - memset(&conf, 0, sizeof(struct ieee80211_scan_conf)); - conf.running_freq = local->conf.freq; - conf.running_channel = local->conf.channel; - conf.running_phymode = local->conf.phymode; - conf.running_channel_val = local->conf.channel_val; - conf.running_power_level = local->conf.power_level; - conf.running_antenna_max = local->conf.antenna_max; - - if (local->scan.in_scan == 0) - ieee80211_scan_start(dev, &conf); - else - ieee80211_scan_stop(dev, &conf); -} - - -void ieee80211_init_scan(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_hdr hdr; - u16 fc; - int len = 10; - struct rate_control_extra extra; - - /* Only initialize passive scanning if the hardware supports it */ - if (!local->hw->passive_scan) { - local->scan.skb = NULL; - memset(&local->scan.tx_control, 0, - sizeof(local->scan.tx_control)); - printk(KERN_DEBUG "%s: Does not support passive scan, " - "disabled\n", dev->name); - return; - } - - local->scan.interval = 0; - local->scan.our_mode_only = 1; - local->scan.time = 10000; - local->scan.timer.function = ieee80211_scan_handler; - local->scan.timer.data = (unsigned long) dev; - local->scan.timer.expires = jiffies + local->scan.interval * HZ; - add_timer(&local->scan.timer); - - /* Create a CTS from for broadcasting before - * the low level changes channels */ - local->scan.skb = alloc_skb(len, GFP_KERNEL); - if (local->scan.skb == NULL) { - printk(KERN_WARNING "%s: Failed to allocate CTS packet for " - "passive scan\n", dev->name); - return; - } - - fc = (WLAN_FC_TYPE_CTRL << 2) | (WLAN_FC_STYPE_CTS << 4); - hdr.frame_control = cpu_to_le16(fc); - hdr.duration_id = - cpu_to_le16(2 * local->hw->channel_change_time + - local->scan.time); - memcpy(hdr.addr1, dev->dev_addr, ETH_ALEN); /* DA */ - hdr.seq_ctrl = 0; - - memcpy(skb_put(local->scan.skb, len), &hdr, len); - - memset(&local->scan.tx_control, 0, sizeof(local->scan.tx_control)); - local->scan.tx_control.key_idx = HW_KEY_IDX_INVALID; - local->scan.tx_control.do_not_encrypt = 1; - memset(&extra, 0, sizeof(extra)); - extra.endidx = local->num_curr_rates; - local->scan.tx_control.tx_rate = - rate_control_get_rate(dev, local->scan.skb, &extra)->val; - local->scan.tx_control.no_ack = 1; -} - - -void ieee80211_stop_scan(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - - if (local->hw->passive_scan != 0) { - del_timer_sync(&local->scan.timer); - dev_kfree_skb(local->scan.skb); - local->scan.skb = NULL; - } -} diff --git a/target/linux/package/ieee80211-dscape/src/ieee80211_sta.c b/target/linux/package/ieee80211-dscape/src/ieee80211_sta.c deleted file mode 100644 index be73032354..0000000000 --- a/target/linux/package/ieee80211-dscape/src/ieee80211_sta.c +++ /dev/null @@ -1,2868 +0,0 @@ -/* - * BSS client mode implementation - * Copyright 2003, Jouni Malinen - * Copyright 2004, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* TODO: - * BSS table: use as the key to support multi-SSID APs - * order BSS list by RSSI(?) ("quality of AP") - * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, - * SSID) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "ieee80211_i.h" -#include "rate_control.h" -#include "hostapd_ioctl.h" - -/* #define IEEE80211_IBSS_DEBUG */ - -#define IEEE80211_AUTH_TIMEOUT (HZ / 5) -#define IEEE80211_AUTH_MAX_TRIES 3 -#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) -#define IEEE80211_ASSOC_MAX_TRIES 3 -#define IEEE80211_MONITORING_INTERVAL (2 * HZ) -#define IEEE80211_PROBE_INTERVAL (60 * HZ) -#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) -#define IEEE80211_SCAN_INTERVAL (2 * HZ) -#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ) -#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ) - -#define IEEE80211_PROBE_DELAY (HZ / 33) -#define IEEE80211_CHANNEL_TIME (HZ / 33) -#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) -#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) -#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) -#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) - -#define IEEE80211_IBSS_MAX_STA_ENTRIES 128 - - -#define IEEE80211_FC(type, stype) cpu_to_le16((type << 2) | (stype << 4)) - -#define ERP_INFO_USE_PROTECTION BIT(1) - -static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, - u8 *ssid, size_t ssid_len); -static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid); -static void ieee80211_rx_bss_put(struct net_device *dev, - struct ieee80211_sta_bss *bss); -static int ieee80211_sta_find_ibss(struct net_device *dev, - struct ieee80211_if_sta *ifsta); -static int ieee80211_sta_wep_configured(struct net_device *dev); - - -/* Parsed Information Elements */ -struct ieee802_11_elems { - u8 *ssid; - u8 ssid_len; - u8 *supp_rates; - u8 supp_rates_len; - u8 *fh_params; - u8 fh_params_len; - u8 *ds_params; - u8 ds_params_len; - u8 *cf_params; - u8 cf_params_len; - u8 *tim; - u8 tim_len; - u8 *ibss_params; - u8 ibss_params_len; - u8 *challenge; - u8 challenge_len; - u8 *wpa; - u8 wpa_len; - u8 *rsn; - u8 rsn_len; - u8 *erp_info; - u8 erp_info_len; - u8 *ext_supp_rates; - u8 ext_supp_rates_len; - u8 *wmm_info; - u8 wmm_info_len; - u8 *wmm_param; - u8 wmm_param_len; -}; - -typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; - - -static ParseRes ieee802_11_parse_elems(u8 *start, size_t len, - struct ieee802_11_elems *elems) -{ - size_t left = len; - u8 *pos = start; - int unknown = 0; - - memset(elems, 0, sizeof(*elems)); - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) { -#if 0 - if (net_ratelimit()) - printk(KERN_DEBUG "IEEE 802.11 element parse " - "failed (id=%d elen=%d left=%d)\n", - id, elen, left); -#endif - return ParseFailed; - } - - switch (id) { - case WLAN_EID_SSID: - elems->ssid = pos; - elems->ssid_len = elen; - break; - case WLAN_EID_SUPP_RATES: - elems->supp_rates = pos; - elems->supp_rates_len = elen; - break; - case WLAN_EID_FH_PARAMS: - elems->fh_params = pos; - elems->fh_params_len = elen; - break; - case WLAN_EID_DS_PARAMS: - elems->ds_params = pos; - elems->ds_params_len = elen; - break; - case WLAN_EID_CF_PARAMS: - elems->cf_params = pos; - elems->cf_params_len = elen; - break; - case WLAN_EID_TIM: - elems->tim = pos; - elems->tim_len = elen; - break; - case WLAN_EID_IBSS_PARAMS: - elems->ibss_params = pos; - elems->ibss_params_len = elen; - break; - case WLAN_EID_CHALLENGE: - elems->challenge = pos; - elems->challenge_len = elen; - break; - case WLAN_EID_WPA: - if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && - pos[2] == 0xf2) { - /* Microsoft OUI (00:50:F2) */ - if (pos[3] == 1) { - /* OUI Type 1 - WPA IE */ - elems->wpa = pos; - elems->wpa_len = elen; - } else if (elen >= 5 && pos[3] == 2) { - if (pos[4] == 0) { - elems->wmm_info = pos; - elems->wmm_info_len = elen; - } else if (pos[4] == 1) { - elems->wmm_param = pos; - elems->wmm_param_len = elen; - } - } - } - break; - case WLAN_EID_RSN: - elems->rsn = pos; - elems->rsn_len = elen; - break; - case WLAN_EID_ERP_INFO: - elems->erp_info = pos; - elems->erp_info_len = elen; - break; - case WLAN_EID_EXT_SUPP_RATES: - elems->ext_supp_rates = pos; - elems->ext_supp_rates_len = elen; - break; - default: -#if 0 - printk(KERN_DEBUG "IEEE 802.11 element parse ignored " - "unknown element (id=%d elen=%d)\n", - id, elen); -#endif - unknown++; - break; - } - - left -= elen; - pos += elen; - } - - if (left) - return ParseFailed; - - return unknown ? ParseUnknown : ParseOK; -} - - - - -static int ecw2cw(int ecw) -{ - int cw = 1; - while (ecw > 0) { - cw <<= 1; - ecw--; - } - return cw - 1; -} - - -static void ieee80211_sta_wmm_params(struct net_device *dev, - struct ieee80211_if_sta *ifsta, - u8 *wmm_param, size_t wmm_param_len) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_tx_queue_params params; - size_t left; - int count; - u8 *pos; - - if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) - return; - count = wmm_param[6] & 0x0f; - if (count == ifsta->wmm_last_param_set) - return; - ifsta->wmm_last_param_set = count; - - pos = wmm_param + 8; - left = wmm_param_len - 8; - - memset(¶ms, 0, sizeof(params)); - - if (local->hw->conf_tx == NULL) - return; - - local->wmm_acm = 0; - for (; left >= 4; left -= 4, pos += 4) { - int aci = (pos[0] >> 5) & 0x03; - int acm = (pos[0] >> 4) & 0x01; - int queue; - - switch (aci) { - case 1: - queue = IEEE80211_TX_QUEUE_DATA3; - if (acm) { - local->wmm_acm |= BIT(1) | BIT(2); - } - break; - case 2: - queue = IEEE80211_TX_QUEUE_DATA1; - if (acm) { - local->wmm_acm |= BIT(4) | BIT(5); - } - break; - case 3: - queue = IEEE80211_TX_QUEUE_DATA0; - if (acm) { - local->wmm_acm |= BIT(6) | BIT(7); - } - break; - case 0: - default: - queue = IEEE80211_TX_QUEUE_DATA2; - if (acm) { - local->wmm_acm |= BIT(0) | BIT(3); - } - break; - } - - params.aifs = pos[0] & 0x0f; - params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); - params.cw_min = ecw2cw(pos[1] & 0x0f); - /* TXOP is in units of 32 usec; burst_time in 0.1 ms */ - params.burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100; - printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " - "cWmin=%d cWmax=%d burst=%d\n", - dev->name, queue, aci, acm, params.aifs, params.cw_min, - params.cw_max, params.burst_time); - /* TODO: handle ACM (block TX, fallback to next lowest allowed - * AC for now) */ - if (local->hw->conf_tx(local->mdev, queue, ¶ms)) { - printk(KERN_DEBUG "%s: failed to set TX queue " - "parameters for queue %d\n", dev->name, queue); - } - } -} - - -static void ieee80211_sta_send_associnfo(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - char *buf; - size_t len; - int i; - union iwreq_data wrqu; - - if (ifsta->assocreq_ies == NULL && ifsta->assocresp_ies == NULL) - return; - - buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len + - ifsta->assocresp_ies_len), GFP_ATOMIC); - if (buf == NULL) - return; - - len = sprintf(buf, "ASSOCINFO("); - if (ifsta->assocreq_ies) { - len += sprintf(buf + len, "ReqIEs="); - for (i = 0; i < ifsta->assocreq_ies_len; i++) { - len += sprintf(buf + len, "%02x", - ifsta->assocreq_ies[i]); - } - } - if (ifsta->assocresp_ies) { - if (ifsta->assocreq_ies) - len += sprintf(buf + len, " "); - len += sprintf(buf + len, "RespIEs="); - for (i = 0; i < ifsta->assocresp_ies_len; i++) { - len += sprintf(buf + len, "%02x", - ifsta->assocresp_ies[i]); - } - } - len += sprintf(buf + len, ")"); - - if (len > IW_CUSTOM_MAX) { - len = sprintf(buf, "ASSOCRESPIE="); - for (i = 0; i < ifsta->assocresp_ies_len; i++) { - len += sprintf(buf + len, "%02x", - ifsta->assocresp_ies[i]); - } - } - - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = len; - wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); - - kfree(buf); -} - - -static void ieee80211_set_associated(struct net_device *dev, - struct ieee80211_if_sta *ifsta, int assoc) -{ - union iwreq_data wrqu; - - if (ifsta->associated == assoc) - return; - - ifsta->associated = assoc; - - if (assoc) { - struct ieee80211_sub_if_data *sdata; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - return; - ifsta->prev_bssid_set = 1; - memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); - memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_send_associnfo(dev, ifsta); - } else { - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - } - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); - ifsta->last_probe = jiffies; -} - - -static void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, - int encrypt, int probe_resp) -{ - struct ieee80211_sub_if_data *sdata; - struct ieee80211_tx_packet_data *pkt_data; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - skb->dev = sdata->master; - skb->mac.raw = skb->nh.raw = skb->h.raw = skb->data; - - pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; - memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); - pkt_data->magic = IEEE80211_CB_MAGIC; - pkt_data->sdata = sdata; - pkt_data->control.do_not_encrypt = !encrypt; - if (probe_resp) - pkt_data->control.pkt_type = PKT_PROBE_RESP; - - dev_queue_xmit(skb); -} - - -static void ieee80211_send_auth(struct net_device *dev, - struct ieee80211_if_sta *ifsta, - int transaction, u8 *extra, size_t extra_len, - int encrypt) -{ - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - - skb = dev_alloc_skb(sizeof(*mgmt) + 6 + extra_len); - if (skb == NULL) { - printk(KERN_DEBUG "%s: failed to allocate buffer for auth " - "frame\n", dev->name); - return; - } - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); - memset(mgmt, 0, 24 + 6); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_AUTH); - if (encrypt) - mgmt->frame_control |= cpu_to_le16(WLAN_FC_ISWEP); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); - mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); - ifsta->auth_transaction = transaction + 1; - mgmt->u.auth.status_code = cpu_to_le16(0); - if (extra) - memcpy(skb_put(skb, extra_len), extra, extra_len); - - ieee80211_sta_tx(dev, skb, encrypt, 0); -} - - -static void ieee80211_authenticate(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - ifsta->auth_tries++; - if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { - printk(KERN_DEBUG "%s: authentication with AP " MACSTR - " timed out\n", - dev->name, MAC2STR(ifsta->bssid)); - return; - } - - ifsta->state = IEEE80211_AUTHENTICATE; - printk(KERN_DEBUG "%s: authenticate with AP " MACSTR "\n", - dev->name, MAC2STR(ifsta->bssid)); - - ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0); - - mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); -} - - -static void ieee80211_send_assoc(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - struct ieee80211_local *local = dev->priv; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u8 *pos, *ies; - int i, len; - u16 capab; - struct ieee80211_sta_bss *bss; - int wmm = 0; - - skb = dev_alloc_skb(sizeof(*mgmt) + 200 + ifsta->extra_ie_len + - ifsta->ssid_len); - if (skb == NULL) { - printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " - "frame\n", dev->name); - return; - } - - capab = ifsta->capab; - if (local->conf.phymode == MODE_IEEE80211G) { - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | - WLAN_CAPABILITY_SHORT_PREAMBLE; - } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); - if (bss) { - if (bss->capability & WLAN_CAPABILITY_PRIVACY) - capab |= WLAN_CAPABILITY_PRIVACY; - if (bss->wmm_ie) { - wmm = 1; - } - ieee80211_rx_bss_put(dev, bss); - } - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - - if (ifsta->prev_bssid_set) { - skb_put(skb, 10); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_REASSOC_REQ); - mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1); - memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid, - ETH_ALEN); - } else { - skb_put(skb, 4); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ASSOC_REQ); - mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.assoc_req.listen_interval = cpu_to_le16(1); - } - - /* SSID */ - ies = pos = skb_put(skb, 2 + ifsta->ssid_len); - *pos++ = WLAN_EID_SSID; - *pos++ = ifsta->ssid_len; - memcpy(pos, ifsta->ssid, ifsta->ssid_len); - - len = local->num_curr_rates; - if (len > 8) - len = 8; - pos = skb_put(skb, len + 2); - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = len; - for (i = 0; i < len; i++) { - int rate = local->curr_rates[i].rate; - if (local->conf.phymode == MODE_ATHEROS_TURBO) - rate /= 2; - *pos++ = (u8) (rate / 5); - } - - if (local->num_curr_rates > len) { - pos = skb_put(skb, local->num_curr_rates - len + 2); - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = local->num_curr_rates - len; - for (i = len; i < local->num_curr_rates; i++) { - int rate = local->curr_rates[i].rate; - if (local->conf.phymode == MODE_ATHEROS_TURBO) - rate /= 2; - *pos++ = (u8) (rate / 5); - } - } - - if (ifsta->extra_ie) { - pos = skb_put(skb, ifsta->extra_ie_len); - memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len); - } - - if (wmm && ifsta->wmm_enabled) { - pos = skb_put(skb, 9); - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = 7; /* len */ - *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ - *pos++ = 0x50; - *pos++ = 0xf2; - *pos++ = 2; /* WME */ - *pos++ = 0; /* WME info */ - *pos++ = 1; /* WME ver */ - *pos++ = 0; - } - - kfree(ifsta->assocreq_ies); - ifsta->assocreq_ies_len = (skb->data + skb->len) - ies; - ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_ATOMIC); - if (ifsta->assocreq_ies) - memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); - - ieee80211_sta_tx(dev, skb, 0, 0); -} - - -static void ieee80211_send_deauth(struct net_device *dev, - struct ieee80211_if_sta *ifsta, u16 reason) -{ - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - - skb = dev_alloc_skb(sizeof(*mgmt)); - if (skb == NULL) { - printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " - "frame\n", dev->name); - return; - } - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - skb_put(skb, 2); - mgmt->u.deauth.reason_code = cpu_to_le16(reason); - - ieee80211_sta_tx(dev, skb, 0, 0); -} - - -static void ieee80211_send_disassoc(struct net_device *dev, - struct ieee80211_if_sta *ifsta, u16 reason) -{ - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - - skb = dev_alloc_skb(sizeof(*mgmt)); - if (skb == NULL) { - printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " - "frame\n", dev->name); - return; - } - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DISASSOC); - skb_put(skb, 2); - mgmt->u.disassoc.reason_code = cpu_to_le16(reason); - - ieee80211_sta_tx(dev, skb, 0, 0); -} - - -static int ieee80211_privacy_mismatch(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - struct ieee80211_sta_bss *bss; - int res = 0; - - if (ifsta == NULL || ifsta->mixed_cell || - ifsta->key_mgmt != IEEE80211_KEY_MGMT_NONE) - return 0; - - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); - if (bss == NULL) - return 0; - - if (ieee80211_sta_wep_configured(dev) != - !!(bss->capability & WLAN_CAPABILITY_PRIVACY)) - res = 1; - - ieee80211_rx_bss_put(dev, bss); - - return res; -} - - -static void ieee80211_associate(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - ifsta->assoc_tries++; - if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { - printk(KERN_DEBUG "%s: association with AP " MACSTR - " timed out\n", - dev->name, MAC2STR(ifsta->bssid)); - return; - } - - ifsta->state = IEEE80211_ASSOCIATE; - printk(KERN_DEBUG "%s: associate with AP " MACSTR "\n", - dev->name, MAC2STR(ifsta->bssid)); - if (ieee80211_privacy_mismatch(dev, ifsta)) { - printk(KERN_DEBUG "%s: mismatch in privacy configuration and " - "mixed-cell disabled - abort association\n", dev->name); - return; - } - - ieee80211_send_assoc(dev, ifsta); - - mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); -} - - -static void ieee80211_associated(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - int disassoc; - - /* TODO: start monitoring current AP signal quality and number of - * missed beacons. Scan other channels every now and then and search - * for better APs. */ - /* TODO: remove expired BSSes */ - - ifsta->state = IEEE80211_ASSOCIATED; - - sta = sta_info_get(local, ifsta->bssid); - if (sta == NULL) { - printk(KERN_DEBUG "%s: No STA entry for own AP " MACSTR "\n", - dev->name, MAC2STR(ifsta->bssid)); - disassoc = 1; - } else { - disassoc = 0; - if (time_after(jiffies, - sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { - if (ifsta->probereq_poll) { - printk(KERN_DEBUG "%s: No ProbeResp from " - "current AP " MACSTR " - assume out of " - "range\n", - dev->name, MAC2STR(ifsta->bssid)); - disassoc = 1; - } else { - ieee80211_send_probe_req(dev, ifsta->bssid, - local->scan_ssid, - local->scan_ssid_len); - ifsta->probereq_poll = 1; - } - } else { - ifsta->probereq_poll = 0; - if (time_after(jiffies, ifsta->last_probe + - IEEE80211_PROBE_INTERVAL)) { - ifsta->last_probe = jiffies; - ieee80211_send_probe_req(dev, ifsta->bssid, - ifsta->ssid, - ifsta->ssid_len); - } - } - sta_info_release(local, sta); - } - if (disassoc) { - union iwreq_data wrqu; - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); - mod_timer(&ifsta->timer, - jiffies + IEEE80211_MONITORING_INTERVAL + 30 * HZ); - } else { - mod_timer(&ifsta->timer, - jiffies + IEEE80211_MONITORING_INTERVAL); - } -} - - -static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, - u8 *ssid, size_t ssid_len) -{ - struct ieee80211_local *local = dev->priv; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u8 *pos, *supp_rates, *esupp_rates = NULL; - int i; - - skb = dev_alloc_skb(sizeof(*mgmt) + 200); - if (skb == NULL) { - printk(KERN_DEBUG "%s: failed to allocate buffer for probe " - "request\n", dev->name); - return; - } - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_PROBE_REQ); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); - if (dst) { - memcpy(mgmt->da, dst, ETH_ALEN); - memcpy(mgmt->bssid, dst, ETH_ALEN); - } else { - memset(mgmt->da, 0xff, ETH_ALEN); - memset(mgmt->bssid, 0xff, ETH_ALEN); - } - pos = skb_put(skb, 2 + ssid_len); - *pos++ = WLAN_EID_SSID; - *pos++ = ssid_len; - memcpy(pos, ssid, ssid_len); - - supp_rates = skb_put(skb, 2); - supp_rates[0] = WLAN_EID_SUPP_RATES; - supp_rates[1] = 0; - for (i = 0; i < local->num_curr_rates; i++) { - struct ieee80211_rate *rate = &local->curr_rates[i]; - if (!(rate->flags & IEEE80211_RATE_SUPPORTED)) - continue; - if (esupp_rates) { - pos = skb_put(skb, 1); - esupp_rates[1]++; - } else if (supp_rates[1] == 8) { - esupp_rates = skb_put(skb, 3); - esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; - esupp_rates[1] = 1; - pos = &esupp_rates[2]; - } else { - pos = skb_put(skb, 1); - supp_rates[1]++; - } - if (local->conf.phymode == MODE_ATHEROS_TURBO) - *pos = rate->rate / 10; - else - *pos = rate->rate / 5; - } - - ieee80211_sta_tx(dev, skb, 0, 0); -} - - -static int ieee80211_sta_wep_configured(struct net_device *dev) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata == NULL || sdata->default_key == NULL || - sdata->default_key->alg != ALG_WEP) - return 0; - return 1; -} - - -static void ieee80211_auth_completed(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - printk(KERN_DEBUG "%s: authenticated\n", dev->name); - ifsta->authenticated = 1; - ieee80211_associate(dev, ifsta); -} - - -static void ieee80211_auth_challenge(struct net_device *dev, - struct ieee80211_if_sta *ifsta, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - u8 *pos; - struct ieee802_11_elems elems; - - printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name); - pos = mgmt->u.auth.variable; - if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) - == ParseFailed) { - printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n", - dev->name); - return; - } - if (elems.challenge == NULL) { - printk(KERN_DEBUG "%s: no challenge IE in shared key auth " - "frame\n", dev->name); - return; - } - ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2, - elems.challenge_len + 2, 1); -} - - -static void ieee80211_rx_mgmt_auth(struct net_device *dev, - struct ieee80211_if_sta *ifsta, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_local *local = dev->priv; - u16 auth_alg, auth_transaction, status_code; - - if (ifsta->state != IEEE80211_AUTHENTICATE && - local->conf.mode != IW_MODE_ADHOC) { - printk(KERN_DEBUG "%s: authentication frame received from " - MACSTR ", but not in authenticate state - ignored\n", - dev->name, MAC2STR(mgmt->sa)); - return; - } - - if (len < 24 + 6) { - printk(KERN_DEBUG "%s: too short (%zd) authentication frame " - "received from " MACSTR " - ignored\n", - dev->name, len, MAC2STR(mgmt->sa)); - return; - } - - if (local->conf.mode != IW_MODE_ADHOC && - memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) { - printk(KERN_DEBUG "%s: authentication frame received from " - "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - " - "ignored\n", dev->name, MAC2STR(mgmt->sa), - MAC2STR(mgmt->bssid)); - return; - } - - if (local->conf.mode == IW_MODE_ADHOC && - memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) { - printk(KERN_DEBUG "%s: authentication frame received from " - "unknown BSSID (SA=" MACSTR " BSSID=" MACSTR ") - " - "ignored\n", dev->name, MAC2STR(mgmt->sa), - MAC2STR(mgmt->bssid)); - return; - } - - auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); - auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); - status_code = le16_to_cpu(mgmt->u.auth.status_code); - - printk(KERN_DEBUG "%s: RX authentication from " MACSTR " (alg=%d " - "transaction=%d status=%d)\n", - dev->name, MAC2STR(mgmt->sa), auth_alg, - auth_transaction, status_code); - - if (local->conf.mode == IW_MODE_ADHOC) { - /* IEEE 802.11 standard does not require authentication in IBSS - * networks and most implementations do not seem to use it. - * However, try to reply to authentication attempts if someone - * has actually implemented this. - * TODO: Could implement shared key authentication. */ - if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) { - printk(KERN_DEBUG "%s: unexpected IBSS authentication " - "frame (alg=%d transaction=%d)\n", - dev->name, auth_alg, auth_transaction); - return; - } - ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0); - } - - if (auth_alg != ifsta->auth_alg || - auth_transaction != ifsta->auth_transaction) { - printk(KERN_DEBUG "%s: unexpected authentication frame " - "(alg=%d transaction=%d)\n", - dev->name, auth_alg, auth_transaction); - return; - } - - if (status_code != WLAN_STATUS_SUCCESS) { - printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d " - "code=%d)\n", dev->name, ifsta->auth_alg, status_code); - if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { - const int num_algs = 3; - u8 algs[num_algs]; - int i, pos; - algs[0] = algs[1] = algs[2] = 0xff; - if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN) - algs[0] = WLAN_AUTH_OPEN; - if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY) - algs[1] = WLAN_AUTH_SHARED_KEY; - if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP) - algs[2] = WLAN_AUTH_LEAP; - if (ifsta->auth_alg == WLAN_AUTH_OPEN) - pos = 0; - else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY) - pos = 1; - else - pos = 2; - for (i = 0; i < num_algs; i++) { - pos++; - if (pos >= num_algs) - pos = 0; - if (algs[pos] == ifsta->auth_alg || - algs[pos] == 0xff) - continue; - if (algs[pos] == WLAN_AUTH_SHARED_KEY && - !ieee80211_sta_wep_configured(dev)) - continue; - ifsta->auth_alg = algs[pos]; - printk(KERN_DEBUG "%s: set auth_alg=%d for " - "next try\n", - dev->name, ifsta->auth_alg); - break; - } - } - return; - } - - switch (ifsta->auth_alg) { - case WLAN_AUTH_OPEN: - case WLAN_AUTH_LEAP: - ieee80211_auth_completed(dev, ifsta); - break; - case WLAN_AUTH_SHARED_KEY: - if (ifsta->auth_transaction == 4) - ieee80211_auth_completed(dev, ifsta); - else - ieee80211_auth_challenge(dev, ifsta, mgmt, len, - rx_status); - break; - } -} - - -static void ieee80211_rx_mgmt_deauth(struct net_device *dev, - struct ieee80211_if_sta *ifsta, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - u16 reason_code; - - if (len < 24 + 2) { - printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame " - "received from " MACSTR " - ignored\n", - dev->name, len, MAC2STR(mgmt->sa)); - return; - } - - if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) { - printk(KERN_DEBUG "%s: deauthentication frame received from " - "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - " - "ignored\n", dev->name, MAC2STR(mgmt->sa), - MAC2STR(mgmt->bssid)); - return; - } - - reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); - - printk(KERN_DEBUG "%s: RX deauthentication from " MACSTR - " (reason=%d)\n", - dev->name, MAC2STR(mgmt->sa), reason_code); - - if (ifsta->authenticated) { - printk(KERN_DEBUG "%s: deauthenticated\n", dev->name); - } - - if (ifsta->state == IEEE80211_AUTHENTICATE || - ifsta->state == IEEE80211_ASSOCIATE || - ifsta->state == IEEE80211_ASSOCIATED) { - ifsta->state = IEEE80211_AUTHENTICATE; - mod_timer(&ifsta->timer, - jiffies + IEEE80211_RETRY_AUTH_INTERVAL); - } - - ieee80211_set_associated(dev, ifsta, 0); - ifsta->authenticated = 0; -} - - -static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, - struct ieee80211_if_sta *ifsta, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - u16 reason_code; - - if (len < 24 + 2) { - printk(KERN_DEBUG "%s: too short (%zd) disassociation frame " - "received from " MACSTR " - ignored\n", - dev->name, len, MAC2STR(mgmt->sa)); - return; - } - - if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) { - printk(KERN_DEBUG "%s: disassociation frame received from " - "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - " - "ignored\n", dev->name, MAC2STR(mgmt->sa), - MAC2STR(mgmt->bssid)); - return; - } - - reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); - - printk(KERN_DEBUG "%s: RX disassociation from " MACSTR - " (reason=%d)\n", - dev->name, MAC2STR(mgmt->sa), reason_code); - - if (ifsta->associated) - printk(KERN_DEBUG "%s: disassociated\n", dev->name); - - if (ifsta->state == IEEE80211_ASSOCIATED) { - ifsta->state = IEEE80211_ASSOCIATE; - mod_timer(&ifsta->timer, - jiffies + IEEE80211_RETRY_AUTH_INTERVAL); - } - - ieee80211_set_associated(dev, ifsta, 0); -} - - -static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, - struct ieee80211_if_sta *ifsta, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status, - int reassoc) -{ - struct ieee80211_local *local = dev->priv; - struct sta_info *sta; - u32 rates; - u16 capab_info, status_code, aid; - struct ieee802_11_elems elems; - u8 *pos; - int i, j; - - /* AssocResp and ReassocResp have identical structure, so process both - * of them in this function. */ - - if (ifsta->state != IEEE80211_ASSOCIATE) { - printk(KERN_DEBUG "%s: association frame received from " - MACSTR ", but not in associate state - ignored\n", - dev->name, MAC2STR(mgmt->sa)); - return; - } - - if (len < 24 + 6) { - printk(KERN_DEBUG "%s: too short (%zd) association frame " - "received from " MACSTR " - ignored\n", - dev->name, len, MAC2STR(mgmt->sa)); - return; - } - - if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) { - printk(KERN_DEBUG "%s: association frame received from " - "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - " - "ignored\n", dev->name, MAC2STR(mgmt->sa), - MAC2STR(mgmt->bssid)); - return; - } - - capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); - status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); - aid = le16_to_cpu(mgmt->u.assoc_resp.aid); - if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) - printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " - "set\n", dev->name, aid); - aid &= ~(BIT(15) | BIT(14)); - - printk(KERN_DEBUG "%s: RX %sssocResp from " MACSTR " (capab=0x%x " - "status=%d aid=%d)\n", - dev->name, reassoc ? "Rea" : "A", MAC2STR(mgmt->sa), - capab_info, status_code, aid); - - if (status_code != WLAN_STATUS_SUCCESS) { - printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", - dev->name, status_code); - return; - } - - pos = mgmt->u.assoc_resp.variable; - if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) - == ParseFailed) { - printk(KERN_DEBUG "%s: failed to parse AssocResp\n", - dev->name); - return; - } - - if (elems.supp_rates == NULL) { - printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", - dev->name); - return; - } - - printk(KERN_DEBUG "%s: associated\n", dev->name); - ifsta->aid = aid; - ifsta->ap_capab = capab_info; - - kfree(ifsta->assocresp_ies); - ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt); - ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_ATOMIC); - if (ifsta->assocresp_ies) - memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len); - - ieee80211_set_associated(dev, ifsta, 1); - - /* Add STA entry for the AP */ - sta = sta_info_get(local, ifsta->bssid); - if (sta == NULL) { - sta = sta_info_add(local, dev, ifsta->bssid); - if (sta == NULL) { - printk(KERN_DEBUG "%s: failed to add STA entry for the" - " AP\n", dev->name); - return; - } - } - - sta->dev = dev; - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - sta->assoc_ap = 1; - - rates = 0; - for (i = 0; i < elems.supp_rates_len; i++) { - int rate = (elems.supp_rates[i] & 0x7f) * 5; - if (local->conf.phymode == MODE_ATHEROS_TURBO) - rate *= 2; - for (j = 0; j < local->num_curr_rates; j++) - if (local->curr_rates[j].rate == rate) - rates |= BIT(j); - } - for (i = 0; i < elems.ext_supp_rates_len; i++) { - int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; - if (local->conf.phymode == MODE_ATHEROS_TURBO) - rate *= 2; - for (j = 0; j < local->num_curr_rates; j++) - if (local->curr_rates[j].rate == rate) - rates |= BIT(j); - } - sta->supp_rates = rates; - - rate_control_rate_init(local, sta); - - if (elems.wmm_param && ifsta->wmm_enabled) { - sta->flags |= WLAN_STA_WME; - ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, - elems.wmm_param_len); - } - - - sta_info_release(local, sta); - - ieee80211_associated(dev, ifsta); -} - - -/* Caller must hold local->sta_bss_lock */ -static void __ieee80211_rx_bss_hash_add(struct net_device *dev, - struct ieee80211_sta_bss *bss) -{ - struct ieee80211_local *local = dev->priv; - bss->hnext = local->sta_bss_hash[STA_HASH(bss->bssid)]; - local->sta_bss_hash[STA_HASH(bss->bssid)] = bss; -} - - -/* Caller must hold local->sta_bss_lock */ -static void __ieee80211_rx_bss_hash_del(struct net_device *dev, - struct ieee80211_sta_bss *bss) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sta_bss *b, *prev = NULL; - b = local->sta_bss_hash[STA_HASH(bss->bssid)]; - while (b) { - if (b == bss) { - if (prev == NULL) { - local->sta_bss_hash[STA_HASH(bss->bssid)] = - bss->hnext; - } else { - prev->hnext = bss->hnext; - } - break; - } - prev = b; - b = b->hnext; - } -} - - -static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sta_bss *bss; - - bss = kmalloc(sizeof(*bss), GFP_ATOMIC); - if (bss == NULL) - return NULL; - memset(bss, 0, sizeof(*bss)); - atomic_inc(&bss->users); - atomic_inc(&bss->users); - memcpy(bss->bssid, bssid, ETH_ALEN); - - spin_lock_bh(&local->sta_bss_lock); - /* TODO: order by RSSI? */ - list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(dev, bss); - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} - - -static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sta_bss *bss; - - spin_lock_bh(&local->sta_bss_lock); - bss = local->sta_bss_hash[STA_HASH(bssid)]; - while (bss) { - if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { - atomic_inc(&bss->users); - break; - } - bss = bss->hnext; - } - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} - - -static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) -{ - kfree(bss->wpa_ie); - kfree(bss->rsn_ie); - kfree(bss->wmm_ie); - kfree(bss); -} - - -static void ieee80211_rx_bss_put(struct net_device *dev, - struct ieee80211_sta_bss *bss) -{ - struct ieee80211_local *local = dev->priv; - if (!atomic_dec_and_test(&bss->users)) - return; - - spin_lock_bh(&local->sta_bss_lock); - __ieee80211_rx_bss_hash_del(dev, bss); - list_del(&bss->list); - spin_unlock_bh(&local->sta_bss_lock); - ieee80211_rx_bss_free(bss); -} - - -void ieee80211_rx_bss_list_init(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - spin_lock_init(&local->sta_bss_lock); - INIT_LIST_HEAD(&local->sta_bss_list); -} - - -void ieee80211_rx_bss_list_deinit(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sta_bss *bss; - struct list_head *ptr; - - for (;;) { - ptr = local->sta_bss_list.next; - if (!ptr || ptr == &local->sta_bss_list) - break; - bss = list_entry(ptr, struct ieee80211_sta_bss, list); - ieee80211_rx_bss_put(dev, bss); - } -} - - -static void ieee80211_rx_bss_info(struct net_device *dev, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status, - int beacon) -{ - struct ieee80211_local *local = dev->priv; - struct ieee802_11_elems elems; - size_t baselen; - int channel, invalid = 0, clen; - struct ieee80211_sta_bss *bss; - struct sta_info *sta; - struct ieee80211_sub_if_data *sdata; - u64 timestamp; - u8 *pos; - - if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN)) - return; /* ignore ProbeResp to foreign address */ - -#if 0 - printk(KERN_DEBUG "%s: RX %s from " MACSTR " to " MACSTR "\n", - dev->name, beacon ? "Beacon" : "Probe Response", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da)); -#endif - - baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; - if (baselen > len) - return; - - pos = mgmt->u.beacon.timestamp; - timestamp = ((u64) pos[7] << 56) | ((u64) pos[6] << 48) | - ((u64) pos[5] << 40) | ((u64) pos[4] << 32) | - ((u64) pos[3] << 24) | ((u64) pos[2] << 16) | - ((u64) pos[1] << 8) | ((u64) pos[0]); - - if (local->conf.mode == IW_MODE_ADHOC && beacon && - memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0) { -#ifdef IEEE80211_IBSS_DEBUG - static unsigned long last_tsf_debug = 0; - u64 tsf; - if (local->hw->get_tsf) - tsf = local->hw->get_tsf(local->mdev); - else - tsf = -1LLU; - if (time_after(jiffies, last_tsf_debug + 5 * HZ)) { - printk(KERN_DEBUG "RX beacon SA=" MACSTR " BSSID=" - MACSTR " TSF=0x%llx BCN=0x%llx diff=%lld " - "@%ld\n", - MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid), - tsf, timestamp, tsf - timestamp, jiffies); - last_tsf_debug = jiffies; - } -#endif /* IEEE80211_IBSS_DEBUG */ - } - - if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, - &elems) == ParseFailed) - invalid = 1; - - if (local->conf.mode == IW_MODE_ADHOC && elems.supp_rates && - memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0 && - (sta = sta_info_get(local, mgmt->sa)) && - (sdata = IEEE80211_DEV_TO_SUB_IF(dev)) && - sdata->type == IEEE80211_SUB_IF_TYPE_STA) { - struct ieee80211_rate *rates; - size_t num_rates; - u32 supp_rates, prev_rates; - int i, j, oper_mode; - - rates = local->curr_rates; - num_rates = local->num_curr_rates; - oper_mode = local->sta_scanning ? local->scan_oper_phymode : - local->conf.phymode; - for (i = 0; i < local->hw->num_modes; i++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[i]; - if (oper_mode == mode->mode) { - rates = mode->rates; - num_rates = mode->num_rates; - break; - } - } - - supp_rates = 0; - for (i = 0; i < elems.supp_rates_len + - elems.ext_supp_rates_len; i++) { - u8 rate = 0; - int own_rate; - if (i < elems.supp_rates_len) - rate = elems.supp_rates[i]; - else if (elems.ext_supp_rates) - rate = elems.ext_supp_rates - [i - elems.supp_rates_len]; - own_rate = 5 * (rate & 0x7f); - if (oper_mode == MODE_ATHEROS_TURBO) - own_rate *= 2; - for (j = 0; j < num_rates; j++) - if (rates[j].rate == own_rate) - supp_rates |= BIT(j); - } - - prev_rates = sta->supp_rates; - sta->supp_rates &= supp_rates; - if (sta->supp_rates == 0) { - /* No matching rates - this should not really happen. - * Make sure that at least one rate is marked - * supported to avoid issues with TX rate ctrl. */ - - sta->supp_rates = sdata->u.sta.supp_rates_bits; - } - if (sta->supp_rates != prev_rates) { - printk(KERN_DEBUG "%s: updated supp_rates set for " - MACSTR " based on beacon info (0x%x & 0x%x -> " - "0x%x)\n", - dev->name, MAC2STR(sta->addr), prev_rates, - supp_rates, sta->supp_rates); - } - sta_info_release(local, sta); - } - - if (elems.ssid == NULL) - return; - - if (elems.ds_params && elems.ds_params_len == 1) - channel = elems.ds_params[0]; - else - channel = rx_status->channel; - - bss = ieee80211_rx_bss_get(dev, mgmt->bssid); - if (bss == NULL) { - bss = ieee80211_rx_bss_add(dev, mgmt->bssid); - if (bss == NULL) - return; - } else { -#if 0 - /* TODO: order by RSSI? */ - spin_lock_bh(&local->sta_bss_lock); - list_move_tail(&bss->list, &local->sta_bss_list); - spin_unlock_bh(&local->sta_bss_lock); -#endif - } - - if (bss->probe_resp && beacon) { - /* Do not allow beacon to override data from Probe Response. */ - ieee80211_rx_bss_put(dev, bss); - return; - } - - bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); - bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); - if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { - memcpy(bss->ssid, elems.ssid, elems.ssid_len); - bss->ssid_len = elems.ssid_len; - } - - bss->supp_rates_len = 0; - if (elems.supp_rates) { - clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; - if (clen > elems.supp_rates_len) - clen = elems.supp_rates_len; - memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates, - clen); - bss->supp_rates_len += clen; - } - if (elems.ext_supp_rates) { - clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; - if (clen > elems.ext_supp_rates_len) - clen = elems.ext_supp_rates_len; - memcpy(&bss->supp_rates[bss->supp_rates_len], - elems.ext_supp_rates, clen); - bss->supp_rates_len += clen; - } - - if (elems.wpa && - (bss->wpa_ie == NULL || bss->wpa_ie_len != elems.wpa_len || - memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) { - kfree(bss->wpa_ie); - bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC); - if (bss->wpa_ie) { - memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2); - bss->wpa_ie_len = elems.wpa_len + 2; - } else - bss->wpa_ie_len = 0; - } else if (!elems.wpa && bss->wpa_ie) { - kfree(bss->wpa_ie); - bss->wpa_ie = NULL; - bss->wpa_ie_len = 0; - } - - if (elems.rsn && - (bss->rsn_ie == NULL || bss->rsn_ie_len != elems.rsn_len || - memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) { - kfree(bss->rsn_ie); - bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC); - if (bss->rsn_ie) { - memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2); - bss->rsn_ie_len = elems.rsn_len + 2; - } else - bss->rsn_ie_len = 0; - } else if (!elems.rsn && bss->rsn_ie) { - kfree(bss->rsn_ie); - bss->rsn_ie = NULL; - bss->rsn_ie_len = 0; - } - - if (elems.wmm_param && - (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wmm_param_len || - memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) { - kfree(bss->wmm_ie); - bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC); - if (bss->wmm_ie) { - memcpy(bss->wmm_ie, elems.wmm_param - 2, - elems.wmm_param_len + 2); - bss->wmm_ie_len = elems.wmm_param_len + 2; - } else - bss->wmm_ie_len = 0; - } else if (!elems.wmm_param && bss->wmm_ie) { - kfree(bss->wmm_ie); - bss->wmm_ie = NULL; - bss->wmm_ie_len = 0; - } - - - bss->hw_mode = local->conf.phymode; - bss->channel = channel; - bss->freq = local->conf.freq; - if (channel != local->conf.channel && - (local->conf.phymode == MODE_IEEE80211G || - local->conf.phymode == MODE_IEEE80211B) && - channel >= 1 && channel <= 14) { - static const int freq_list[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 - }; - /* IEEE 802.11g/b mode can receive packets from neighboring - * channels, so map the channel into frequency. */ - bss->freq = freq_list[channel - 1]; - } - bss->timestamp = timestamp; - bss->last_update = jiffies; - bss->rssi = rx_status->ssi; - if (!beacon) - bss->probe_resp++; - ieee80211_rx_bss_put(dev, bss); -} - - -static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0); -} - - -static void ieee80211_rx_mgmt_beacon(struct net_device *dev, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_sta *ifsta; - int use_protection; - size_t baselen; - struct ieee802_11_elems elems; - - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1); - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - return; - ifsta = &sdata->u.sta; - - if (!ifsta->associated || - memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) - return; - - /* Process beacon from the current BSS */ - baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; - if (baselen > len) - return; - - if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, - &elems) == ParseFailed) - return; - - use_protection = 0; - if (elems.erp_info && elems.erp_info_len >= 1) { - use_protection = - (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0; - } - - if (use_protection != !!ifsta->use_protection) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" - MACSTR ")\n", - dev->name, - use_protection ? "enabled" : "disabled", - MAC2STR(ifsta->bssid)); - } - ifsta->use_protection = use_protection ? 1 : 0; - local->cts_protect_erp_frames = use_protection; - } - - if (elems.wmm_param && ifsta->wmm_enabled) { - ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, - elems.wmm_param_len); - } -} - - -static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, - struct ieee80211_if_sta *ifsta, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_local *local = dev->priv; - int tx_last_beacon; - struct sk_buff *skb; - struct ieee80211_mgmt *resp; - u8 *pos, *end; - - if (local->conf.mode != IW_MODE_ADHOC || - ifsta->state != IEEE80211_IBSS_JOINED || - len < 24 + 2 || ifsta->probe_resp == NULL) - return; - - if (local->hw->tx_last_beacon) - tx_last_beacon = local->hw->tx_last_beacon(local->mdev); - else - tx_last_beacon = 1; - -#ifdef IEEE80211_IBSS_DEBUG - printk(KERN_DEBUG "%s: RX ProbeReq SA=" MACSTR " DA=" MACSTR " BSSID=" - MACSTR " (tx_last_beacon=%d)\n", - dev->name, MAC2STR(mgmt->sa), MAC2STR(mgmt->da), - MAC2STR(mgmt->bssid), tx_last_beacon); -#endif /* IEEE80211_IBSS_DEBUG */ - - if (!tx_last_beacon) - return; - - if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 && - memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) - return; - - end = ((u8 *) mgmt) + len; - pos = mgmt->u.probe_req.variable; - if (pos[0] != WLAN_EID_SSID || - pos + 2 + pos[1] > end) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " - "from " MACSTR "\n", - dev->name, MAC2STR(mgmt->sa)); - } - return; - } - if (pos[1] != 0 && - (pos[1] != ifsta->ssid_len || - memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) { - /* Ignore ProbeReq for foreign SSID */ - return; - } - - /* Reply with ProbeResp */ - skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC); - if (skb == NULL) - return; - - resp = (struct ieee80211_mgmt *) skb->data; - memcpy(resp->da, mgmt->sa, ETH_ALEN); -#ifdef IEEE80211_IBSS_DEBUG - printk(KERN_DEBUG "%s: Sending ProbeResp to " MACSTR "\n", - dev->name, MAC2STR(resp->da)); -#endif /* IEEE80211_IBSS_DEBUG */ - ieee80211_sta_tx(dev, skb, 0, 1); -} - - -void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_sta *ifsta; - struct ieee80211_mgmt *mgmt; - u16 fc; - - if (skb->len < 24) - goto fail; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) { - printk(KERN_DEBUG "%s: ieee80211_sta_rx_mgmt: non-STA " - "interface (type=%d)\n", dev->name, sdata->type); - goto fail; - } - ifsta = &sdata->u.sta; - - mgmt = (struct ieee80211_mgmt *) skb->data; - fc = le16_to_cpu(mgmt->frame_control); - - switch (WLAN_FC_GET_STYPE(fc)) { - case WLAN_FC_STYPE_PROBE_REQ: - ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len, - rx_status); - break; - case WLAN_FC_STYPE_PROBE_RESP: - ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); - break; - case WLAN_FC_STYPE_BEACON: - ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); - break; - case WLAN_FC_STYPE_AUTH: - ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len, rx_status); - break; - case WLAN_FC_STYPE_ASSOC_RESP: - ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, - rx_status, 0); - break; - case WLAN_FC_STYPE_REASSOC_RESP: - ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, - rx_status, 1); - break; - case WLAN_FC_STYPE_DEAUTH: - ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len, - rx_status); - break; - case WLAN_FC_STYPE_DISASSOC: - ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len, - rx_status); - break; - default: - printk(KERN_DEBUG "%s: received unknown management frame - " - "stype=%d\n", dev->name, WLAN_FC_GET_STYPE(fc)); - break; - } - - fail: - dev_kfree_skb(skb); -} - - -void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_mgmt *mgmt; - u16 fc; - - if (skb->len < 24) { - dev_kfree_skb(skb); - return; - } - - mgmt = (struct ieee80211_mgmt *) skb->data; - fc = le16_to_cpu(mgmt->frame_control); - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) { - if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) { - ieee80211_rx_mgmt_probe_resp(dev, mgmt, - skb->len, rx_status); - } else if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) { - ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, - rx_status); - } - } - - dev_kfree_skb(skb); -} - - -static int ieee80211_sta_active_ibss(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - struct list_head *ptr; - int active = 0; - struct sta_info *sta; - - spin_lock_bh(&local->sta_lock); - list_for_each(ptr, &local->sta_list) { - sta = list_entry(ptr, struct sta_info, list); - if (sta->dev == dev && - time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, - jiffies)) { - active++; - break; - } - } - spin_unlock_bh(&local->sta_lock); - - return active; -} - - -static void ieee80211_sta_expire(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - struct list_head *ptr, *n; - struct sta_info *sta; - - spin_lock_bh(&local->sta_lock); - list_for_each_safe(ptr, n, &local->sta_list) { - sta = list_entry(ptr, struct sta_info, list); - if (time_after(jiffies, sta->last_rx + - IEEE80211_IBSS_INACTIVITY_LIMIT)) { - printk(KERN_DEBUG "%s: expiring inactive STA " MACSTR - "\n", dev->name, MAC2STR(sta->addr)); - sta_info_free(local, sta, 1); - } - } - spin_unlock_bh(&local->sta_lock); -} - - -static void ieee80211_sta_merge_ibss(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); - - ieee80211_sta_expire(dev); - if (ieee80211_sta_active_ibss(dev)) - return; - - printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " - "IBSS networks with same SSID (merge)\n", dev->name); - ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len); -} - - -void ieee80211_sta_timer(unsigned long ptr) -{ - struct net_device *dev; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_sta *ifsta; - - dev = (struct net_device *) ptr; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) { - printk(KERN_DEBUG "%s: ieee80211_sta_timer: non-STA interface " - "(type=%d)\n", dev->name, sdata->type); - return; - } - ifsta = &sdata->u.sta; - - switch (ifsta->state) { - case IEEE80211_DISABLED: - break; - case IEEE80211_AUTHENTICATE: - ieee80211_authenticate(dev, ifsta); - break; - case IEEE80211_ASSOCIATE: - ieee80211_associate(dev, ifsta); - break; - case IEEE80211_ASSOCIATED: - ieee80211_associated(dev, ifsta); - break; - case IEEE80211_IBSS_SEARCH: - ieee80211_sta_find_ibss(dev, ifsta); - break; - case IEEE80211_IBSS_JOINED: - ieee80211_sta_merge_ibss(dev, ifsta); - break; - default: - printk(KERN_DEBUG "ieee80211_sta_timer: Unknown state %d\n", - ifsta->state); - break; - } - - if (ieee80211_privacy_mismatch(dev, ifsta)) { - printk(KERN_DEBUG "%s: privacy configuration mismatch and " - "mixed-cell disabled - disassociate\n", dev->name); - - ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED); - ieee80211_set_associated(dev, ifsta, 0); - } -} - - -static void ieee80211_sta_new_auth(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - struct ieee80211_local *local = dev->priv; - - if (local->conf.mode != IW_MODE_INFRA) - return; - - if (local->hw->reset_tsf) { - /* Reset own TSF to allow time synchronization work. */ - local->hw->reset_tsf(local->mdev); - } - - ifsta->wmm_last_param_set = -1; /* allow any WMM update */ - - - if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN) - ifsta->auth_alg = WLAN_AUTH_OPEN; - else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY) - ifsta->auth_alg = WLAN_AUTH_SHARED_KEY; - else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP) - ifsta->auth_alg = WLAN_AUTH_LEAP; - else - ifsta->auth_alg = WLAN_AUTH_OPEN; - printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name, - ifsta->auth_alg); - ifsta->auth_transaction = -1; - ifsta->auth_tries = ifsta->assoc_tries = 0; - ieee80211_authenticate(dev, ifsta); -} - - -static int ieee80211_ibss_allowed(struct ieee80211_local *local) -{ - int m, c; - - for (m = 0; m < local->hw->num_modes; m++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[m]; - if (mode->mode != local->conf.phymode) - continue; - for (c = 0; c < mode->num_channels; c++) { - struct ieee80211_channel *chan = &mode->channels[c]; - if (chan->flag & IEEE80211_CHAN_W_SCAN && - chan->chan == local->conf.channel) { - if (chan->flag & IEEE80211_CHAN_W_IBSS) - return 1; - break; - } - } - } - - return 0; -} - - -extern int ieee80211_ioctl_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra); - -static int ieee80211_sta_join_ibss(struct net_device *dev, - struct ieee80211_if_sta *ifsta, - struct ieee80211_sta_bss *bss) -{ - struct ieee80211_local *local = dev->priv; - struct iw_freq rq; - int res, rates, i, j; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - struct ieee80211_tx_control control; - struct ieee80211_rate *rate; - struct rate_control_extra extra; - u8 *pos; - struct ieee80211_sub_if_data *sdata; - - /* Remove possible STA entries from other IBSS networks. */ - sta_info_flush(local, NULL); - - if (local->hw->reset_tsf) { - /* Reset own TSF to allow time synchronization work. */ - local->hw->reset_tsf(local->mdev); - } - memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); - memcpy(local->bssid, bss->bssid, ETH_ALEN); - memcpy(local->conf.client_bssid, bss->bssid, ETH_ALEN); - - local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - sdata->drop_unencrypted = bss->capability & - cpu_to_le16(WLAN_CAPABILITY_PRIVACY) ? 1 : 0; - - memset(&rq, 0, sizeof(rq)); - rq.m = bss->freq * 100000; - rq.e = 1; - res = ieee80211_ioctl_siwfreq(dev, NULL, &rq, NULL); - - if (!ieee80211_ibss_allowed(local)) { - printk(KERN_DEBUG "%s: IBSS not allowed on channel %d " - "(%d MHz)\n", dev->name, local->conf.channel, - local->conf.freq); - return -1; - } - - /* Set beacon template based on scan results */ - skb = dev_alloc_skb(400); - do { - if (skb == NULL) - break; - - mgmt = (struct ieee80211_mgmt *) - skb_put(skb, 24 + sizeof(mgmt->u.beacon)); - memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_BEACON); - memset(mgmt->da, 0xff, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->u.beacon.beacon_int = - cpu_to_le16(local->conf.beacon_int); - mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability); - - pos = skb_put(skb, 2 + ifsta->ssid_len); - *pos++ = WLAN_EID_SSID; - *pos++ = ifsta->ssid_len; - memcpy(pos, ifsta->ssid, ifsta->ssid_len); - - rates = bss->supp_rates_len; - if (rates > 8) - rates = 8; - pos = skb_put(skb, 2 + rates); - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = rates; - memcpy(pos, bss->supp_rates, rates); - - pos = skb_put(skb, 2 + 1); - *pos++ = WLAN_EID_DS_PARAMS; - *pos++ = 1; - *pos++ = bss->channel; - - pos = skb_put(skb, 2 + 2); - *pos++ = WLAN_EID_IBSS_PARAMS; - *pos++ = 2; - /* FIX: set ATIM window based on scan results */ - *pos++ = 0; - *pos++ = 0; - - if (bss->supp_rates_len > 8) { - rates = bss->supp_rates_len - 8; - pos = skb_put(skb, 2 + rates); - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = rates; - memcpy(pos, &bss->supp_rates[8], rates); - } - - memset(&control, 0, sizeof(control)); - control.pkt_type = PKT_PROBE_RESP; - memset(&extra, 0, sizeof(extra)); - extra.endidx = local->num_curr_rates; - rate = rate_control_get_rate(dev, skb, &extra); - if (rate == NULL) { - printk(KERN_DEBUG "%s: Failed to determine TX rate " - "for IBSS beacon\n", dev->name); - break; - } - control.tx_rate = (local->short_preamble && - (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? - rate->val2 : rate->val; - control.antenna_sel = local->conf.antenna_sel; - control.power_level = local->conf.power_level; - control.no_ack = 1; - control.retry_limit = 1; - control.rts_cts_duration = 0; - - ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC); - if (ifsta->probe_resp) { - mgmt = (struct ieee80211_mgmt *) - ifsta->probe_resp->data; - mgmt->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_PROBE_RESP); - } else { - printk(KERN_DEBUG "%s: Could not allocate ProbeResp " - "template for IBSS\n", dev->name); - } - - if (local->hw->beacon_update && - local->hw->beacon_update(dev, skb, &control) == 0) { - printk(KERN_DEBUG "%s: Configured IBSS beacon " - "template based on scan results\n", dev->name); - skb = NULL; - } - - rates = 0; - for (i = 0; i < bss->supp_rates_len; i++) { - int rate = (bss->supp_rates[i] & 0x7f) * 5; - if (local->conf.phymode == MODE_ATHEROS_TURBO) - rate *= 2; - for (j = 0; j < local->num_curr_rates; j++) - if (local->curr_rates[j].rate == rate) - rates |= BIT(j); - } - ifsta->supp_rates_bits = rates; - } while (0); - - if (skb) { - printk(KERN_DEBUG "%s: Failed to configure IBSS beacon " - "template\n", dev->name); - dev_kfree_skb(skb); - } - - ifsta->state = IEEE80211_IBSS_JOINED; - mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); - - ieee80211_rx_bss_put(dev, bss); - - return res; -} - - -static int ieee80211_sta_create_ibss(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sta_bss *bss; - struct ieee80211_sub_if_data *sdata; - u8 bssid[ETH_ALEN], *pos; - int i; - -#if 0 - /* Easier testing, use fixed BSSID. */ - memset(bssid, 0xfe, ETH_ALEN); -#else - /* Generate random, not broadcast, locally administered BSSID. Mix in - * own MAC address to make sure that devices that do not have proper - * random number generator get different BSSID. */ - get_random_bytes(bssid, ETH_ALEN); - for (i = 0; i < ETH_ALEN; i++) - bssid[i] ^= dev->dev_addr[i]; - bssid[0] &= ~0x01; - bssid[0] |= 0x02; -#endif - - printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID " MACSTR "\n", - dev->name, MAC2STR(bssid)); - - bss = ieee80211_rx_bss_add(dev, bssid); - if (bss == NULL) - return -ENOMEM; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (local->conf.beacon_int == 0) - local->conf.beacon_int = 100; - bss->beacon_int = local->conf.beacon_int; - bss->hw_mode = local->conf.phymode; - bss->channel = local->conf.channel; - bss->freq = local->conf.freq; - bss->last_update = jiffies; - bss->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS); - if (sdata->default_key) { - bss->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - } else - sdata->drop_unencrypted = 0; - bss->supp_rates_len = local->num_curr_rates; - pos = bss->supp_rates; - for (i = 0; i < local->num_curr_rates; i++) { - int rate = local->curr_rates[i].rate; - if (local->conf.phymode == MODE_ATHEROS_TURBO) - rate /= 2; - *pos++ = (u8) (rate / 5); - } - - return ieee80211_sta_join_ibss(dev, ifsta, bss); -} - - -static int ieee80211_sta_find_ibss(struct net_device *dev, - struct ieee80211_if_sta *ifsta) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sta_bss *bss; - int found = 0; - u8 bssid[ETH_ALEN]; - struct list_head *ptr; - int active_ibss; - - if (ifsta->ssid_len == 0) - return -EINVAL; - - active_ibss = ieee80211_sta_active_ibss(dev); -#ifdef IEEE80211_IBSS_DEBUG - printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", - dev->name, active_ibss); -#endif /* IEEE80211_IBSS_DEBUG */ - spin_lock_bh(&local->sta_bss_lock); - list_for_each(ptr, &local->sta_bss_list) { - bss = list_entry(ptr, struct ieee80211_sta_bss, list); - if (ifsta->ssid_len != bss->ssid_len || - memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 - || !(bss->capability & WLAN_CAPABILITY_IBSS)) - continue; -#ifdef IEEE80211_IBSS_DEBUG - printk(KERN_DEBUG " bssid=" MACSTR " found\n", - MAC2STR(bss->bssid)); -#endif /* IEEE80211_IBSS_DEBUG */ - memcpy(bssid, bss->bssid, ETH_ALEN); - found = 1; - if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0) - break; - } - spin_unlock_bh(&local->sta_bss_lock); - -#ifdef IEEE80211_IBSS_DEBUG - printk(KERN_DEBUG " sta_find_ibss: selected " MACSTR " current " - MACSTR "\n", MAC2STR(bssid), MAC2STR(ifsta->bssid)); -#endif /* IEEE80211_IBSS_DEBUG */ - if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && - (bss = ieee80211_rx_bss_get(dev, bssid))) { - printk(KERN_DEBUG "%s: Selected IBSS BSSID " MACSTR - " based on configured SSID\n", - dev->name, MAC2STR(bssid)); - return ieee80211_sta_join_ibss(dev, ifsta, bss); - } -#ifdef IEEE80211_IBSS_DEBUG - printk(KERN_DEBUG " did not try to join ibss\n"); -#endif /* IEEE80211_IBSS_DEBUG */ - - /* Selected IBSS not found in current scan results - try to scan */ - if (ifsta->state == IEEE80211_IBSS_JOINED && - !ieee80211_sta_active_ibss(dev)) { - mod_timer(&ifsta->timer, - jiffies + IEEE80211_IBSS_MERGE_INTERVAL); - } else if (time_after(jiffies, local->last_scan_completed + - IEEE80211_SCAN_INTERVAL)) { - printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " - "join\n", dev->name); - return ieee80211_sta_req_scan(dev, ifsta->ssid, - ifsta->ssid_len); - } else if (ifsta->state != IEEE80211_IBSS_JOINED) { - int interval = IEEE80211_SCAN_INTERVAL; - - if (time_after(jiffies, ifsta->ibss_join_req + - IEEE80211_IBSS_JOIN_TIMEOUT)) { - if (ifsta->create_ibss && - ieee80211_ibss_allowed(local)) - return ieee80211_sta_create_ibss(dev, ifsta); - if (ifsta->create_ibss) { - printk(KERN_DEBUG "%s: IBSS not allowed on the" - " configured channel %d (%d MHz)\n", - dev->name, local->conf.channel, - local->conf.freq); - } - - /* No IBSS found - decrease scan interval and continue - * scanning. */ - interval = IEEE80211_SCAN_INTERVAL_SLOW; - } - - ifsta->state = IEEE80211_IBSS_SEARCH; - mod_timer(&ifsta->timer, jiffies + interval); - return 0; - } - - return 0; -} - - -int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) -{ - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_sta *ifsta; - struct ieee80211_local *local = dev->priv; - - if (len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; - - /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is - * not defined. */ - if (local->hw->conf_tx) { - struct ieee80211_tx_queue_params qparam; - int i; - - memset(&qparam, 0, sizeof(qparam)); - /* TODO: are these ok defaults for all hw_modes? */ - qparam.aifs = 2; - qparam.cw_min = - local->conf.phymode == MODE_IEEE80211B ? 31 : 15; - qparam.cw_max = 1023; - qparam.burst_time = 0; - for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++) - { - local->hw->conf_tx(dev, i + IEEE80211_TX_QUEUE_DATA0, - &qparam); - } - /* IBSS uses different parameters for Beacon sending */ - qparam.cw_min++; - qparam.cw_min *= 2; - qparam.cw_min--; - local->hw->conf_tx(dev, IEEE80211_TX_QUEUE_BEACON, &qparam); - } - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - ifsta = &sdata->u.sta; - - if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) - ifsta->prev_bssid_set = 0; - memcpy(ifsta->ssid, ssid, len); - memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len); - ifsta->ssid_len = len; - - ifsta->ssid_set = 1; - if (local->conf.mode == IW_MODE_ADHOC && !ifsta->bssid_set) { - ifsta->ibss_join_req = jiffies; - ifsta->state = IEEE80211_IBSS_SEARCH; - return ieee80211_sta_find_ibss(dev, ifsta); - } - - if (ifsta->bssid_set && ifsta->state != IEEE80211_AUTHENTICATE) - ieee80211_sta_new_auth(dev, ifsta); - - return 0; -} - - -int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - memcpy(ssid, ifsta->ssid, ifsta->ssid_len); - *len = ifsta->ssid_len; - return 0; -} - - -int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_sta *ifsta; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - ifsta = &sdata->u.sta; - - memcpy(ifsta->bssid, bssid, ETH_ALEN); - if (local->conf.mode == IW_MODE_ADHOC) - memcpy(local->bssid, bssid, ETH_ALEN); - - if (memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) - ifsta->bssid_set = 0; - else - ifsta->bssid_set = 1; - if (ifsta->ssid_set) - ieee80211_sta_new_auth(dev, ifsta); - - return 0; -} - - -static void ieee80211_sta_save_oper_chan(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - local->scan_oper_channel = local->conf.channel; - local->scan_oper_channel_val = local->conf.channel_val; - local->scan_oper_power_level = local->conf.power_level; - local->scan_oper_freq = local->conf.freq; - local->scan_oper_phymode = local->conf.phymode; - local->scan_oper_antenna_max = local->conf.antenna_max; -} - - -static int ieee80211_sta_restore_oper_chan(struct net_device *dev) -{ - struct ieee80211_local *local = dev->priv; - local->conf.channel = local->scan_oper_channel; - local->conf.channel_val = local->scan_oper_channel_val; - local->conf.power_level = local->scan_oper_power_level; - local->conf.freq = local->scan_oper_freq; - local->conf.phymode = local->scan_oper_phymode; - local->conf.antenna_max = local->scan_oper_antenna_max; - return ieee80211_hw_config(dev); -} - - -static int ieee80211_active_scan(struct ieee80211_local *local) -{ - int m, c; - - for (m = 0; m < local->hw->num_modes; m++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[m]; - if (mode->mode != local->conf.phymode) - continue; - for (c = 0; c < mode->num_channels; c++) { - struct ieee80211_channel *chan = &mode->channels[c]; - if (chan->flag & IEEE80211_CHAN_W_SCAN && - chan->chan == local->conf.channel) { - if (chan->flag & IEEE80211_CHAN_W_ACTIVE_SCAN) - return 1; - break; - } - } - } - - return 0; -} - - -static void ieee80211_sta_scan_timer(unsigned long ptr) -{ - struct net_device *dev = (struct net_device *) ptr; - struct ieee80211_local *local = dev->priv; - struct ieee80211_hw_modes *mode; - struct ieee80211_channel *chan; - int skip; - union iwreq_data wrqu; - - if (!local->sta_scanning) - return; - - switch (local->scan_state) { - case SCAN_SET_CHANNEL: - mode = &local->hw->modes[local->scan_hw_mode_idx]; - if (local->scan_hw_mode_idx >= local->hw->num_modes || - (local->scan_hw_mode_idx + 1 == local->hw->num_modes && - local->scan_channel_idx >= mode->num_channels)) { - if (ieee80211_sta_restore_oper_chan(dev)) { - printk(KERN_DEBUG "%s: failed to restore " - "operational channel after scan\n", - dev->name); - } - printk(KERN_DEBUG "%s: scan completed\n", dev->name); - local->sta_scanning = 0; - local->last_scan_completed = jiffies; - memset(&wrqu, 0, sizeof(wrqu)); - wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); - if (local->conf.mode == IW_MODE_ADHOC) { - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - if (!ifsta->bssid_set || - (ifsta->state == IEEE80211_IBSS_JOINED && - !ieee80211_sta_active_ibss(dev))) - ieee80211_sta_find_ibss(dev, ifsta); - } - return; - } - skip = !(local->hw_modes & (1 << mode->mode)); - chan = &mode->channels[local->scan_channel_idx]; - if (!(chan->flag & IEEE80211_CHAN_W_SCAN) || - (local->conf.mode == IW_MODE_ADHOC && - !(chan->flag & IEEE80211_CHAN_W_IBSS)) || - (local->hw_modes & (1 << MODE_IEEE80211G) && - mode->mode == MODE_IEEE80211B && local->scan_skip_11b)) - skip = 1; - - if (!skip) { -#if 0 - printk(KERN_DEBUG "%s: scan channel %d (%d MHz)\n", - dev->name, chan->chan, chan->freq); -#endif - - local->conf.channel = chan->chan; - local->conf.channel_val = chan->val; - local->conf.power_level = chan->power_level; - local->conf.freq = chan->freq; - local->conf.phymode = mode->mode; - local->conf.antenna_max = chan->antenna_max; - if (ieee80211_hw_config(dev)) { - printk(KERN_DEBUG "%s: failed to set channel " - "%d (%d MHz) for scan\n", dev->name, - chan->chan, chan->freq); - skip = 1; - } - } - - local->scan_channel_idx++; - if (local->scan_channel_idx >= - local->hw->modes[local->scan_hw_mode_idx].num_channels) { - local->scan_hw_mode_idx++; - local->scan_channel_idx = 0; - } - - if (skip) { - local->scan_timer.expires = jiffies; - break; - } - - local->scan_timer.expires = jiffies + IEEE80211_PROBE_DELAY; - local->scan_state = SCAN_SEND_PROBE; - break; - case SCAN_SEND_PROBE: - if (ieee80211_active_scan(local)) { - ieee80211_send_probe_req(dev, NULL, local->scan_ssid, - local->scan_ssid_len); - local->scan_timer.expires = - jiffies + IEEE80211_CHANNEL_TIME; - } else { - local->scan_timer.expires = - jiffies + IEEE80211_PASSIVE_CHANNEL_TIME; - } - local->scan_state = SCAN_SET_CHANNEL; - break; - } - - add_timer(&local->scan_timer); -} - - -int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) -{ - struct ieee80211_local *local = dev->priv; - - if (ssid_len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; - - /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) - * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS - * BSSID: MACAddress - * SSID - * ScanType: ACTIVE, PASSIVE - * ProbeDelay: delay (in microseconds) to be used prior to transmitting - * a Probe frame during active scanning - * ChannelList - * MinChannelTime (>= ProbeDelay), in TU - * MaxChannelTime: (>= MinChannelTime), in TU - */ - - /* MLME-SCAN.confirm - * BSSDescriptionSet - * ResultCode: SUCCESS, INVALID_PARAMETERS - */ - - /* TODO: if assoc, move to power save mode for the duration of the - * scan */ - - if (local->sta_scanning) - return -EBUSY; - - printk(KERN_DEBUG "%s: starting scan\n", dev->name); - - ieee80211_sta_save_oper_chan(dev); - - local->sta_scanning = 1; - /* TODO: stop TX queue? */ - - if (ssid) { - local->scan_ssid_len = ssid_len; - memcpy(local->scan_ssid, ssid, ssid_len); - } else - local->scan_ssid_len = 0; - local->scan_skip_11b = 1; /* FIX: clear this is 11g is not supported */ - local->scan_state = SCAN_SET_CHANNEL; - local->scan_hw_mode_idx = 0; - local->scan_channel_idx = 0; - init_timer(&local->scan_timer); - local->scan_timer.data = (unsigned long) dev; - local->scan_timer.function = ieee80211_sta_scan_timer; - local->scan_timer.expires = jiffies + 1; - add_timer(&local->scan_timer); - - return 0; -} - - -static char * -ieee80211_sta_scan_result(struct net_device *dev, - struct ieee80211_sta_bss *bss, - char *current_ev, char *end_buf) -{ - struct ieee80211_local *local = dev->priv; - struct iw_event iwe; - - if (time_after(jiffies, - bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) - return current_ev; - - if (!(local->hw_modes & (1 << bss->hw_mode))) - return current_ev; - - if (local->scan_flags & IEEE80211_SCAN_WPA_ONLY && - bss->wpa_ie == NULL && bss->rsn_ie == NULL) - return current_ev; - - if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID && - (local->scan_ssid_len != bss->ssid_len || - memcmp(local->scan_ssid, bss->ssid, bss->ssid_len) != 0)) - return current_ev; - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, - IW_EV_ADDR_LEN); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.length = bss->ssid_len; - iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, - bss->ssid); - - if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWMODE; - if (bss->capability & WLAN_CAPABILITY_ESS) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, - IW_EV_UINT_LEN); - } - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = bss->freq * 100000; - iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, - IW_EV_FREQ_LEN); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWENCODE; - if (bss->capability & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ""); - - if (bss && bss->wpa_ie) { - char *buf, *p; - int i; - buf = kmalloc(30 + bss->wpa_ie_len * 2, GFP_ATOMIC); - if (buf) { - p = buf; - p += sprintf(p, "wpa_ie="); - for (i = 0; i < bss->wpa_ie_len; i++) - p+= sprintf(p, "%02x", bss->wpa_ie[i]); - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(current_ev, end_buf, - &iwe, buf); - kfree(buf); - } - } - - if (bss && bss->rsn_ie) { - char *buf, *p; - int i; - buf = kmalloc(30 + bss->rsn_ie_len * 2, GFP_ATOMIC); - if (buf) { - p = buf; - p += sprintf(p, "rsn_ie="); - for (i = 0; i < bss->rsn_ie_len; i++) - p+= sprintf(p, "%02x", bss->rsn_ie[i]); - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(current_ev, end_buf, - &iwe, buf); - kfree(buf); - } - } - - if (bss) { - char *buf; - buf = kmalloc(30, GFP_ATOMIC); - if (buf) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "tsf=%016llx", bss->timestamp); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(current_ev, end_buf, - &iwe, buf); - kfree(buf); - } - } - - do { - char *buf, *p; - int i; - - if (!(local->scan_flags & IEEE80211_SCAN_EXTRA_INFO)) - break; - - buf = kmalloc(100, GFP_ATOMIC); - if (buf == NULL) - break; - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "bcn_int=%d", bss->beacon_int); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, - buf); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "rssi=%d", bss->rssi); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, - buf); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "capab=0x%04x", bss->capability); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, - buf); - - p = buf; - p += sprintf(p, "supp_rates="); - for (i = 0; i < bss->supp_rates_len; i++) - p+= sprintf(p, "%02x", bss->supp_rates[i]); - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, - buf); - - kfree(buf); - break; - } while (0); - - return current_ev; -} - - -int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len) -{ - struct ieee80211_local *local = dev->priv; - struct list_head *ptr; - char *current_ev = buf; - char *end_buf = buf + len; - struct ieee80211_sta_bss *bss; - - spin_lock_bh(&local->sta_bss_lock); - list_for_each(ptr, &local->sta_bss_list) { - bss = list_entry(ptr, struct ieee80211_sta_bss, list); - current_ev = ieee80211_sta_scan_result(dev, bss, current_ev, - end_buf); - } - spin_unlock_bh(&local->sta_bss_lock); - return current_ev - buf; -} - - -int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - kfree(ifsta->extra_ie); - if (len == 0) { - ifsta->extra_ie = NULL; - ifsta->extra_ie_len = 0; - return 0; - } - ifsta->extra_ie = kmalloc(len, GFP_KERNEL); - if (ifsta->extra_ie == NULL) { - ifsta->extra_ie_len = 0; - return -ENOMEM; - } - memcpy(ifsta->extra_ie, ie, len); - ifsta->extra_ie_len = len; - if (ifsta->bssid_set && ifsta->ssid_set && - ifsta->state != IEEE80211_AUTHENTICATE) - ieee80211_sta_new_auth(dev, ifsta); - return 0; -} - - -struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, - struct sk_buff *skb, u8 *bssid, - u8 *addr) -{ - struct ieee80211_local *local = dev->priv; - struct list_head *ptr; - struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = NULL; - struct net_device *sta_dev = NULL; - - /* TODO: Could consider removing the least recently used entry and - * allow new one to be added. */ - if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: No room for a new IBSS STA " - "entry " MACSTR "\n", dev->name, MAC2STR(addr)); - } - return NULL; - } - - spin_lock_bh(&local->sub_if_lock); - list_for_each(ptr, &local->sub_if_list) { - sdata = list_entry(ptr, struct ieee80211_sub_if_data, list); - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA && - memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { - sta_dev = sdata->dev; - break; - } - } - spin_unlock_bh(&local->sub_if_lock); - - if (sta_dev == NULL) - return NULL; - - printk(KERN_DEBUG "%s: Adding new IBSS station " MACSTR " (dev=%s)\n", - dev->name, MAC2STR(addr), sta_dev->name); - - sta = sta_info_add(local, dev, addr); - if (sta == NULL) { - return NULL; - } - - sta->dev = sta_dev; - sta->supp_rates = sdata->u.sta.supp_rates_bits; - - rate_control_rate_init(local, sta); - - return sta; /* caller will call sta_info_release() */ -} - - -int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - - printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n", - dev->name, reason); - - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - return -EINVAL; - - ieee80211_send_deauth(dev, ifsta, reason); - ieee80211_set_associated(dev, ifsta, 0); - return 0; -} - - -int ieee80211_sta_disassociate(struct net_device *dev, u16 reason) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - - printk(KERN_DEBUG "%s: disassociate(reason=%d)\n", - dev->name, reason); - - if (sdata->type != IEEE80211_SUB_IF_TYPE_STA) - return -EINVAL; - - if (!ifsta->associated) - return -1; - - ieee80211_send_disassoc(dev, ifsta, reason); - ieee80211_set_associated(dev, ifsta, 0); - return 0; -} diff --git a/target/linux/package/ieee80211-dscape/src/include/net/ieee80211.h b/target/linux/package/ieee80211-dscape/src/include/net/ieee80211.h deleted file mode 100644 index 5d8975527a..0000000000 --- a/target/linux/package/ieee80211-dscape/src/include/net/ieee80211.h +++ /dev/null @@ -1,872 +0,0 @@ -/* - * Low-level hardware driver -- IEEE 802.11 driver (80211.o) interface - * Copyright 2002-2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef IEEE80211_H -#define IEEE80211_H - -#include "ieee80211_shared.h" - -/* Note! Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsave() can be - * called in hardware interrupt context. The low-level driver must not call any - * other functions in hardware interrupt context. If there is a need for such - * call, the low-level driver should first ACK the interrupt and perform the - * IEEE 802.11 code call after this, e.g., from a scheduled tasklet (in - * software interrupt context). - */ - -/* - * Frame format used when passing frame between low-level hardware drivers - * and IEEE 802.11 driver the same as used in the wireless media, i.e., - * buffers start with IEEE 802.11 header and include the same octets that - * are sent over air. - * - * If hardware uses IEEE 802.3 headers (and perform 802.3 <-> 802.11 - * conversion in firmware), upper layer 802.11 code needs to be changed to - * support this. - * - * If the receive frame format is not the same as the real frame sent - * on the wireless media (e.g., due to padding etc.), upper layer 802.11 code - * could be updated to provide support for such format assuming this would - * optimize the performance, e.g., by removing need to re-allocation and - * copying of the data. - */ - -/* Interface version (used for compatibility verification) */ -#define IEEE80211_VERSION 2 - - -/* Channel information structure. Low-level driver is expected to fill in chan, - * freq, and val fields. Other fields will be filled in by 80211.o based on - * hostapd information and low-level driver does not need to use them. The - * limits for each channel will be provided in 'struct ieee80211_conf' when - * configuring the low-level driver with hw->config callback. */ -struct ieee80211_channel { - short chan; /* channel number (IEEE 802.11) */ - short freq; /* frequency in MHz */ - int val; /* hw specific value for the channel */ - int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */ - unsigned char power_level; - unsigned char antenna_max; -}; - -struct ieee80211_rate { - int rate; /* rate in 100 kbps */ - int val; /* hw specific value for the rate */ - int flags; /* IEEE80211_RATE_ flags */ - int val2; /* hw specific value for the rate when using short preamble - * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for - * 2, 5.5, and 11 Mbps) */ - signed char min_rssi_ack; - unsigned char min_rssi_ack_delta; - - /* following fields are set by 80211.o and need not be filled by the - * low-level driver */ - int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for - * optimizing channel utilization estimates */ -}; - -struct ieee80211_hw_modes { - int mode; - int num_channels; - struct ieee80211_channel *channels; - int num_rates; - struct ieee80211_rate *rates; - int xr_end; /* only used with Atheros XR */ -}; - -struct ieee80211_tx_queue_params { - int aifs; /* 0 .. 255; -1 = use default */ - int cw_min; /* 2^n-1: 1, 3, 7, .. , 1023; 0 = use default */ - int cw_max; /* 2^n-1: 1, 3, 7, .. , 1023; 0 = use default */ - int burst_time; /* maximum burst time in 0.1 ms (i.e., 10 = 1 ms); - * 0 = disabled */ -}; - -#define NUM_TX_DATA_QUEUES 6 - -struct ieee80211_tx_queue_stats_data { - unsigned int len; /* num packets in queue */ - unsigned int limit; /* queue len (soft) limit */ - unsigned int count; /* total num frames sent */ -}; - -struct ieee80211_tx_queue_stats { - struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES]; -}; - -#ifndef IEEE80211_TX_QUEUE_NUMS -#define IEEE80211_TX_QUEUE_NUMS -/* TODO: these need to be synchronized with hostapd_ioctl.h; make a shared - * header file that can be included into low-level drivers, 80211.o, and - * hostapd */ -enum { - IEEE80211_TX_QUEUE_DATA0 = 0, - IEEE80211_TX_QUEUE_DATA1 = 1, - IEEE80211_TX_QUEUE_DATA2 = 2, - IEEE80211_TX_QUEUE_DATA3 = 3, - IEEE80211_TX_QUEUE_DATA4 = 4, - IEEE80211_TX_QUEUE_SVP = 5, - IEEE80211_TX_QUEUE_AFTER_BEACON = 6, - IEEE80211_TX_QUEUE_BEACON = 7 -}; -#endif /* IEEE80211_TX_QUEUE_NUMS */ - - -struct ieee80211_low_level_stats { - unsigned int dot11ACKFailureCount; - unsigned int dot11RTSFailureCount; - unsigned int dot11FCSErrorCount; - unsigned int dot11RTSSuccessCount; -}; - -/* Transmit control fields. This data structure is passed to low-level driver - * with each TX frame. The low-level driver is responsible of configuring - * hardware to use given values (depending on what is supported). */ -#define HW_KEY_IDX_INVALID -1 - -struct ieee80211_tx_control { - enum { PKT_NORMAL = 0, PKT_PROBE_RESP } pkt_type; - int tx_rate; /* Transmit rate, given as the hw specific value for the - * rate (from struct ieee80211_rate) */ - int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw - * specific value for the rate (from - * struct ieee80211_rate) */ - /* 1 = only first attempt, 2 = one retry, .. */ - unsigned int retry_limit:8; - /* duration field for RTS/CTS frame */ - unsigned int rts_cts_duration:16; - /* TODO: change these bit flags to use one unsigned int variable and - * defines with BIT(n). These are copied to TX status structure and - * this will make the code faster and smaller. */ - unsigned int req_tx_status:1; /* request TX status callback for this - * frame */ - unsigned int do_not_encrypt:1; /* send this frame without encryption; - * e.g., for EAPOL frames */ - unsigned int use_rts_cts:1; /* Use RTS-CTS before sending frame. */ - unsigned int use_cts_protect:1; /* Use CTS protection for the frame - * (e.g., for combined 802.11g / - * 802.11b networks) */ - unsigned int no_ack:1; /* Tell the low level not to wait for an ack */ - unsigned int rate_ctrl_probe:1; - unsigned int clear_dst_mask:1; - unsigned int requeue:1; - /* following three flags are only used with Atheros Super A/G */ - unsigned int compress:1; - unsigned int turbo_prime_notify:1; /* notify HostaAPd after frame - * transmission */ - unsigned int fast_frame:1; - - unsigned int atheros_xr:1; /* only used with Atheros XR */ - - unsigned int power_level:8; /* per-packet transmit power level, in dBm - */ - unsigned int antenna_sel:4; /* 0 = default/diversity, - * 1 = Ant0, 2 = Ant1 */ - int key_idx:8; /* -1 = do not encrypt, >= 0 keyidx from hw->set_key() - */ - int icv_len:8; /* Length of the ICV/MIC field in octets */ - int iv_len:8; /* Length of the IV field in octets */ - unsigned int queue:4; /* hardware queue to use for this frame; - * 0 = highest, hw->queues-1 = lowest */ - unsigned int sw_retry_attempt:4; /* no. of times hw has tried to - * transmit frame (not incl. hw retries) */ - -#if 0 - int rateidx; /* internal 80211.o rateidx, to be copied to tx_status */ - int alt_retry_rate; /* retry rate for the last retries, given as the - * hw specific value for the rate (from - * struct ieee80211_rate). To be used to limit - * packet dropping when probing higher rates, if hw - * supports multiple retry rates. -1 = not used */ -#endif -}; - -#define IEEE80211_CB_MAGIC 0xAAB80211 - -struct ieee80211_tx_packet_data { - unsigned int magic; - struct ieee80211_tx_control control; - unsigned long jiffies; - struct ieee80211_sub_if_data *sdata; -}; - -#define RX_FLAG_MMIC_ERROR 0x1 -#define RX_FLAG_DECRYPTED 0x2 -#define RX_FLAG_XR_DOUBLE_CHIRP 0x4 - -/* Receive status. The low-level driver should provide this information - * (the subset supported by hardware) to the 802.11 code with each received - * frame. - * Current implementation copies this into skb->cb, so it must be less than - * 48 bytes. */ -struct ieee80211_rx_status { -#if 0 - u64 hosttime; - u64 mactime; -#endif - int freq; /* receive frequency in Mhz */ - int channel; - int phymode; - int ssi; - int antenna; - int rate; - int flag; -}; - -/* Transmit status. The low-level driver should provide this information - * (the subset supported by hardware) to the 802.11 code for each transmit - * frame. */ -struct ieee80211_tx_status { - /* flags copied from struct ieee80211_tx_control) */ - unsigned int req_tx_status:1; /* whether TX status was explicitly - * requested */ - unsigned int rate_ctrl_probe:1; /* whether this was a probe packet from - * rate control */ - unsigned int tx_filtered:1; - - /* following three fields are only used with Atheros Super A/G */ - unsigned int turbo_prime_notify:1; /* notify HostAPd - CTS for Turbo - * Prime is sent */ - int queue_length; /* information about TX queue */ - int queue_number; - - int ack; /* whether the TX frame was ACKed */ - int ack_signal; /* measured signal strength of the ACK frame */ - int excessive_retries; - int retry_count; - int rateidx; /* internal 80211.o rateidx, to be copied to tx_status */ -}; - - -struct ieee80211_conf { - int channel; /* IEEE 802.11 channel number */ - int freq; /* MHz */ - int channel_val; /* hw specific value for the channel */ - - int mode; /* IW_MODE_ */ - - int phymode; /* MODE_IEEE80211A, .. */ - unsigned int regulatory_domain; - int adm_status; - - int beacon_int; - - /* Bitfields, grouped together */ - - int sw_encrypt:1; - int sw_decrypt:1; - int short_slot_time:1; /* use IEEE 802.11g Short Slot Time */ - int ssid_hidden:1; /* do not broadcast the ssid */ - - /* these fields are used by low level drivers for hardware - * that generate beacons independently */ - u8 *ssid; - size_t ssid_len; - u8 *generic_elem; - size_t generic_elem_len; - - u8 power_level; /* transmit power limit for current - * regulatory domain; in dBm */ - u8 antenna_max; /* maximum antenna gain */ - short tx_power_reduction; /* in 0.1 dBm */ - - int antenna_sel; /* default antenna conf: - * 0 = default/diversity, - * 1 = Ant0, - * 2 = Ant1 */ - - int calib_int; /* hw/radio calibration interval in - * seconds */ - int antenna_def; - int antenna_mode; - - u8 bssid_mask[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff = 1 BSSID */ - int bss_count; - - int atheros_super_ag_compression; - int atheros_super_ag_fast_frame; - int atheros_super_ag_burst; - int atheros_super_ag_wme_ele; - int atheros_super_ag_turbo_g; - int atheros_super_ag_turbo_prime; - - int atheros_xr; - - u8 client_bssid[ETH_ALEN]; - - /* Following five fields are used for IEEE 802.11H */ - unsigned int radar_detect; - unsigned int spect_mgmt; - unsigned int quiet_duration; /* duration of quiet period */ - unsigned int quiet_offset; /* how far into the beacon is the quiet - * period */ - unsigned int quiet_period; -}; - - -typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL } -ieee80211_key_alg; - - -struct ieee80211_key_conf { - - int hw_key_idx; /* filled + used by low-level driver */ - ieee80211_key_alg alg; - int keylen; - - int force_sw_encrypt:1; /* to be cleared by low-level driver */ - int keyidx:8; /* WEP key index */ - int default_tx_key:1; /* This key is the new default TX key - * (used only for broadcast keys). */ - int default_wep_only:1; /* static WEP is the only configured security - * policy; this allows some low-level drivers - * to determine when hwaccel can be used */ - u8 key[0]; -}; - -#define IEEE80211_SCAN_START 1 -#define IEEE80211_SCAN_END 2 - -struct ieee80211_scan_conf { - int scan_channel; /* IEEE 802.11 channel number to do passive scan - * on */ - int scan_freq; /* new freq in MHz to switch to for passive scan - */ - int scan_channel_val; /* hw specific value for the channel */ - int scan_phymode; /* MODE_IEEE80211A, .. */ - unsigned char scan_power_level; - unsigned char scan_antenna_max; - - - int running_channel; /* IEEE 802.11 channel number we operate on - * normally */ - int running_freq; /* freq in MHz we're operating on normally */ - int running_channel_val; /* hw specific value for the channel */ - int running_phymode; - unsigned char running_power_level; - unsigned char running_antenna_max; - - int scan_time; /* time a scan will take in us */ - int tries; - - struct sk_buff *skb; /* skb to transmit before changing channels, maybe - * NULL for none */ - struct ieee80211_tx_control *tx_control; - -}; - -#ifndef IW_MODE_ADHOC -#define IW_MODE_ADHOC 1 -#endif - -#ifndef IW_MODE_INFRA -#define IW_MODE_INFRA 2 -#endif - -#ifndef IW_MODE_MASTER -#define IW_MODE_MASTER 3 -#endif - -#ifndef IW_MODE_MONITOR -#define IW_MODE_MONITOR 6 -#endif - -#define IEEE80211_SEQ_COUNTER_RX 0 -#define IEEE80211_SEQ_COUNTER_TX 1 - -typedef enum { - SET_KEY, DISABLE_KEY, REMOVE_ALL_KEYS, - ENABLE_COMPRESSION, DISABLE_COMPRESSION -} set_key_cmd; - -/* Configuration block used by the low-level driver to tell 802.11 code about - * supported hardware features and to pass function pointers for callback - * functions. */ -struct ieee80211_hw { - int version; /* IEEE80211_VERSION */ - - /* Driver name */ - char *name; - - /* TODO: frame_type 802.11/802.3, sw_encryption requirements */ - - /* Some wireless LAN chipsets generate beacons in the hardware/firmware - * and others rely on host generated beacons. This option is used to - * configure upper layer IEEE 802.11 module to generate beacons. The - * low-level driver can use ieee80211_beacon_get() to fetch next - * beacon frame. */ - int host_gen_beacon:1; - - - /* Some devices handle decryption internally and do not - * indicate whether the frame was encrypted (unencrypted frames - * will be dropped by the hardware, unless specifically allowed - * through) */ - int device_hides_wep:1; - - /* Whether RX frames passed to ieee80211_rx() include FCS in the end - */ - int rx_includes_fcs:1; - - /* Some wireless LAN chipsets buffer broadcast/multicast frames for - * power saving stations in the hardware/firmware and others rely on - * the host system for such buffering. This option is used to - * configure upper layer IEEE 802.11 to buffer broadcast/multicast - * frames when there are power saving stations so that low-level driver - * can fetch them with ieee80211_get_buffered_bc(). */ - int host_broadcast_ps_buffering:1; - - int wep_include_iv:1; - int data_nullfunc_ack:1; /* will data nullfunc frames get proper - * TX status callback */ - - /* Force sw version of encryption for TKIP packets if WMM is enabled. - */ - int no_tkip_wmm_hwaccel:1; - - /* 1 if the payload needs to be padded at even boundaries after the - * header */ - unsigned int extra_hdr_room:1; - - /* Some devices handle Michael MIC internally and do not include MIC in - * the received packets given to 80211.o. device_strips_mic must be set - * for such devices. ISWEP bit is still expected to be set in the IEEE - * 802.11 header with this option unlike with device_hides_wep option. - */ - unsigned int device_strips_mic:1; - - /* 1 = low-level driver supports skb fraglist (NETIF_F_FRAGLIST), i.e., - * more than one skb per frame */ - unsigned int fraglist; - - /* This is the time in us to change channels - */ - int channel_change_time; - - int num_modes; - struct ieee80211_hw_modes *modes; - - /* Handler that 802.11 module calls for each transmitted frame. - * skb contains the buffer starting from the IEEE 802.11 header. - * The low-level driver should send the frame out based on - * configuration in the TX control data. */ - int (*tx)(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_tx_control *control); - - /* Handler for performing hardware reset. */ - int (*reset)(struct net_device *dev); - - /* Handler that is called when any netdevice attached to the hardware - * device is set UP for the first time. This can be used, e.g., to - * enable interrupts and beacon sending. */ - int (*open)(struct net_device *dev); - - /* Handler that is called when the last netdevice attached to the - * hardware device is set DOWN. This can be used, e.g., to disable - * interrupts and beacon sending. */ - int (*stop)(struct net_device *dev); - - /* Handler for configuration requests. IEEE 802.11 code calls this - * function to change hardware configuration, e.g., channel. */ - int (*config)(struct net_device *dev, struct ieee80211_conf *conf); - - /* Set TIM bit handler. If the hardware/firmware takes care of beacon - * generation, IEEE 802.11 code uses this function to tell the - * low-level to set (or clear if set==0) TIM bit for the given aid. If - * host system is used to generate beacons, this handler is not used - * and low-level driver should set it to NULL. */ - int (*set_tim)(struct net_device *dev, int aid, int set); - - /* Set encryption key. IEEE 802.11 module calls this function to set - * encryption keys. addr is ff:ff:ff:ff:ff:ff for default keys and - * station hwaddr for individual keys. aid of the station is given - * to help low-level driver in selecting which key->hw_key_idx to use - * for this key. TX control data will use the hw_key_idx selected by - * the low-level driver. */ - int (*set_key)(struct net_device *dev, set_key_cmd cmd, u8 *addr, - struct ieee80211_key_conf *key, int aid); - - /* Set TX key index for default/broadcast keys. This is needed in cases - * where wlan card is doing full WEP/TKIP encapsulation (wep_include_iv - * is not set), in other cases, this function pointer can be set to - * NULL since 80211.o takes care of selecting the key index for each - * TX frame. */ - int (*set_key_idx)(struct net_device *dev, int idx); - - /* Enable/disable IEEE 802.1X. This item requests wlan card to pass - * unencrypted EAPOL-Key frames even when encryption is configured. - * If the wlan card does not require such a configuration, this - * function pointer can be set to NULL. 80211.o */ - int (*set_ieee8021x)(struct net_device *dev, int use_ieee8021x); - - /* Set port authorization state (IEEE 802.1X PAE) to be authorized - * (authorized=1) or unauthorized (authorized=0). This function can be - * used if the wlan hardware or low-level driver implements PAE. - * 80211.o module will anyway filter frames based on authorization - * state, so this function pointer can be NULL if low-level driver does - * not require event notification about port state changes. */ - int (*set_port_auth)(struct net_device *dev, u8 *addr, int authorized); - - /* Ask the hardware to do a passive scan on a new channel. The hardware - * will do what ever is required to nicely leave the current channel - * including transmit any CTS packets, etc. */ - int (*passive_scan)(struct net_device *dev, int state, - struct ieee80211_scan_conf *conf); - - /* return low-level statistics */ - int (*get_stats)(struct net_device *dev, - struct ieee80211_low_level_stats *stats); - - /* Enable/disable test modes; mode = IEEE80211_TEST_* */ - int (*test_mode)(struct net_device *dev, int mode); - - /* Configuration of test parameters */ - int (*test_param)(struct net_device *dev, int param, int value); - - /* Change MAC address. addr is pointer to struct sockaddr. */ - int (*set_mac_address)(struct net_device *dev, void *addr); - - /* For devices that generate their own beacons and probe response - * or association responses this updates the state of privacy_invoked - * returns 0 for success or an error number */ - - int (*set_privacy_invoked)(struct net_device *dev, - int privacy_invoked); - - /* For devices that have internal sequence counters, allow 802.11 - * code to access the current value of a counter */ - int (*get_sequence_counter)(struct net_device *dev, - u8* addr, u8 keyidx, u8 txrx, - u32* iv32, u16* iv16); - - /* Configuration of RTS threshold (if device needs it) */ - int (*set_rts_threshold)(struct net_device *dev, u32 value); - - /* Configuration of fragmentation threshold (if device needs it) */ - int (*set_frag_threshold)(struct net_device *dev, u32 value); - - /* Configuration of retry limits (if device needs it) */ - int (*set_retry_limit)(struct net_device *dev, u32 short_retry, - u32 long_retr); - - /* Number of STAs in STA table notification (NULL = disabled) */ - void (*sta_table_notification)(struct net_device *dev, int num_sta); - - /* Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), - * bursting) for a hardware TX queue. - * queue = IEEE80211_TX_QUEUE_*. */ - int (*conf_tx)(struct net_device *dev, int queue, - const struct ieee80211_tx_queue_params *params); - - /* Get statistics of the current TX queue status. This is used to get - * number of currently queued packets (queue length), maximum queue - * size (limit), and total number of packets sent using each TX queue - * (count). This information is used for WMM to find out which TX - * queues have room for more packets and by hostapd to provide - * statistics about the current queueing state to external programs. */ - int (*get_tx_stats)(struct net_device *dev, - struct ieee80211_tx_queue_stats *stats); - - /* Number of available hardware TX queues for data packets. - * WMM requires at least four queues. */ - int queues; - - /* Get the current TSF timer value from firmware/hardware. Currently, - * this is only used for IBSS mode debugging and, as such, is not a - * required function. */ - u64 (*get_tsf)(struct net_device *dev); - - /* Reset the TSF timer and allow firmware/hardware to synchronize with - * other STAs in the IBSS. This is only used in IBSS mode. This - * function is optional if the firmware/hardware takes full care of - * TSF synchronization. */ - void (*reset_tsf)(struct net_device *dev); - - /* Setup beacon data for IBSS beacons. Unlike access point (Master), - * IBSS uses a fixed beacon frame which is configured using this - * function. This handler is required only for IBSS mode. */ - int (*beacon_update)(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_tx_control *control); - - /* Determine whether the last IBSS beacon was sent by us. This is - * needed only for IBSS mode and the result of this function is used to - * determine whether to reply to Probe Requests. */ - int (*tx_last_beacon)(struct net_device *dev); - - /* Optional handler for XR-in-use notification. */ - int (*atheros_xr_in_use)(struct net_device *dev, int in_use); -}; - -/* Allocate a new hardware device. This must be called once for each - * hardware device. The returned pointer must be used to refer to this - * device when calling other functions. 802.11 code allocates a private data - * area for the low-level driver. The size of this area is given as - * priv_data_len. ieee80211_dev_hw_data() is used to get a pointer to the - * private data area. - * - * Note: in this version of the interface the returned pointer is struct - * net_device *. This may change in the future and low-level driver should - * not refer the device data directly to remain compatible with the future - * versions of the interface. */ -struct net_device *ieee80211_alloc_hw(size_t priv_data_len, - void (*setup)(struct net_device *)); - -/* Register hardware device to the IEEE 802.11 code and kernel. Low-level - * drivers must call this function before using any other IEEE 802.11 - * function. */ -int ieee80211_register_hw(struct net_device *dev, struct ieee80211_hw *hw); - -/* This function is allowed to update hardware configuration (e.g., list of - * supported operation modes and rates). */ -int ieee80211_update_hw(struct net_device *dev, struct ieee80211_hw *hw); - -/* Unregister a hardware device. This function instructs 802.11 code to free - * allocated resources and unregister netdevices from the kernel. */ -void ieee80211_unregister_hw(struct net_device *dev); - -/* Free allocated net_device including private data of a driver. */ -void ieee80211_free_hw(struct net_device *dev); - -/* Receive frame callback function. The low-level driver uses this function to - * send received frames to the IEEE 802.11 code. Receive buffer (skb) must - * start with IEEE 802.11 header. */ -void ieee80211_rx(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *status); -void ieee80211_rx_irqsafe(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *status); - -/* Transmit status callback function. The low-level driver must call this - * function to report transmit status for all the TX frames that had - * req_tx_status set in the transmit control fields. In addition, this should - * be called at least for all unicast frames to provide information for TX rate - * control algorithm. In order to maintain all statistics, this function is - * recommended to be called after each frame, including multicast/broadcast, is - * sent. */ -void ieee80211_tx_status(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_tx_status *status); -void ieee80211_tx_status_irqsafe(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_tx_status *status); - -/* Beacon generation function. If the beacon frames are generated by the host - * system (i.e., not in hardware/firmware), the low-level driver uses this - * function to receive the next beacon frame from the 802.11 code. The - * low-level is responsible for calling this function before beacon data is - * needed (e.g., based on hardware interrupt). Returned skb is used only once - * and low-level driver is responsible of freeing it. */ -struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int bss_idx, - struct ieee80211_tx_control *control); - -/* Function for accessing buffered broadcast and multicast frames. If - * hardware/firmware does not implement buffering of broadcast/multicast - * frames when power saving is used, 802.11 code buffers them in the host - * memory. The low-level driver uses this function to fetch next buffered - * frame. In most cases, this is used when generating beacon frame. This - * function returns a pointer to the next buffered skb or NULL if no more - * buffered frames are available. - * - * Note: buffered frames are returned only after DTIM beacon frame was - * generated with ieee80211_beacon_get() and the low-level driver must thus - * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns - * NULL if the previous generated beacon was not DTIM, so the low-level driver - * does not need to check for DTIM beacons separately and should be able to - * use common code for all beacons. */ -struct sk_buff * -ieee80211_get_buffered_bc(struct net_device *dev, int bss_idx, - struct ieee80211_tx_control *control); - -/* Low level drivers that have their own MLME and MAC indicate - * the aid for an associating station with this call */ -int ieee80211_set_aid_for_sta(struct net_device *dev, u8 *peer_address, - u16 aid); - - -/* Given an sk_buff with a raw 802.11 header at the data pointer this function - * returns the 802.11 header length in bytes (not including encryption - * headers). If the data in the sk_buff is too short to contain a valid 802.11 - * header the function returns 0. - */ -int ieee80211_get_hdrlen_from_skb(struct sk_buff *skb); - -/* Like ieee80211_get_hdrlen_from_skb() but takes a FC in CPU order. */ -int ieee80211_get_hdrlen(u16 fc); - -/* Function for net interface operation. IEEE 802.11 may use multiple kernel - * netdevices for each hardware device. The low-level driver does not "see" - * these interfaces, so it should use this function to perform netif - * operations on all interface. */ -typedef enum { - NETIF_ATTACH, NETIF_DETACH, NETIF_START, NETIF_STOP, NETIF_WAKE, - NETIF_IS_STOPPED, NETIF_UPDATE_TX_START -} Netif_Oper; -int ieee80211_netif_oper(struct net_device *dev, Netif_Oper op); - - -/* - * Function to get hardware configuration information - * by the low level driver should it need it. - */ -struct ieee80211_conf * -ieee80211_get_hw_conf(struct net_device *dev); - - -/* Return a pointer to the low-level private data area for the given device. */ -void * ieee80211_dev_hw_data(struct net_device *dev); -/* Return a pointer to network statistics data area for the given device. */ -void * ieee80211_dev_stats(struct net_device *dev); - -/* Function to indicate Radar Detection. The low level driver must call this - * function to indicate the presence of radar in the current channel. - * Additionally the radar type also could be sent */ -int ieee80211_radar_status(struct net_device *dev, int channel, int radar, - int radar_type); - -/* Test modes */ -enum { - IEEE80211_TEST_DISABLE = 0 /* terminate testing */, - IEEE80211_TEST_UNMASK_CHANNELS = 1 /* allow all channels to be used */, - IEEE80211_TEST_CONTINUOUS_TX = 2, -}; - -/* Test parameters */ -enum { - /* TX power in hardware specific raw value */ - IEEE80211_TEST_PARAM_TX_POWER_RAW = 0, - /* TX rate in hardware specific raw value */ - IEEE80211_TEST_PARAM_TX_RATE_RAW = 1, - /* Continuous TX pattern (32-bit) */ - IEEE80211_TEST_PARAM_TX_PATTERN = 2, - /* TX power in 0.1 dBm, 100 = 10 dBm */ - IEEE80211_TEST_PARAM_TX_POWER = 3, - /* TX rate in 100 kbps, 540 = 54 Mbps */ - IEEE80211_TEST_PARAM_TX_RATE = 4, - IEEE80211_TEST_PARAM_TX_ANT_SEL_RAW = 5, -}; - -/* ieee80211_tx_led called with state == 1 when the first frame is queued - * with state == 0 when the last frame is transmitted and tx queue is empty - */ -void ieee80211_tx_led(int state, struct net_device *dev); -/* ieee80211_rx_led is called each time frame is received, state is not used - * (== 2) - */ -void ieee80211_rx_led(int state, struct net_device *dev); - - -/* IEEE 802.11 defines */ - -#define FCS_LEN 4 - -#define WLAN_FC_PVER 0x0003 -#define WLAN_FC_TODS 0x0100 -#define WLAN_FC_FROMDS 0x0200 -#define WLAN_FC_MOREFRAG 0x0400 -#define WLAN_FC_RETRY 0x0800 -#define WLAN_FC_PWRMGT 0x1000 -#define WLAN_FC_MOREDATA 0x2000 -#define WLAN_FC_ISWEP 0x4000 -#define WLAN_FC_ORDER 0x8000 - -#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2) -#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & 0x000f) -#define WLAN_GET_SEQ_SEQ(seq) ((seq) >> 4) - -#define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08) - -#define WLAN_FC_TYPE_MGMT 0 -#define WLAN_FC_TYPE_CTRL 1 -#define WLAN_FC_TYPE_DATA 2 - -/* management */ -#define WLAN_FC_STYPE_ASSOC_REQ 0 -#define WLAN_FC_STYPE_ASSOC_RESP 1 -#define WLAN_FC_STYPE_REASSOC_REQ 2 -#define WLAN_FC_STYPE_REASSOC_RESP 3 -#define WLAN_FC_STYPE_PROBE_REQ 4 -#define WLAN_FC_STYPE_PROBE_RESP 5 -#define WLAN_FC_STYPE_BEACON 8 -#define WLAN_FC_STYPE_ATIM 9 -#define WLAN_FC_STYPE_DISASSOC 10 -#define WLAN_FC_STYPE_AUTH 11 -#define WLAN_FC_STYPE_DEAUTH 12 -#define WLAN_FC_STYPE_ACTION 13 - -/* control */ -#define WLAN_FC_STYPE_PSPOLL 10 -#define WLAN_FC_STYPE_RTS 11 -#define WLAN_FC_STYPE_CTS 12 -#define WLAN_FC_STYPE_ACK 13 -#define WLAN_FC_STYPE_CFEND 14 -#define WLAN_FC_STYPE_CFENDACK 15 - -/* data */ -#define WLAN_FC_STYPE_DATA 0 -#define WLAN_FC_STYPE_DATA_CFACK 1 -#define WLAN_FC_STYPE_DATA_CFPOLL 2 -#define WLAN_FC_STYPE_DATA_CFACKPOLL 3 -#define WLAN_FC_STYPE_NULLFUNC 4 -#define WLAN_FC_STYPE_CFACK 5 -#define WLAN_FC_STYPE_CFPOLL 6 -#define WLAN_FC_STYPE_CFACKPOLL 7 -#define WLAN_FC_STYPE_QOS_DATA 8 -#define WLAN_FC_STYPE_QOS_DATA_CFACK 9 -#define WLAN_FC_STYPE_QOS_DATA_CFPOLL 10 -#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL 11 -#define WLAN_FC_STYPE_QOS_NULLFUNC 12 -#define WLAN_FC_STYPE_QOS_CFACK 13 -#define WLAN_FC_STYPE_QOS_CFPOLL 14 -#define WLAN_FC_STYPE_QOS_CFACKPOLL 15 - - -#define IEEE80211_MAX_FRAG_THRESHOLD 2346 -#define IEEE80211_MAX_RTS_THRESHOLD 2347 - -struct ieee80211_hdr { - u16 frame_control; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; - u8 addr4[6]; -} __attribute__ ((packed)); - -/* return a pointer to the source address (SA) */ -static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) -{ - u8 *raw = (u8 *) hdr; - u8 tofrom = (*(raw+1)) & 3; /* get the TODS and FROMDS bits */ - - switch (tofrom) { - case 2: - return hdr->addr3; - case 3: - return hdr->addr4; - } - return hdr->addr2; -} - -/* return a pointer to the destination address (DA) */ -static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) -{ - u8 *raw = (u8 *) hdr; - u8 to_ds = (*(raw+1)) & 1; /* get the TODS bit */ - - if (to_ds) - return hdr->addr3; - return hdr->addr1; -} - -static inline int ieee80211_get_morefrag(struct ieee80211_hdr *hdr) -{ - return (le16_to_cpu(hdr->frame_control) & WLAN_FC_MOREFRAG) != 0; -} - -#endif /* IEEE80211_H */ diff --git a/target/linux/package/ieee80211-dscape/src/include/net/ieee80211_common.h b/target/linux/package/ieee80211-dscape/src/include/net/ieee80211_common.h deleted file mode 100644 index 68c1663861..0000000000 --- a/target/linux/package/ieee80211-dscape/src/include/net/ieee80211_common.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * IEEE 802.11 driver (80211.o) -- hostapd interface - * Copyright 2002-2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef IEEE80211_COMMON_H -#define IEEE80211_COMMON_H - -/* - * This is common header information with user space. It is used on all - * frames sent to wlan#ap interface. - */ - -#define IEEE80211_FI_VERSION 0x80211001 - -struct ieee80211_frame_info { - u32 version; - u32 length; - u64 mactime; - u64 hosttime; - u32 phytype; - u32 channel; - u32 datarate; - u32 antenna; - u32 priority; - u32 ssi_type; - u32 ssi_signal; - u32 ssi_noise; - u32 preamble; - u32 encoding; - - /* Note: this structure is otherwise identical to capture format used - * in linux-wlan-ng, but this additional field is used to provide meta - * data about the frame to hostapd. This was the easiest method for - * providing this information, but this might change in the future. */ - u32 msg_type; -} __attribute__ ((packed)); - - -enum ieee80211_msg_type { - ieee80211_msg_normal = 0, - ieee80211_msg_tx_callback_ack = 1, - ieee80211_msg_tx_callback_fail = 2, - ieee80211_msg_passive_scan = 3, - ieee80211_msg_wep_frame_unknown_key = 4, - ieee80211_msg_michael_mic_failure = 5, - ieee80211_msg_monitor = 6, - ieee80211_msg_sta_not_assoc = 7, - ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */, - ieee80211_msg_key_threshold_notification = 9, - ieee80211_msg_radar = 11, -}; - -struct ieee80211_msg_set_aid_for_sta { - char sta_address[ETH_ALEN]; - u16 aid; -}; - -struct ieee80211_msg_key_notification { - int tx_rx_count; - char ifname[IFNAMSIZ]; - u8 addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast keys */ -}; - - -enum ieee80211_phytype { - ieee80211_phytype_fhss_dot11_97 = 1, - ieee80211_phytype_dsss_dot11_97 = 2, - ieee80211_phytype_irbaseband = 3, - ieee80211_phytype_dsss_dot11_b = 4, - ieee80211_phytype_pbcc_dot11_b = 5, - ieee80211_phytype_ofdm_dot11_g = 6, - ieee80211_phytype_pbcc_dot11_g = 7, - ieee80211_phytype_ofdm_dot11_a = 8, - ieee80211_phytype_dsss_dot11_turbog = 255, - ieee80211_phytype_dsss_dot11_turbo = 256, -}; - -enum ieee80211_ssi_type { - ieee80211_ssi_none = 0, - ieee80211_ssi_norm = 1, /* normalized, 0-1000 */ - ieee80211_ssi_dbm = 2, - ieee80211_ssi_raw = 3, /* raw SSI */ -}; - -struct ieee80211_radar_info { - int channel; - int radar; - int radar_type; -}; - -#endif /* IEEE80211_COMMON_H */ diff --git a/target/linux/package/ieee80211-dscape/src/include/net/ieee80211_mgmt.h b/target/linux/package/ieee80211-dscape/src/include/net/ieee80211_mgmt.h deleted file mode 100644 index 86732684ea..0000000000 --- a/target/linux/package/ieee80211-dscape/src/include/net/ieee80211_mgmt.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * IEEE 802.11 -- shared defines for 80211.o and hostapd - * Copyright 2002, Jouni Malinen - * Copyright 2002-2004, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef IEEE802_11_MGMT_H -#define IEEE802_11_MGMT_H - - -struct ieee80211_mgmt { - u16 frame_control; - u16 duration; - u8 da[6]; - u8 sa[6]; - u8 bssid[6]; - u16 seq_ctrl; - union { - struct { - u16 auth_alg; - u16 auth_transaction; - u16 status_code; - /* possibly followed by Challenge text */ - u8 variable[0]; - } __attribute__ ((packed)) auth; - struct { - u16 reason_code; - } __attribute__ ((packed)) deauth; - struct { - u16 capab_info; - u16 listen_interval; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) assoc_req; - struct { - u16 capab_info; - u16 status_code; - u16 aid; - /* followed by Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) assoc_resp, reassoc_resp; - struct { - u16 capab_info; - u16 listen_interval; - u8 current_ap[6]; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) reassoc_req; - struct { - u16 reason_code; - } __attribute__ ((packed)) disassoc; - struct { - u8 timestamp[8]; - u16 beacon_int; - u16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params, TIM */ - u8 variable[0]; - } __attribute__ ((packed)) beacon; - struct { - /* only variable items: SSID, Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) probe_req; - struct { - u8 timestamp[8]; - u16 beacon_int; - u16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params */ - u8 variable[0]; - } __attribute__ ((packed)) probe_resp; - struct { - u8 category; - union { - struct { - u8 action_code; - u8 dialog_token; - u8 status_code; - u8 variable[0]; - } __attribute__ ((packed)) wme_action; - struct{ - u8 action_code; - u8 element_id; - u8 length; - u8 switch_mode; - u8 new_chan; - u8 switch_count; - } __attribute__((packed)) chan_switch; - } u; - } __attribute__ ((packed)) action; - } u; -} __attribute__ ((packed)); - - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 -#define WLAN_AUTH_LEAP 128 - -#define WLAN_AUTH_CHALLENGE_LEN 128 - -#define WLAN_CAPABILITY_ESS BIT(0) -#define WLAN_CAPABILITY_IBSS BIT(1) -#define WLAN_CAPABILITY_CF_POLLABLE BIT(2) -#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3) -#define WLAN_CAPABILITY_PRIVACY BIT(4) -#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5) -#define WLAN_CAPABILITY_PBCC BIT(6) -#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7) -/* 802.11h */ -#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8) -#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10) -#define WLAN_CAPABILITY_DSSS_OFDM BIT(13) - -/* Status codes */ -#define WLAN_STATUS_SUCCESS 0 -#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 -#define WLAN_STATUS_CAPS_UNSUPPORTED 10 -#define WLAN_STATUS_REASSOC_NO_ASSOC 11 -#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 -#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 -#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 -#define WLAN_STATUS_CHALLENGE_FAIL 15 -#define WLAN_STATUS_AUTH_TIMEOUT 16 -#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 -#define WLAN_STATUS_ASSOC_DENIED_RATES 18 -/* 802.11b */ -#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 -#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 -#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 -/* 802.11h */ -#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22 -#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23 -#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24 -/* 802.11g */ -#define WLAN_STATUS_ASSOC_DENOED_NO_SHORT_SLOT_TIME 25 -#define WLAN_STATUS_ASSOC_DENOED_NO_ER_PBCC 26 -#define WLAN_STATUS_ASSOC_DENOED_NO_DSSS_OFDM 27 - - -/* Reason codes */ -#define WLAN_REASON_UNSPECIFIED 1 -#define WLAN_REASON_PREV_AUTH_NOT_VALID 2 -#define WLAN_REASON_DEAUTH_LEAVING 3 -#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 -#define WLAN_REASON_DISASSOC_AP_BUSY 5 -#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 -#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 -#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 -#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 -/* 802.11h */ -#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10 -#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11 - -#define WLAN_REASON_MIC_FAILURE 14 - - -/* Information Element IDs */ -#define WLAN_EID_SSID 0 -#define WLAN_EID_SUPP_RATES 1 -#define WLAN_EID_FH_PARAMS 2 -#define WLAN_EID_DS_PARAMS 3 -#define WLAN_EID_CF_PARAMS 4 -#define WLAN_EID_TIM 5 -#define WLAN_EID_IBSS_PARAMS 6 -#define WLAN_EID_COUNTRY 7 -#define WLAN_EID_CHALLENGE 16 -/* EIDs defined as part fo 11h - starts */ -#define WLAN_EID_PWR_CONSTRAINT 32 -#define WLAN_EID_PWR_CAPABILITY 33 -#define WLAN_EID_TPC_REQUEST 34 -#define WLAN_EID_TPC_REPORT 35 -#define WLAN_EID_SUPPORTED_CHANNELS 36 -#define WLAN_EID_CHANNEL_SWITCH 37 -#define WLAN_EID_MEASURE_REQUEST 38 -#define WLAN_EID_MEASURE_REPORT 39 -#define WLAN_EID_QUITE 40 -#define WLAN_EID_IBSS_DFS 41 -/* EIDs defined as part fo 11h - ends */ -#define WLAN_EID_ERP_INFO 42 -#define WLAN_EID_RSN 48 -#define WLAN_EID_EXT_SUPP_RATES 50 -#define WLAN_EID_WPA 221 -#define WLAN_EID_GENERIC 221 -#define WLAN_EID_VENDOR_SPECIFIC 221 - - - -#define ATHEROS_INFO_USEXR BIT(3) - -#endif /* IEEE802_11_MGMT_H */ diff --git a/target/linux/package/ieee80211-dscape/src/include/net/ieee80211_shared.h b/target/linux/package/ieee80211-dscape/src/include/net/ieee80211_shared.h deleted file mode 100644 index 95355bb222..0000000000 --- a/target/linux/package/ieee80211-dscape/src/include/net/ieee80211_shared.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * IEEE 802.11 -- shared defines for low-level drivers, 80211.o, and hostapd - * Copyright 2002-2004, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef IEEE80211_SHARED_H -#define IEEE80211_SHARED_H - -/* 802.11g is backwards-compatible with 802.11b, so a wlan card can - * actually be both in 11b and 11g modes at the same time. */ -enum { - MODE_IEEE80211A = 0 /* IEEE 802.11a */, - MODE_IEEE80211B = 1 /* IEEE 802.11b only */, - MODE_ATHEROS_TURBO = 2 /* Atheros Turbo mode (2x.11a at 5 GHz) */, - MODE_IEEE80211G = 3 /* IEEE 802.11g (and 802.11b compatibility) */, - MODE_ATHEROS_TURBOG = 4 /* Atheros Turbo mode (2x.11g at 2.4 GHz) */, - MODE_ATHEROS_PRIME = 5 /* Atheros Dynamic Turbo mode */, - MODE_ATHEROS_PRIMEG = 6 /* Atheros Dynamic Turbo mode G */, - MODE_ATHEROS_XR = 7 /* Atheros XR mode */, - NUM_IEEE80211_MODES = 8 -}; - -#define IEEE80211_CHAN_W_SCAN 0x00000001 -#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002 -#define IEEE80211_CHAN_W_IBSS 0x00000004 - -/* Low-level driver should set PREAMBLE2, OFDM, CCK, and TURBO flags. - * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the - * configuration. */ -#define IEEE80211_RATE_ERP 0x00000001 -#define IEEE80211_RATE_BASIC 0x00000002 -#define IEEE80211_RATE_PREAMBLE2 0x00000004 -#define IEEE80211_RATE_SUPPORTED 0x00000010 -#define IEEE80211_RATE_OFDM 0x00000020 -#define IEEE80211_RATE_CCK 0x00000040 -#define IEEE80211_RATE_TURBO 0x00000080 -#define IEEE80211_RATE_MANDATORY 0x00000100 -#define IEEE80211_RATE_XR 0x00000200 - -#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2) -#define IEEE80211_RATE_MODULATION(f) \ -(f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM)) - - -#endif /* IEEE80211_SHARED_H */ diff --git a/target/linux/package/ieee80211-dscape/src/michael.c b/target/linux/package/ieee80211-dscape/src/michael.c deleted file mode 100644 index 0f844f7895..0000000000 --- a/target/linux/package/ieee80211-dscape/src/michael.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Michael MIC implementation - optimized for TKIP MIC operations - * Copyright 2002-2003, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include - -#include "michael.h" - -static inline u32 rotr(u32 val, int bits) -{ - return (val >> bits) | (val << (32 - bits)); -} - - -static inline u32 rotl(u32 val, int bits) -{ - return (val << bits) | (val >> (32 - bits)); -} - - -static inline u32 xswap(u32 val) -{ - return ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); -} - - -#define michael_block(l, r) \ -do { \ - r ^= rotl(l, 17); \ - l += r; \ - r ^= xswap(l); \ - l += r; \ - r ^= rotl(l, 3); \ - l += r; \ - r ^= rotr(l, 2); \ - l += r; \ -} while (0) - - -static inline u32 michael_get32(u8 *data) -{ - return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); -} - - -static inline void michael_put32(u32 val, u8 *data) -{ - data[0] = val & 0xff; - data[1] = (val >> 8) & 0xff; - data[2] = (val >> 16) & 0xff; - data[3] = (val >> 24) & 0xff; -} - - -void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority, - u8 *data, size_t data_len, u8 *mic) -{ - u32 l, r, val; - size_t block, blocks, left; - - l = michael_get32(key); - r = michael_get32(key + 4); - - /* A pseudo header (DA, SA, Priority, 0, 0, 0) is used in Michael MIC - * calculation, but it is _not_ transmitted */ - l ^= michael_get32(da); - michael_block(l, r); - l ^= da[4] | (da[5] << 8) | (sa[0] << 16) | (sa[1] << 24); - michael_block(l, r); - l ^= michael_get32(&sa[2]); - michael_block(l, r); - l ^= priority; - michael_block(l, r); - - /* Real data */ - blocks = data_len / 4; - left = data_len % 4; - - for (block = 0; block < blocks; block++) { - l ^= michael_get32(&data[block * 4]); - michael_block(l, r); - } - - /* Partial block of 0..3 bytes and padding: 0x5a + 4..7 zeros to make - * total length a multiple of 4. */ - val = 0x5a; - while (left > 0) { - val <<= 8; - left--; - val |= data[blocks * 4 + left]; - } - l ^= val; - michael_block(l, r); - /* last block is zero, so l ^ 0 = l */ - michael_block(l, r); - - michael_put32(l, mic); - michael_put32(r, mic + 4); -} diff --git a/target/linux/package/ieee80211-dscape/src/michael.h b/target/linux/package/ieee80211-dscape/src/michael.h deleted file mode 100644 index 5acd8fd946..0000000000 --- a/target/linux/package/ieee80211-dscape/src/michael.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Michael MIC implementation - optimized for TKIP MIC operations - * Copyright 2002-2003, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef MICHAEL_H -#define MICHAEL_H - -#define MICHAEL_MIC_LEN 8 - -void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority, - u8 *data, size_t data_len, u8 *mic); - -#endif /* MICHAEL_H */ diff --git a/target/linux/package/ieee80211-dscape/src/rate_control.c b/target/linux/package/ieee80211-dscape/src/rate_control.c deleted file mode 100644 index 8782a756da..0000000000 --- a/target/linux/package/ieee80211-dscape/src/rate_control.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright 2002-2005, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "ieee80211_i.h" -#include "rate_control.h" - - -/* This is a minimal implementation of TX rate controlling that can be used - * as the default when no improved mechanisms are available. */ - - -#define RATE_CONTROL_EMERG_DEC 2 -#define RATE_CONTROL_INTERVAL (HZ / 20) -#define RATE_CONTROL_MIN_TX 10 - - -static void rate_control_rate_inc(struct ieee80211_local *local, - struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata; - int i = sta->txrate; - int maxrate; - - sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); - if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { - /* forced unicast rate - do not change STA rate */ - return; - } - - maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1; - - if (i > local->num_curr_rates) - i = local->num_curr_rates - 2; - - while (i + 1 < local->num_curr_rates) { - i++; - if (sta->supp_rates & BIT(i) && - local->curr_rates[i].flags & IEEE80211_RATE_SUPPORTED && - (maxrate < 0 || i <= maxrate)) { - sta->txrate = i; - break; - } - } -} - - -static void rate_control_rate_dec(struct ieee80211_local *local, - struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata; - int i = sta->txrate; - - sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); - if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { - /* forced unicast rate - do not change STA rate */ - return; - } - - if (i > local->num_curr_rates) - i = local->num_curr_rates; - - while (i > 0) { - i--; - if (sta->supp_rates & BIT(i) && - local->curr_rates[i].flags & IEEE80211_RATE_SUPPORTED) { - sta->txrate = i; - break; - } - } -} - - -static struct ieee80211_rate * -rate_control_lowest_rate(struct ieee80211_local *local) -{ - int i; - - for (i = 0; i < local->num_curr_rates; i++) { - struct ieee80211_rate *rate = &local->curr_rates[i]; - - if (rate->flags & IEEE80211_RATE_SUPPORTED - ) - return rate; - } - - printk(KERN_DEBUG "rate_control_lowest_rate - no supported rates " - "found\n"); - return &local->curr_rates[0]; -} - - -struct global_rate_control { - int dummy; -}; - -struct sta_rate_control { - unsigned long last_rate_change; - u32 tx_num_failures; - u32 tx_num_xmit; - - unsigned long avg_rate_update; - u32 tx_avg_rate_sum; - u32 tx_avg_rate_num; -}; - - -static void rate_control_simple_tx_status(struct net_device *dev, - struct sk_buff *skb, - struct ieee80211_tx_status *status) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct sta_info *sta; - struct sta_rate_control *srctrl; - - sta = sta_info_get(local, hdr->addr1); - - if (!sta) - return; - - srctrl = sta->rate_ctrl_priv; - srctrl->tx_num_xmit++; - if (status->excessive_retries) { - sta->antenna_sel = sta->antenna_sel == 1 ? 2 : 1; - if (local->sta_antenna_sel == STA_ANTENNA_SEL_SW_CTRL_DEBUG) { - printk(KERN_DEBUG "%s: " MACSTR " TX antenna --> %d " - "(@%lu)\n", - dev->name, MAC2STR(hdr->addr1), - sta->antenna_sel, jiffies); - } - srctrl->tx_num_failures++; - sta->tx_retry_failed++; - sta->tx_num_consecutive_failures++; - sta->tx_num_mpdu_fail++; - } else { - sta->last_ack_rssi[0] = sta->last_ack_rssi[1]; - sta->last_ack_rssi[1] = sta->last_ack_rssi[2]; - sta->last_ack_rssi[2] = status->ack_signal; - sta->tx_num_consecutive_failures = 0; - sta->tx_num_mpdu_ok++; - } - sta->tx_retry_count += status->retry_count; - sta->tx_num_mpdu_fail += status->retry_count; - - if (time_after(jiffies, - srctrl->last_rate_change + RATE_CONTROL_INTERVAL) && - srctrl->tx_num_xmit > RATE_CONTROL_MIN_TX) { - u32 per_failed; - srctrl->last_rate_change = jiffies; - - per_failed = (100 * sta->tx_num_mpdu_fail) / - (sta->tx_num_mpdu_fail + sta->tx_num_mpdu_ok); - /* TODO: calculate average per_failed to make adjusting - * parameters easier */ -#if 0 - if (net_ratelimit()) { - printk(KERN_DEBUG "MPDU fail=%d ok=%d per_failed=%d\n", - sta->tx_num_mpdu_fail, sta->tx_num_mpdu_ok, - per_failed); - } -#endif - - if (per_failed > local->rate_ctrl_num_down) { - rate_control_rate_dec(local, sta); - } else if (per_failed < local->rate_ctrl_num_up) { - rate_control_rate_inc(local, sta); - } - srctrl->tx_avg_rate_sum += local->curr_rates[sta->txrate].rate; - srctrl->tx_avg_rate_num++; - srctrl->tx_num_failures = 0; - srctrl->tx_num_xmit = 0; - } else if (sta->tx_num_consecutive_failures >= - RATE_CONTROL_EMERG_DEC) { - rate_control_rate_dec(local, sta); - } - - if (srctrl->avg_rate_update + 60 * HZ < jiffies) { - srctrl->avg_rate_update = jiffies; - if (srctrl->tx_avg_rate_num > 0) { -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: STA " MACSTR " Average rate: " - "%d (%d/%d)\n", - dev->name, MAC2STR(sta->addr), - srctrl->tx_avg_rate_sum / - srctrl->tx_avg_rate_num, - srctrl->tx_avg_rate_sum, - srctrl->tx_avg_rate_num); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - srctrl->tx_avg_rate_sum = 0; - srctrl->tx_avg_rate_num = 0; - } - } - - sta_info_release(local, sta); -} - - -static struct ieee80211_rate * -rate_control_simple_get_rate(struct net_device *dev, struct sk_buff *skb, - struct rate_control_extra *extra) -{ - struct ieee80211_local *local = dev->priv; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct sta_info *sta; - int rateidx, nonerp_idx; - u16 fc; - - memset(extra, 0, sizeof(*extra)); - - fc = le16_to_cpu(hdr->frame_control); - if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_DATA || - (hdr->addr1[0] & 0x01)) { - /* Send management frames and broadcast/multicast data using - * lowest rate. */ - /* TODO: this could probably be improved.. */ - return rate_control_lowest_rate(local); - } - - sta = sta_info_get(local, hdr->addr1); - - if (!sta) - return rate_control_lowest_rate(local); - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) - sta->txrate = sdata->bss->force_unicast_rateidx; - - rateidx = sta->txrate; - - if (rateidx >= local->num_curr_rates) - rateidx = local->num_curr_rates - 1; - - sta->last_txrate = rateidx; - nonerp_idx = rateidx; - while (nonerp_idx > 0 && - ((local->curr_rates[nonerp_idx].flags & IEEE80211_RATE_ERP) || - !(local->curr_rates[nonerp_idx].flags & - IEEE80211_RATE_SUPPORTED) || - !(sta->supp_rates & BIT(nonerp_idx)))) - nonerp_idx--; - extra->nonerp_idx = nonerp_idx; - extra->nonerp = &local->curr_rates[extra->nonerp_idx]; - - sta_info_release(local, sta); - - return &local->curr_rates[rateidx]; -} - - -static void rate_control_simple_rate_init(struct ieee80211_local *local, - struct sta_info *sta) -{ - int i; - sta->txrate = 0; - /* TODO: what is a good starting rate for STA? About middle? Maybe not - * the lowest or the highest rate.. Could consider using RSSI from - * previous packets? Need to have IEEE 802.1X auth succeed immediately - * after assoc.. */ - for (i = 0; i < local->num_curr_rates; i++) { - if ((sta->supp_rates & BIT(i)) && - (local->curr_rates[i].flags & IEEE80211_RATE_SUPPORTED)) - sta->txrate = i; - } -} - - -static void * rate_control_simple_alloc(struct ieee80211_local *local) -{ - struct global_rate_control *rctrl; - - rctrl = kmalloc(sizeof(*rctrl), GFP_ATOMIC); - if (rctrl == NULL) { - return NULL; - } - memset(rctrl, 0, sizeof(*rctrl)); - return rctrl; -} - - -static void rate_control_simple_free(void *priv) -{ - struct global_rate_control *rctrl = priv; - kfree(rctrl); -} - - -static void rate_control_simple_clear(void *priv) -{ -} - - -static void * rate_control_simple_alloc_sta(void) -{ - struct sta_rate_control *rctrl; - - rctrl = kmalloc(sizeof(*rctrl), GFP_ATOMIC); - if (rctrl == NULL) { - return NULL; - } - memset(rctrl, 0, sizeof(*rctrl)); - return rctrl; -} - - -static void rate_control_simple_free_sta(void *priv) -{ - struct sta_rate_control *rctrl = priv; - kfree(rctrl); -} - - -static int rate_control_simple_status_sta(struct ieee80211_local *local, - struct sta_info *sta, char *buf) -{ - char *p = buf; - struct sta_rate_control *srctrl = sta->rate_ctrl_priv; - - p += sprintf(p, "tx_avg_rate_sum=%d\n", srctrl->tx_avg_rate_sum); - p += sprintf(p, "tx_avg_rate_num=%d\n", srctrl->tx_avg_rate_num); - if (srctrl->tx_avg_rate_num) - p += sprintf(p, "tx_avg_rate_avg=%d\n", - srctrl->tx_avg_rate_sum / - srctrl->tx_avg_rate_num); - return p - buf; -} - - -static int rate_control_simple_status_global(struct ieee80211_local *local, - char *buf) -{ - return 0; -} - - -static struct rate_control_ops rate_control_simple = { - .name = "simple", - .tx_status = rate_control_simple_tx_status, - .get_rate = rate_control_simple_get_rate, - .rate_init = rate_control_simple_rate_init, - .clear = rate_control_simple_clear, - .status_sta = rate_control_simple_status_sta, - .status_global = rate_control_simple_status_global, - .alloc = rate_control_simple_alloc, - .free = rate_control_simple_free, - .alloc_sta = rate_control_simple_alloc_sta, - .free_sta = rate_control_simple_free_sta, -}; - - -int __init rate_control_simple_init(void) -{ - return ieee80211_rate_control_register(&rate_control_simple); -} - - -static void __exit rate_control_simple_exit(void) -{ - ieee80211_rate_control_unregister(&rate_control_simple); -} - - -module_init(rate_control_simple_init); -module_exit(rate_control_simple_exit); diff --git a/target/linux/package/ieee80211-dscape/src/rate_control.h b/target/linux/package/ieee80211-dscape/src/rate_control.h deleted file mode 100644 index 9ceea7da57..0000000000 --- a/target/linux/package/ieee80211-dscape/src/rate_control.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2002-2005, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RATE_CONTROL -#define RATE_CONTROL - -#define RATE_CONTROL_NUM_DOWN 20 -#define RATE_CONTROL_NUM_UP 15 - - -struct rate_control_extra { - /* values from rate_control_get_rate() to the caller: */ - struct ieee80211_rate *probe; /* probe with this rate, or NULL for no - * probing */ - int startidx, endidx, rateidx; - struct ieee80211_rate *nonerp; - int nonerp_idx; - - /* parameters from the caller to rate_control_get_rate(): */ - int mgmt_data; /* this is data frame that is used for management - * (e.g., IEEE 802.1X EAPOL) */ - u16 ethertype; -}; - - -struct rate_control_ops { - const char *name; - void (*tx_status)(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_tx_status *status); - struct ieee80211_rate * - (*get_rate)(struct net_device *dev, struct sk_buff *skb, - struct rate_control_extra *extra); - void (*rate_init)(struct ieee80211_local *local, struct sta_info *sta); - void (*clear)(void *priv); - int (*status_sta)(struct ieee80211_local *local, - struct sta_info *sta, char *buf); - int (*status_global)(struct ieee80211_local *local, char *buf); - - void * (*alloc)(struct ieee80211_local *local); - void (*free)(void *priv); - void * (*alloc_sta)(void); - void (*free_sta)(void *priv); -}; - - -int ieee80211_rate_control_register(struct rate_control_ops *ops); -void ieee80211_rate_control_unregister(struct rate_control_ops *ops); - - -static inline void rate_control_tx_status(struct net_device *dev, - struct sk_buff *skb, - struct ieee80211_tx_status *status) -{ - struct ieee80211_local *local = dev->priv; - local->rate_ctrl->tx_status(dev, skb, status); -} - - -static inline struct ieee80211_rate * -rate_control_get_rate(struct net_device *dev, struct sk_buff *skb, - struct rate_control_extra *extra) -{ - struct ieee80211_local *local = dev->priv; - return local->rate_ctrl->get_rate(dev, skb, extra); -} - - -static inline void rate_control_rate_init(struct ieee80211_local *local, - struct sta_info *sta) -{ - local->rate_ctrl->rate_init(local, sta); -} - - -static inline void rate_control_clear(struct ieee80211_local *local) -{ - local->rate_ctrl->clear(local->rate_ctrl_priv); -} - - -static inline int rate_control_status_sta(struct ieee80211_local *local, - struct sta_info *sta, char *buf) -{ - return local->rate_ctrl->status_sta(local, sta, buf); -} - - -static inline int rate_control_status_global(struct ieee80211_local *local, - char *buf) -{ - return local->rate_ctrl->status_global(local, buf); -} - - -static inline void * rate_control_alloc(struct ieee80211_local *local) -{ - return local->rate_ctrl->alloc(local); -} - - -static inline void rate_control_free(struct ieee80211_local *local) -{ - if (local->rate_ctrl == NULL || local->rate_ctrl_priv == NULL) - return; - local->rate_ctrl->free(local->rate_ctrl_priv); - local->rate_ctrl_priv = NULL; -} - - -static inline void * rate_control_alloc_sta(struct ieee80211_local *local) -{ - return local->rate_ctrl->alloc_sta(); -} - - -static inline void rate_control_free_sta(struct ieee80211_local *local, - void *priv) -{ - local->rate_ctrl->free_sta(priv); -} - -#endif /* RATE_CONTROL */ diff --git a/target/linux/package/ieee80211-dscape/src/sta_info.c b/target/linux/package/ieee80211-dscape/src/sta_info.c deleted file mode 100644 index 4bb9f74ba0..0000000000 --- a/target/linux/package/ieee80211-dscape/src/sta_info.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright 2002-2005, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "ieee80211_i.h" -#include "ieee80211_proc.h" -#include "rate_control.h" - - -/* Caller must hold local->sta_lock */ -static void sta_info_hash_add(struct ieee80211_local *local, - struct sta_info *sta) -{ - sta->hnext = local->sta_hash[STA_HASH(sta->addr)]; - local->sta_hash[STA_HASH(sta->addr)] = sta; -} - - -/* Caller must hold local->sta_lock */ -static void sta_info_hash_del(struct ieee80211_local *local, - struct sta_info *sta) -{ - struct sta_info *s; - - s = local->sta_hash[STA_HASH(sta->addr)]; - if (s == NULL) - return; - if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) { - local->sta_hash[STA_HASH(sta->addr)] = s->hnext; - return; - } - - while (s->hnext != NULL && - memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0) - s = s->hnext; - if (s->hnext != NULL) - s->hnext = s->hnext->hnext; - else - printk(KERN_ERR "%s: could not remove STA " MACSTR " from " - "hash table\n", local->mdev->name, MAC2STR(sta->addr)); -} - - -struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr) -{ - struct sta_info *sta; - - spin_lock_bh(&local->sta_lock); - sta = local->sta_hash[STA_HASH(addr)]; - while (sta) { - if (memcmp(sta->addr, addr, ETH_ALEN) == 0) { - atomic_inc(&sta->users); - break; - } - sta = sta->hnext; - } - spin_unlock_bh(&local->sta_lock); - - return sta; -} - - -int sta_info_min_txrate_get(struct ieee80211_local *local) -{ - struct sta_info *sta; - int min_txrate = 9999999; - int i; - - spin_lock_bh(&local->sta_lock); - for (i = 0; i < STA_HASH_SIZE; i++) { - sta = local->sta_hash[i]; - while (sta) { - if (sta->txrate < min_txrate) - min_txrate = sta->txrate; - sta = sta->hnext; - } - } - spin_unlock_bh(&local->sta_lock); - if (min_txrate == 9999999) - min_txrate = 0; - - return min_txrate; -} - - -void sta_info_release(struct ieee80211_local *local, struct sta_info *sta) -{ - struct sk_buff *skb; - - if (!atomic_dec_and_test(&sta->users)) - return; - - /* free sta structure; it has already been removed from - * hash table etc. external structures. Make sure that all - * buffered frames are release (one might have been added - * after sta_info_free() was called). */ - while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { - local->total_ps_buffered--; - dev_kfree_skb_any(skb); - } - while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { - dev_kfree_skb_any(skb); - } - rate_control_free_sta(local, sta->rate_ctrl_priv); - kfree(sta); -} - - -struct sta_info * sta_info_add(struct ieee80211_local *local, - struct net_device *dev, u8 *addr) -{ - struct sta_info *sta; - - sta = kmalloc(sizeof(*sta), GFP_ATOMIC); - if (!sta) - return NULL; - - memset(sta, 0, sizeof(*sta)); - - sta->rate_ctrl_priv = rate_control_alloc_sta(local); - if (sta->rate_ctrl_priv == NULL) { - kfree(sta); - return NULL; - } - - memcpy(sta->addr, addr, ETH_ALEN); - sta->dev = dev; - skb_queue_head_init(&sta->ps_tx_buf); - skb_queue_head_init(&sta->tx_filtered); - atomic_inc(&sta->users); /* sta in hashlist etc, decremented by - * sta_info_free() */ - atomic_inc(&sta->users); /* sta used by caller, decremented by - * sta_info_release() */ - spin_lock_bh(&local->sta_lock); - list_add(&sta->list, &local->sta_list); - local->num_sta++; - sta_info_hash_add(local, sta); - spin_unlock_bh(&local->sta_lock); - if (local->hw->sta_table_notification) - local->hw->sta_table_notification(local->mdev, local->num_sta); - sta->key_idx_compression = HW_KEY_IDX_INVALID; - -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Added STA " MACSTR "\n", - dev->name, MAC2STR(addr)); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - - if (!in_interrupt()) { - ieee80211_proc_init_sta(local, sta); - } else { - /* procfs entry adding might sleep, so schedule process context - * task for adding proc entry for STAs that do not yet have - * one. */ - schedule_work(&local->sta_proc_add); - } - - return sta; -} - - -void sta_info_free(struct ieee80211_local *local, struct sta_info *sta, - int locked) -{ - struct sk_buff *skb; - struct ieee80211_sub_if_data *sdata; - - if (!locked) - spin_lock_bh(&local->sta_lock); - sta_info_hash_del(local, sta); - list_del(&sta->list); - sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); - if (sta->flags & WLAN_STA_PS) { - sta->flags &= ~WLAN_STA_PS; - if (sdata->bss) - atomic_dec(&sdata->bss->num_sta_ps); - } - local->num_sta--; - sta_info_remove_aid_ptr(sta); - if (!locked) - spin_unlock_bh(&local->sta_lock); - if (local->hw->sta_table_notification) - local->hw->sta_table_notification(local->mdev, local->num_sta); - - while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { - local->total_ps_buffered--; - dev_kfree_skb_any(skb); - } - while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { - dev_kfree_skb_any(skb); - } - - if (sta->key) { - if (local->hw->set_key) { - struct ieee80211_key_conf *key; - key = ieee80211_key_data2conf(local, sta->key); - if (key) { - local->hw->set_key(local->mdev, DISABLE_KEY, - sta->addr, key, sta->aid); - kfree(key); - } - } - kfree(sta->key); - sta->key = NULL; - } else if (sta->key_idx_compression != HW_KEY_IDX_INVALID) { - struct ieee80211_key_conf conf; - memset(&conf, 0, sizeof(conf)); - conf.hw_key_idx = sta->key_idx_compression; - conf.alg = ALG_NULL; - conf.force_sw_encrypt = 1; - local->hw->set_key(local->mdev, DISABLE_KEY, sta->addr, &conf, - sta->aid); - sta->key_idx_compression = HW_KEY_IDX_INVALID; - } - -#ifdef CONFIG_IEEE80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Removed STA " MACSTR "\n", - local->mdev->name, MAC2STR(sta->addr)); -#endif /* CONFIG_IEEE80211_VERBOSE_DEBUG */ - - ieee80211_proc_deinit_sta(local, sta); - - if (atomic_read(&sta->users) != 1) { - /* This is OK, but printed for debugging. The station structure - * will be removed when the other user of the data calls - * sta_info_release(). */ - printk(KERN_DEBUG "%s: STA " MACSTR " users count %d when " - "removing it\n", local->mdev->name, MAC2STR(sta->addr), - atomic_read(&sta->users)); - } - - sta_info_release(local, sta); -} - - -static inline int sta_info_buffer_expired(struct sk_buff *skb) -{ - struct ieee80211_tx_packet_data *pkt_data; - if (!skb) - return 0; - - /* TODO: this could be improved by passing STA listen interval into - * the kernel driver and expiring frames after 2 x listen_interval x - * beacon interval */ - - pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; - - if (pkt_data->magic != IEEE80211_CB_MAGIC) - return 1; - - return time_after(jiffies, pkt_data->jiffies + STA_TX_BUFFER_EXPIRE); -} - - -static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, - struct sta_info *sta) -{ - unsigned long flags; - struct sk_buff *skb; - - if (skb_queue_empty(&sta->ps_tx_buf)) - return; - - for (;;) { - spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); - skb = skb_peek(&sta->ps_tx_buf); - if (sta_info_buffer_expired(skb)) - skb = __skb_dequeue(&sta->ps_tx_buf); - else - skb = NULL; - spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags); - - if (skb) { - local->total_ps_buffered--; - printk(KERN_DEBUG "Buffered frame expired (STA " - MACSTR ")\n", MAC2STR(sta->addr)); - dev_kfree_skb(skb); - } else - break; - } -} - - -static void sta_info_cleanup(unsigned long data) -{ - struct ieee80211_local *local = (struct ieee80211_local *) data; - struct list_head *ptr; - - spin_lock_bh(&local->sta_lock); - ptr = local->sta_list.next; - while (ptr && ptr != &local->sta_list) { - struct sta_info *sta = (struct sta_info *) ptr; - atomic_inc(&sta->users); - sta_info_cleanup_expire_buffered(local, sta); - sta_info_release(local, sta); - ptr = ptr->next; - } - spin_unlock_bh(&local->sta_lock); - - local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL; - add_timer(&local->sta_cleanup); -} - - -static void sta_info_proc_add_task(void *data) -{ - struct ieee80211_local *local = data; - struct list_head *ptr; - struct sta_info *sta; - int max_adds = 100; - - while (max_adds > 0) { - sta = NULL; - spin_lock_bh(&local->sta_lock); - list_for_each(ptr, &local->sta_list) { - sta = list_entry(ptr, struct sta_info, list); - if (!sta->proc_entry_added) { - atomic_inc(&sta->users); - break; - } - sta = NULL; - } - spin_unlock_bh(&local->sta_lock); - - if (!sta) - break; - - ieee80211_proc_init_sta(local, sta); - atomic_dec(&sta->users); - - max_adds--; - } -} - - -void sta_info_init(struct ieee80211_local *local) -{ - spin_lock_init(&local->sta_lock); - INIT_LIST_HEAD(&local->sta_list); - - init_timer(&local->sta_cleanup); - local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL; - local->sta_cleanup.data = (unsigned long) local; - local->sta_cleanup.function = sta_info_cleanup; - - INIT_WORK(&local->sta_proc_add, sta_info_proc_add_task, local); -} - -void sta_info_start(struct ieee80211_local *local) -{ - add_timer(&local->sta_cleanup); -} - -void sta_info_stop(struct ieee80211_local *local) -{ - struct list_head *ptr; - - del_timer(&local->sta_cleanup); - - ptr = local->sta_list.next; - while (ptr && ptr != &local->sta_list) { - struct sta_info *sta = (struct sta_info *) ptr; - ptr = ptr->next; - sta_info_free(local, sta, 0); - } -} - - -void sta_info_remove_aid_ptr(struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); - if (sta->aid <= 0 || !sdata->bss) - return; - - sdata->bss->sta_aid[sta->aid - 1] = NULL; - if (sta->aid == sdata->bss->max_aid) { - while (sdata->bss->max_aid > 0 && - sdata->bss->sta_aid[sdata->bss->max_aid - 1] == NULL) - sdata->bss->max_aid--; - } -} - - -/** - * sta_info_flush - flush matching STA entries from the STA table - * @local: local interface data - * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs - */ -void sta_info_flush(struct ieee80211_local *local, struct net_device *dev) -{ - struct list_head *ptr, *n; - - spin_lock_bh(&local->sta_lock); - - list_for_each_safe(ptr, n, &local->sta_list) { - struct sta_info *sta = list_entry(ptr, struct sta_info, list); - if (dev == NULL || dev == sta->dev) - sta_info_free(local, sta, 1); - } - spin_unlock_bh(&local->sta_lock); -} diff --git a/target/linux/package/ieee80211-dscape/src/sta_info.h b/target/linux/package/ieee80211-dscape/src/sta_info.h deleted file mode 100644 index ef6906d56d..0000000000 --- a/target/linux/package/ieee80211-dscape/src/sta_info.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2002-2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef STA_INFO_H -#define STA_INFO_H - -/* Stations flags (struct sta_info::flags) */ -#define WLAN_STA_AUTH BIT(0) -#define WLAN_STA_ASSOC BIT(1) -#define WLAN_STA_PS BIT(2) -#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */ -#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */ -#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is - * controlling whether STA is authorized to - * send and receive non-IEEE 802.1X frames - */ -#define WLAN_STA_SHORT_PREAMBLE BIT(7) -#define WLAN_STA_WME BIT(9) -#define WLAN_STA_XR BIT(26) -#define WLAN_STA_WDS BIT(27) - - -struct sta_info { - struct list_head list; - struct sta_info *hnext; /* next entry in hash table list */ - atomic_t users; /* number of users (do not remove if > 0) */ - - u8 addr[ETH_ALEN]; - u16 aid; /* STA's unique AID (1..2007), 0 = not yet assigned */ - u32 flags; /* WLAN_STA_ */ - - struct sk_buff_head ps_tx_buf; /* buffer of TX frames for station in - * power saving state */ - int pspoll; /* whether STA has send a PS Poll frame */ - struct sk_buff_head tx_filtered; /* buffer of TX frames that were - * already given to low-level driver, - * but were filtered */ - int clear_dst_mask; - - unsigned long rx_packets, tx_packets; /* number of RX/TX MSDUs */ - unsigned long rx_bytes, tx_bytes; - unsigned long tx_retry_failed, tx_retry_count; - unsigned long tx_filtered_count; - - unsigned int wep_weak_iv_count; /* number of RX frames with weak IV */ - - unsigned long last_rx; - u32 supp_rates; /* bitmap of supported rates in local->curr_rates */ - int txrate; /* index in local->curr_rates */ - int last_txrate; /* last rate used to send a frame to this STA */ - int last_nonerp_idx; - - struct net_device *dev; /* which net device is this station associated - * to */ - - struct ieee80211_key *key; - - u32 tx_num_consecutive_failures; - u32 tx_num_mpdu_ok; - u32 tx_num_mpdu_fail; - - void *rate_ctrl_priv; - - /* last received seq/frag number from this STA (per RX queue) */ - u16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; - unsigned long num_duplicates; /* number of duplicate frames received - * from this STA */ - unsigned long tx_fragments; /* number of transmitted MPDUs */ - unsigned long rx_fragments; /* number of received MPDUs */ - unsigned long rx_dropped; /* number of dropped MPDUs from this STA */ - - int last_rssi; /* RSSI of last received frame from this STA */ - int last_ack_rssi[3]; /* RSSI of last received ACKs from this STA */ - unsigned long last_ack; - int channel_use; - int channel_use_raw; - - int antenna_sel; - - - int key_idx_compression; /* key table index for compression and TX - * filtering; used only if sta->key is not - * set */ - - int proc_entry_added:1; - int assoc_ap:1; /* whether this is an AP that we are associated with - * as a client */ - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - u32 wpa_trigger; -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - -#ifdef CONFIG_IEEE80211_DEBUG_COUNTERS - unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; - unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; -#endif /* CONFIG_IEEE80211_DEBUG_COUNTERS */ - - int vlan_id; -}; - - -/* Maximum number of concurrently registered stations */ -#define MAX_STA_COUNT 2007 - -/* Maximum number of AIDs to use for STAs; must be 2007 or lower - * (IEEE 802.11 beacon format limitation) */ -#define MAX_AID_TABLE_SIZE 2007 - -#define STA_HASH_SIZE 256 -#define STA_HASH(sta) (sta[5]) - - -/* Maximum number of frames to buffer per power saving station */ -#define STA_MAX_TX_BUFFER 128 - -/* Buffered frame expiry time */ -#define STA_TX_BUFFER_EXPIRE (10 * HZ) - -/* How often station data is cleaned up (e.g., expiration of buffered frames) - */ -#define STA_INFO_CLEANUP_INTERVAL (10 * HZ) - - -struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr); -int sta_info_min_txrate_get(struct ieee80211_local *local); -void sta_info_release(struct ieee80211_local *local, struct sta_info *sta); -struct sta_info * sta_info_add(struct ieee80211_local *local, - struct net_device *dev, u8 *addr); -void sta_info_free(struct ieee80211_local *local, struct sta_info *sta, - int locked); -void sta_info_init(struct ieee80211_local *local); -void sta_info_start(struct ieee80211_local *local); -void sta_info_stop(struct ieee80211_local *local); -void sta_info_remove_aid_ptr(struct sta_info *sta); -void sta_info_flush(struct ieee80211_local *local, struct net_device *dev); - -#endif /* STA_INFO_H */ diff --git a/target/linux/package/ieee80211-dscape/src/tkip.c b/target/linux/package/ieee80211-dscape/src/tkip.c deleted file mode 100644 index 41e0b8ea05..0000000000 --- a/target/linux/package/ieee80211-dscape/src/tkip.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright 2002-2004, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifdef CONFIG_TKIP_DEBUG -#include -#include -#include -#include -#include -#endif /* CONFIG_TKIP_DEBUG */ - -#include -#include - -#include -#include "ieee80211_key.h" -#ifdef CONFIG_TKIP_DEBUG -#include "ieee80211_i.h" -#endif /* CONFIG_TKIP_DEBUG */ -#include "tkip.h" - -/* Dummy prototypes for structures used in wep.h, but not really needed for - * TKIP. */ -struct ieee80211_local; -struct sk_buff; -#include "wep.h" - - -/* TKIP key mixing functions */ - - -#define PHASE1_LOOP_COUNT 8 - - -/* 2-byte by 2-byte subset of the full AES S-box table; second part of this - * table is identical to first part but byte-swapped */ -static const u16 tkip_sbox[256] = -{ - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, -}; - - -static inline u16 Mk16(u8 x, u8 y) -{ - return ((u16) x << 8) | (u16) y; -} - - -static inline u8 Hi8(u16 v) -{ - return v >> 8; -} - - -static inline u8 Lo8(u16 v) -{ - return v & 0xff; -} - - -static inline u16 Hi16(u32 v) -{ - return v >> 16; -} - - -static inline u16 Lo16(u32 v) -{ - return v & 0xffff; -} - - -static inline u16 RotR1(u16 v) -{ - return (v >> 1) | ((v & 0x0001) << 15); -} - - -static inline u16 tkip_S(u16 val) -{ - u16 a = tkip_sbox[Hi8(val)]; - - return tkip_sbox[Lo8(val)] ^ Hi8(a) ^ (Lo8(a) << 8); -} - - - -/* P1K := Phase1(TA, TK, TSC) - * TA = transmitter address (48 bits) - * TK = dot11DefaultKeyValue or dot11KeyMappingValue (128 bits) - * TSC = TKIP sequence counter (48 bits, only 32 msb bits used) - * P1K: 80 bits - */ -static void tkip_mixing_phase1(const u8 *ta, const u8 *tk, u32 tsc_IV32, - u16 *p1k) -{ - int i, j; - - p1k[0] = Lo16(tsc_IV32); - p1k[1] = Hi16(tsc_IV32); - p1k[2] = Mk16(ta[1], ta[0]); - p1k[3] = Mk16(ta[3], ta[2]); - p1k[4] = Mk16(ta[5], ta[4]); - - for (i = 0; i < PHASE1_LOOP_COUNT; i++) { - j = 2 * (i & 1); - p1k[0] += tkip_S(p1k[4] ^ Mk16(tk[ 1 + j], tk[ 0 + j])); - p1k[1] += tkip_S(p1k[0] ^ Mk16(tk[ 5 + j], tk[ 4 + j])); - p1k[2] += tkip_S(p1k[1] ^ Mk16(tk[ 9 + j], tk[ 8 + j])); - p1k[3] += tkip_S(p1k[2] ^ Mk16(tk[13 + j], tk[12 + j])); - p1k[4] += tkip_S(p1k[3] ^ Mk16(tk[ 1 + j], tk[ 0 + j])) + i; - } -} - - -static void tkip_mixing_phase2(const u16 *p1k, const u8 *tk, u16 tsc_IV16, - u8 *rc4key) -{ - u16 ppk[6]; - int i; - - ppk[0] = p1k[0]; - ppk[1] = p1k[1]; - ppk[2] = p1k[2]; - ppk[3] = p1k[3]; - ppk[4] = p1k[4]; - ppk[5] = p1k[4] + tsc_IV16; - - ppk[0] += tkip_S(ppk[5] ^ Mk16(tk[ 1], tk[ 0])); - ppk[1] += tkip_S(ppk[0] ^ Mk16(tk[ 3], tk[ 2])); - ppk[2] += tkip_S(ppk[1] ^ Mk16(tk[ 5], tk[ 4])); - ppk[3] += tkip_S(ppk[2] ^ Mk16(tk[ 7], tk[ 6])); - ppk[4] += tkip_S(ppk[3] ^ Mk16(tk[ 9], tk[ 8])); - ppk[5] += tkip_S(ppk[4] ^ Mk16(tk[11], tk[10])); - ppk[0] += RotR1(ppk[5] ^ Mk16(tk[13], tk[12])); - ppk[1] += RotR1(ppk[0] ^ Mk16(tk[15], tk[14])); - ppk[2] += RotR1(ppk[1]); - ppk[3] += RotR1(ppk[2]); - ppk[4] += RotR1(ppk[3]); - ppk[5] += RotR1(ppk[4]); - - rc4key[0] = Hi8(tsc_IV16); - rc4key[1] = (Hi8(tsc_IV16) | 0x20) & 0x7f; - rc4key[2] = Lo8(tsc_IV16); - rc4key[3] = Lo8((ppk[5] ^ Mk16(tk[1], tk[0])) >> 1); - - for (i = 0; i < 6; i++) { - rc4key[4 + 2 * i] = Lo8(ppk[i]); - rc4key[5 + 2 * i] = Hi8(ppk[i]); - } -} - - -/* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets - * of the IV. Returns pointer to the octet following IVs (i.e., beginning of - * the packet payload). */ -u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, - u8 iv0, u8 iv1, u8 iv2) -{ - *pos++ = iv0; - *pos++ = iv1; - *pos++ = iv2; - *pos++ = (key->keyidx << 6) | (1 << 5) /* Ext IV */; - *pos++ = key->u.tkip.iv32 & 0xff; - *pos++ = (key->u.tkip.iv32 >> 8) & 0xff; - *pos++ = (key->u.tkip.iv32 >> 16) & 0xff; - *pos++ = (key->u.tkip.iv32 >> 24) & 0xff; - return pos; -} - - -/* Encrypt packet payload with TKIP using @key. @pos is a pointer to the - * beginning of the buffer containing payload. This payload must include - * headroom of eight octets for IV and Ext. IV and taildroom of four octets - * for ICV. @payload_len is the length of payload (_not_ including extra - * headroom and tailroom). @ta is the transmitter addresses. */ -void ieee80211_tkip_encrypt_data(struct ieee80211_key *key, u8 *pos, - size_t payload_len, u8 *ta) -{ - u8 rc4key[16]; - - /* Calculate per-packet key */ - if (key->u.tkip.iv16 == 0 || !key->u.tkip.tx_initialized) { - /* IV16 wrapped around - perform TKIP phase 1 */ - tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY], - key->u.tkip.iv32, key->u.tkip.p1k); - key->u.tkip.tx_initialized = 1; - } - - tkip_mixing_phase2(key->u.tkip.p1k, &key->key[ALG_TKIP_TEMP_ENCR_KEY], - key->u.tkip.iv16, rc4key); - - pos = ieee80211_tkip_add_iv(pos, key, rc4key[0], rc4key[1], rc4key[2]); - ieee80211_wep_encrypt_data(rc4key, 16, pos, payload_len); -} - - -/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the - * beginning of the buffer containing IEEE 802.11 header payload, i.e., - * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the - * length of payload, including IV, Ext. IV, MIC, ICV. */ -int ieee80211_tkip_decrypt_data(struct ieee80211_key *key, u8 *payload, - size_t payload_len, u8 *ta, int only_iv, - int queue) -{ - u32 iv32; - u32 iv16; - u8 rc4key[16], keyid, *pos = payload; - int res; - - if (payload_len < 12) - return -1; - - iv16 = (pos[0] << 8) | pos[2]; - keyid = pos[3]; - iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); - pos += 8; -#ifdef CONFIG_TKIP_DEBUG - { - int i; - printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len); - for (i = 0; i < payload_len; i++) - printk(" %02x", payload[i]); - printk("\n"); - printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n", - iv16, iv32); - } -#endif /* CONFIG_TKIP_DEBUG */ - - if (!(keyid & (1 << 5))) - return TKIP_DECRYPT_NO_EXT_IV; - - if ((keyid >> 6) != key->keyidx) - return TKIP_DECRYPT_INVALID_KEYIDX; - - if (key->u.tkip.rx_initialized[queue] && - (iv32 < key->u.tkip.iv32_rx[queue] || - (iv32 == key->u.tkip.iv32_rx[queue] && - iv16 <= key->u.tkip.iv16_rx[queue]))) { -#ifdef CONFIG_TKIP_DEBUG - printk(KERN_DEBUG "TKIP replay detected for RX frame from " - MACSTR " (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", - MAC2STR(ta), - iv32, iv16, key->u.tkip.iv32_rx[queue], - key->u.tkip.iv16_rx[queue]); -#endif /* CONFIG_TKIP_DEBUG */ - return TKIP_DECRYPT_REPLAY; - } - - if (only_iv) { - res = TKIP_DECRYPT_OK; - goto done; - } - - if (!key->u.tkip.rx_initialized[queue] || - key->u.tkip.iv32_rx[queue] != iv32) { - key->u.tkip.rx_initialized[queue] = 1; - /* IV16 wrapped around - perform TKIP phase 1 */ - tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY], - iv32, key->u.tkip.p1k_rx[queue]); -#ifdef CONFIG_TKIP_DEBUG - { - int i; - printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=" MACSTR - " TK=", MAC2STR(ta)); - for (i = 0; i < 16; i++) - printk("%02x ", - key->key[ALG_TKIP_TEMP_ENCR_KEY + i]); - printk("\n"); - printk(KERN_DEBUG "TKIP decrypt: P1K="); - for (i = 0; i < 5; i++) - printk("%04x ", key->u.tkip.p1k_rx[queue][i]); - printk("\n"); - } -#endif /* CONFIG_TKIP_DEBUG */ - } - - tkip_mixing_phase2(key->u.tkip.p1k_rx[queue], - &key->key[ALG_TKIP_TEMP_ENCR_KEY], - iv16, rc4key); -#ifdef CONFIG_TKIP_DEBUG - { - int i; - printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key="); - for (i = 0; i < 16; i++) - printk("%02x ", rc4key[i]); - printk("\n"); - } -#endif /* CONFIG_TKIP_DEBUG */ - - res = ieee80211_wep_decrypt_data(rc4key, 16, pos, payload_len - 12); - done: - if (res == TKIP_DECRYPT_OK) { - /* FIX: these should be updated only after Michael MIC has been - * verified */ - /* Record previously received IV */ - key->u.tkip.iv32_rx[queue] = iv32; - key->u.tkip.iv16_rx[queue] = iv16; - } - - return res; -} - - diff --git a/target/linux/package/ieee80211-dscape/src/tkip.h b/target/linux/package/ieee80211-dscape/src/tkip.h deleted file mode 100644 index 6c4ab7f698..0000000000 --- a/target/linux/package/ieee80211-dscape/src/tkip.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2002-2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef TKIP_H -#define TKIP_H - -u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, - u8 iv0, u8 iv1, u8 iv2); -void ieee80211_tkip_encrypt_data(struct ieee80211_key *key, u8 *pos, - size_t payload_len, u8 *ta); -enum { - TKIP_DECRYPT_OK = 0, - TKIP_DECRYPT_NO_EXT_IV = -1, - TKIP_DECRYPT_INVALID_KEYIDX = -2, - TKIP_DECRYPT_REPLAY = -3, -}; -int ieee80211_tkip_decrypt_data(struct ieee80211_key *key, u8 *payload, - size_t payload_len, u8 *ta, int only_iv, - int queue); - -#endif /* TKIP_H */ diff --git a/target/linux/package/ieee80211-dscape/src/wep.c b/target/linux/package/ieee80211-dscape/src/wep.c deleted file mode 100644 index 57c2f603c0..0000000000 --- a/target/linux/package/ieee80211-dscape/src/wep.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Software WEP encryption implementation - * Copyright 2002, Jouni Malinen - * Copyright 2003, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include "ieee80211_i.h" -#include "wep.h" - - -static const __u32 crc32_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; - - -void ieee80211_wep_init(struct ieee80211_local *local) -{ - /* start WEP IV from a random value */ - get_random_bytes(&local->wep_iv, WEP_IV_LEN); -} - - -static inline int ieee80211_wep_weak_iv(u32 iv, int keylen) -{ - /* Fluhrer, Mantin, and Shamir have reported weaknesses in the - * key scheduling algorithm of RC4. At least IVs (KeyByte + 3, - * 0xff, N) can be used to speedup attacks, so avoid using them. */ - if ((iv & 0xff00) == 0xff00) { - u8 B = (iv >> 16) & 0xff; - if (B >= 3 && B < 3 + keylen) - return 1; - } - return 0; -} - - -void ieee80211_wep_get_iv(struct ieee80211_local *local, - struct ieee80211_key *key, u8 *iv) -{ - local->wep_iv++; - if (ieee80211_wep_weak_iv(local->wep_iv, key->keylen)) - local->wep_iv += 0x0100; - - if (iv == NULL) - return; - - *iv++ = (local->wep_iv >> 16) & 0xff; - *iv++ = (local->wep_iv >> 8) & 0xff; - *iv++ = local->wep_iv & 0xff; - *iv++ = key->keyidx << 6; -} - - -u8 * ieee80211_wep_add_iv(struct ieee80211_local *local, - struct sk_buff *skb, - struct ieee80211_key *key) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 fc; - int hdrlen; - u8 *newhdr; - - fc = le16_to_cpu(hdr->frame_control); - fc |= WLAN_FC_ISWEP; - hdr->frame_control = cpu_to_le16(fc); - - if ((skb_headroom(skb) < WEP_IV_LEN || - skb_tailroom(skb) < WEP_ICV_LEN)) { - I802_DEBUG_INC(local->tx_expand_skb_head); - if (unlikely(pskb_expand_head(skb, WEP_IV_LEN, WEP_ICV_LEN, - GFP_ATOMIC))) - return NULL; - } - - hdrlen = ieee80211_get_hdrlen(fc); - newhdr = skb_push(skb, WEP_IV_LEN); - memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); - ieee80211_wep_get_iv(local, key, newhdr + hdrlen); - return newhdr + hdrlen; -} - - -void ieee80211_wep_remove_iv(struct ieee80211_local *local, - struct sk_buff *skb, - struct ieee80211_key *key) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 fc; - int hdrlen; - - fc = le16_to_cpu(hdr->frame_control); - hdrlen = ieee80211_get_hdrlen(fc); - memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); - skb_pull(skb, WEP_IV_LEN); -} - - -/* Perform WEP encryption using given key. data buffer must have tailroom - * for 4-byte ICV. data_len must not include this ICV. Note: this function - * does _not_ add IV. data = RC4(data | CRC32(data)) */ -void ieee80211_wep_encrypt_data(u8 *rc4key, size_t klen, u8 *data, - size_t data_len) -{ - u32 i, j, k, crc; - u8 S[256]; - u8 kpos, *pos; -#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) - - /* Setup RC4 state */ - for (i = 0; i < 256; i++) - S[i] = i; - j = 0; - kpos = 0; - for (i = 0; i < 256; i++) { - j = (j + S[i] + rc4key[kpos]) & 0xff; - kpos++; - if (kpos >= klen) - kpos = 0; - S_SWAP(i, j); - } - - /* Compute CRC32 over unencrypted data and apply RC4 to data */ - pos = data; - crc = ~0; - i = j = 0; - for (k = 0; k < data_len; k++) { - crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8); - i = (i + 1) & 0xff; - j = (j + S[i]) & 0xff; - S_SWAP(i, j); - *pos++ ^= S[(S[i] + S[j]) & 0xff]; - } - crc = ~crc; - - /* Append little-endian CRC32 and encrypt it to produce ICV */ - pos[0] = crc; - pos[1] = crc >> 8; - pos[2] = crc >> 16; - pos[3] = crc >> 24; - for (k = 0; k < 4; k++) { - i = (i + 1) & 0xff; - j = (j + S[i]) & 0xff; - S_SWAP(i, j); - *pos++ ^= S[(S[i] + S[j]) & 0xff]; - } -} - - -/* Perform WEP encryption on given skb. 4 bytes of extra space (IV) in the - * beginning of the buffer 4 bytes of extra space (ICV) in the end of the - * buffer will be added. Both IV and ICV will be transmitted, so the - * payload length increases with 8 bytes. - * - * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) - */ -int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, - struct ieee80211_key *key) -{ - u32 klen; - u8 *rc4key, *iv; - size_t len; - - if (key == NULL || key->alg != ALG_WEP) - return -1; - - klen = 3 + key->keylen; - rc4key = kmalloc(klen, GFP_ATOMIC); - if (rc4key == NULL) - return -1; - - iv = ieee80211_wep_add_iv(local, skb, key); - if (iv == NULL) { - kfree(rc4key); - return -1; - } - - len = skb->len - (iv + WEP_IV_LEN - skb->data); - - /* Prepend 24-bit IV to RC4 key */ - memcpy(rc4key, iv, 3); - - /* Copy rest of the WEP key (the secret part) */ - memcpy(rc4key + 3, key->key, key->keylen); - - /* Add room for ICV */ - skb_put(skb, WEP_ICV_LEN); - - ieee80211_wep_encrypt_data(rc4key, klen, iv + WEP_IV_LEN, len); - - kfree(rc4key); - - return 0; -} - - -/* Perform WEP decryption using given key. data buffer includes encrypted - * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV. - * Return 0 on success and -1 on ICV mismatch. */ -int ieee80211_wep_decrypt_data(u8 *rc4key, size_t klen, u8 *data, - size_t data_len) -{ - u32 i, j, k, crc; - u8 S[256]; - u8 kpos, *pos, crcbuf[WEP_ICV_LEN], *cpos; - - /* Setup RC4 state */ - for (i = 0; i < 256; i++) - S[i] = i; - j = 0; - kpos = 0; - for (i = 0; i < 256; i++) { - j = (j + S[i] + rc4key[kpos]) & 0xff; - kpos++; - if (kpos >= klen) - kpos = 0; - S_SWAP(i, j); - } - - /* Apply RC4 to data and compute CRC32 over decrypted data */ - pos = data; - crc = ~0; - i = j = 0; - for (k = 0; k < data_len; k++) { - i = (i + 1) & 0xff; - j = (j + S[i]) & 0xff; - S_SWAP(i, j); - *pos ^= S[(S[i] + S[j]) & 0xff]; - crc = crc32_table[(crc ^ *pos++) & 0xff] ^ (crc >> 8); - } - crc = ~crc; - - /* Decrypt little-endian CRC32 and verify that it matches with the - * received ICV */ - cpos = crcbuf; - crcbuf[0] = crc; - crcbuf[1] = crc >> 8; - crcbuf[2] = crc >> 16; - crcbuf[3] = crc >> 24; - for (k = 0; k < WEP_ICV_LEN; k++) { - i = (i + 1) & 0xff; - j = (j + S[i]) & 0xff; - S_SWAP(i, j); - if (*cpos++ != (*pos++ ^ S[(S[i] + S[j]) & 0xff])) { - /* ICV mismatch */ - return -1; - } - } - - return 0; -} - - -/* Perform WEP decryption on given skb. Buffer includes whole WEP part of - * the frame: IV (4 bytes), encrypted payload (including SNAP header), - * ICV (4 bytes). skb->len includes both IV and ICV. - * - * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on - * failure. If frame is OK, IV and ICV will be removed, i.e., decrypted payload - * is moved to the beginning of the skb and skb length will be reduced. - */ -int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, - struct ieee80211_key *key) -{ - u32 klen; - u8 *rc4key; - u8 keyidx; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 fc; - int hdrlen; - size_t len; - int ret = 0; - - fc = le16_to_cpu(hdr->frame_control); - if (!(fc & WLAN_FC_ISWEP)) - return -1; - - hdrlen = ieee80211_get_hdrlen(fc); - - if (skb->len < 8 + hdrlen) - return -1; - - len = skb->len - hdrlen - 8; - - keyidx = skb->data[hdrlen + 3] >> 6; - - if (key == NULL || keyidx != key->keyidx || key->alg != ALG_WEP) - return -1; - - klen = 3 + key->keylen; - - rc4key = kmalloc(klen, GFP_ATOMIC); - if (rc4key == NULL) - return -1; - - /* Prepend 24-bit IV to RC4 key */ - memcpy(rc4key, skb->data + hdrlen, 3); - - /* Copy rest of the WEP key (the secret part) */ - memcpy(rc4key + 3, key->key, key->keylen); - - if (ieee80211_wep_decrypt_data(rc4key, klen, - skb->data + hdrlen + WEP_IV_LEN, - len)) { - printk(KERN_DEBUG "WEP decrypt failed (ICV)\n"); - ret = -1; - } - - kfree(rc4key); - - /* Trim ICV */ - skb_trim(skb, skb->len - WEP_ICV_LEN); - - /* Remove IV */ - memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); - skb_pull(skb, WEP_IV_LEN); - - return ret; -} - - -int ieee80211_wep_get_keyidx(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 fc; - int hdrlen; - - fc = le16_to_cpu(hdr->frame_control); - if (!(fc & WLAN_FC_ISWEP)) - return -1; - - hdrlen = ieee80211_get_hdrlen(fc); - - if (skb->len < 8 + hdrlen) - return -1; - - return skb->data[hdrlen + 3] >> 6; -} - - -u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 fc; - int hdrlen; - u8 *ivpos; - u32 iv; - - fc = le16_to_cpu(hdr->frame_control); - if (!(fc & WLAN_FC_ISWEP)) - return NULL; - - hdrlen = ieee80211_get_hdrlen(fc); - ivpos = skb->data + hdrlen; - iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; - - if (ieee80211_wep_weak_iv(iv, key->keylen)) - return ivpos; - - return NULL; -} diff --git a/target/linux/package/ieee80211-dscape/src/wep.h b/target/linux/package/ieee80211-dscape/src/wep.h deleted file mode 100644 index 6f693945af..0000000000 --- a/target/linux/package/ieee80211-dscape/src/wep.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Software WEP encryption implementation - * Copyright 2002, Jouni Malinen - * Copyright 2003, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef WEP_H -#define WEP_H - -void ieee80211_wep_init(struct ieee80211_local *local); -void ieee80211_wep_get_iv(struct ieee80211_local *local, - struct ieee80211_key *key, u8 *iv); -u8 * ieee80211_wep_add_iv(struct ieee80211_local *local, - struct sk_buff *skb, - struct ieee80211_key *key); -void ieee80211_wep_remove_iv(struct ieee80211_local *local, - struct sk_buff *skb, - struct ieee80211_key *key); -void ieee80211_wep_encrypt_data(u8 *rc4key, size_t klen, u8 *data, - size_t data_len); -int ieee80211_wep_decrypt_data(u8 *rc4key, size_t klen, u8 *data, - size_t data_len); -int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, - struct ieee80211_key *key); -int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, - struct ieee80211_key *key); -int ieee80211_wep_get_keyidx(struct sk_buff *skb); -u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); - -#endif /* WEP_H */ diff --git a/target/linux/package/ieee80211-dscape/src/wme.c b/target/linux/package/ieee80211-dscape/src/wme.c deleted file mode 100644 index b3fdd59e5a..0000000000 --- a/target/linux/package/ieee80211-dscape/src/wme.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright 2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include "ieee80211_i.h" -#include "wme.h" - -#define CHILD_QDISC_OPS pfifo_qdisc_ops - -static inline int WLAN_FC_IS_QOS_DATA(u16 fc) -{ - return (fc & 0x8C) == 0x88; -} - - -ieee80211_txrx_result -ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx) -{ - u8 *data = rx->skb->data; - int tid; - - /* does the frame have a qos control field? */ - if (WLAN_FC_IS_QOS_DATA(rx->fc)) { - u8 *qc = data + ieee80211_get_hdrlen(rx->fc) - QOS_CONTROL_LEN; - /* frame has qos control */ - tid = qc[0] & QOS_CONTROL_TID_MASK; - } else { - if (unlikely(WLAN_FC_GET_TYPE(rx->fc) == WLAN_FC_TYPE_MGMT)) { - /* Separate TID for management frames */ - tid = NUM_RX_DATA_QUEUES - 1; - } else { - /* no qos control present */ - tid = 0; /* 802.1d - Best Effort */ - } - } -#ifdef CONFIG_IEEE80211_DEBUG_COUNTERS - I802_DEBUG_INC(rx->local->wme_rx_queue[tid]); - if (rx->sta) { - I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]); - } -#endif /* CONFIG_IEEE80211_DEBUG_COUNTERS */ - - rx->u.rx.queue = tid; - /* Set skb->priority to 1d tag if highest order bit of TID is not set. - * For now, set skb->priority to 0 for other cases. */ - rx->skb->priority = (tid > 7) ? 0 : tid; - - return TXRX_CONTINUE; -} - - -ieee80211_txrx_result -ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx) -{ - u16 fc = rx->fc; - u8 *data = rx->skb->data; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data; - - if (!WLAN_FC_IS_QOS_DATA(fc)) - return TXRX_CONTINUE; - - /* remove the qos control field, update frame type and meta-data */ - memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2); - hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2); - /* change frame type to non QOS */ - rx->fc = fc &= ~(WLAN_FC_STYPE_QOS_DATA << 4); - hdr->frame_control = cpu_to_le16(fc); - - return TXRX_CONTINUE; -} - - -/* maximum number of hardware queues we support. */ -#define TC_80211_MAX_QUEUES 8 - -struct ieee80211_sched_data -{ - struct tcf_proto *filter_list; - struct Qdisc *queues[TC_80211_MAX_QUEUES]; - struct sk_buff_head requeued[TC_80211_MAX_QUEUES]; -}; - - -/* given a data frame determine the 802.1p/1d tag to use */ -static inline unsigned classify_1d(struct sk_buff *skb, struct Qdisc *qd) -{ - struct iphdr *ip; - int dscp; - int offset; - -#ifdef CONFIG_NET_SCHED - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct tcf_result res = { -1, 0 }; - - /* if there is a user set filter list, call out to that */ - if (q->filter_list) { - tc_classify(skb, q->filter_list, &res); - if (res.class != -1) - return res.class; - } -#endif /* CONFIG_NET_SCHED */ - - /* skb->priority values from 256->263 are magic values to - * directly indicate a specific 802.1d priority. - * This is used to allow 802.1d priority to be passed directly in - * from VLAN tags, etc. */ - if (skb->priority >= 256 && skb->priority <= 263) - return skb->priority - 256; - - /* check there is a valid IP header present */ - offset = ieee80211_get_hdrlen_from_skb(skb) + 8 /* LLC + proto */; - if (skb->protocol != __constant_htons(ETH_P_IP) || - skb->len < offset + sizeof(*ip)) - return 0; - - ip = (struct iphdr *) (skb->data + offset); - - dscp = ip->tos & 0xfc; - switch (dscp) { - case 0x20: - return 2; - case 0x40: - return 1; - case 0x60: - return 3; - case 0x80: - return 4; - case 0xa0: - return 5; - case 0xc0: - return 6; - case 0xe0: - return 7; - default: - return 0; - } -} - - - - -static inline int wme_downgrade_ac(struct sk_buff *skb) -{ - switch (skb->priority) { - case 6: - case 7: - skb->priority = 5; /* VO -> VI */ - return 0; - case 4: - case 5: - skb->priority = 3; /* VI -> BE */ - return 0; - case 0: - case 3: - skb->priority = 2; /* BE -> BK */ - return 0; - default: - return -1; - } -} - - -/* positive return value indicates which queue to use - * negative return value indicates to drop the frame */ -static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd) -{ - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_tx_packet_data *pkt_data = - (struct ieee80211_tx_packet_data *) skb->cb; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - unsigned short fc = le16_to_cpu(hdr->frame_control); - int qos; - const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 }; - - if (unlikely(pkt_data->magic != IEEE80211_CB_MAGIC)) - return -1; - - /* see if frame is data or non data frame */ - if (unlikely(WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_DATA)) { - /* management frames go on AC_VO queue, but are sent - * without QoS control fields */ - return IEEE80211_TX_QUEUE_DATA0; - } - - if (unlikely(pkt_data->sdata->type == IEEE80211_SUB_IF_TYPE_MGMT)) { - /* Data frames from hostapd (mainly, EAPOL) use AC_VO - * and they will include QoS control fields if - * the target STA is using WME. */ - skb->priority = 7; - return ieee802_1d_to_ac[skb->priority]; - } - - - /* is this a QoS frame? */ - qos = fc & (WLAN_FC_STYPE_QOS_DATA << 4); - - - if (!qos) { - skb->priority = 0; /* required for correct WPA/11i MIC */ - return ieee802_1d_to_ac[skb->priority]; - } - - /* use the data classifier to determine what 802.1d tag the - * data frame has */ - skb->priority = classify_1d(skb, qd); - - - /* incase we are a client verify acm is not set for this ac */ - for (; unlikely(local->wmm_acm & BIT(skb->priority)); ) - { - if (wme_downgrade_ac(skb)) { - /* No AC with lower priority has acm=0, - * drop packet. */ - return -1; - } - } - - /* look up which queue to use for frames with this 1d tag */ - return ieee802_1d_to_ac[skb->priority]; -} - - -static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) -{ - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct ieee80211_tx_packet_data *pkt_data = - (struct ieee80211_tx_packet_data *) skb->cb; - struct ieee80211_tx_control *control = &pkt_data->control; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - unsigned short fc = le16_to_cpu(hdr->frame_control); - struct Qdisc *qdisc; - int err, queue; - - if (control->requeue) { - skb_queue_tail(&q->requeued[control->queue], skb); - return 0; - } - - queue = classify80211(skb, qd); - - /* now we know the 1d priority, fill in the QoS header if there is one */ - if (WLAN_FC_IS_QOS_DATA(fc)) { - struct qos_control *qc = (struct qos_control *) (skb->data + ieee80211_get_hdrlen(fc) - 2); - u8 *p = (u8 *) qc; - *p++ = 0; /* do this due to gcc's lack of optimization on bitfield ops */ - *p = 0; - qc->tag1d = skb->priority; - if (local->wifi_wme_noack_test) - qc->ack_policy = 1; - } - - if (unlikely(queue >= local->hw->queues)) { -#if 0 - if (net_ratelimit()) { - printk(KERN_DEBUG "%s - queue=%d (hw does not " - "support) -> %d\n", - __func__, queue, local->hw->queues - 1); - } -#endif - queue = local->hw->queues - 1; - } - - if (unlikely(queue < 0)) { - kfree_skb(skb); - err = NET_XMIT_DROP; - } else { - control->queue = (unsigned int) queue; - qdisc = q->queues[queue]; - err = qdisc->enqueue(skb, qdisc); - if (err == NET_XMIT_SUCCESS) { - qd->q.qlen++; - qd->bstats.bytes += skb->len; - qd->bstats.packets++; - return NET_XMIT_SUCCESS; - } - } - qd->qstats.drops++; - return err; -} - - -/* TODO: clean up the cases where master_hard_start_xmit - * returns non 0 - it shouldn't ever do that. Once done we - * can remove this function */ -static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) -{ - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct ieee80211_tx_packet_data *pkt_data = - (struct ieee80211_tx_packet_data *) skb->cb; - struct Qdisc *qdisc; - int err; - - /* we recorded which queue to use earlier! */ - qdisc = q->queues[pkt_data->control.queue]; - - if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) { - qd->q.qlen++; - return 0; - } - qd->qstats.drops++; - return err; -} - - -static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd) -{ - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct net_device *dev = qd->dev; - struct ieee80211_local *local = dev->priv; - struct ieee80211_hw *hw = local->hw; - struct ieee80211_tx_queue_stats stats; - struct sk_buff *skb; - struct Qdisc *qdisc; - int queue; - - /* find which hardware queues have space in them */ - hw->get_tx_stats(dev, &stats); - - /* check all the h/w queues in numeric/priority order */ - for (queue = 0; queue < hw->queues; queue++) { - /* see if there is room in this hardware queue */ - if (stats.data[queue].len >= stats.data[queue].limit) - continue; - - /* there is space - try and get a frame */ - skb = skb_dequeue(&q->requeued[queue]); - if (skb) - return skb; - - qdisc = q->queues[queue]; - skb = qdisc->dequeue(qdisc); - if (skb) { - qd->q.qlen--; - return skb; - } - } - /* returning a NULL here when all the h/w queues are full means we - * never need to call netif_stop_queue in the driver */ - return NULL; -} - - -static void wme_qdiscop_reset(struct Qdisc* qd) -{ - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_hw *hw = local->hw; - int queue; - - /* QUESTION: should we have some hardware flush functionality here? */ - - for (queue = 0; queue < hw->queues; queue++) { - skb_queue_purge(&q->requeued[queue]); - qdisc_reset(q->queues[queue]); - } - qd->q.qlen = 0; -} - - -static void wme_qdiscop_destroy(struct Qdisc* qd) -{ - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_hw *hw = local->hw; - struct tcf_proto *tp; - int queue; - - while ((tp = q->filter_list) != NULL) { - q->filter_list = tp->next; - tp->ops->destroy(tp); - } - - for (queue=0; queue < hw->queues; queue++) { - skb_queue_purge(&q->requeued[queue]); - qdisc_destroy(q->queues[queue]); - q->queues[queue] = &noop_qdisc; - } -} - - -/* called whenever parameters are updated on existing qdisc */ -static int wme_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt) -{ -/* struct ieee80211_sched_data *q = qdisc_priv(qd); -*/ - /* check our options block is the right size */ - /* copy any options to our local structure */ -/* Ignore options block for now - always use static mapping - struct tc_ieee80211_qopt *qopt = RTA_DATA(opt); - - if (opt->rta_len < RTA_LENGTH(sizeof(*qopt))) - return -EINVAL; - memcpy(q->tag2queue, qopt->tag2queue, sizeof(qopt->tag2queue)); -*/ - return 0; -} - - -/* called during initial creation of qdisc on device */ -static int wme_qdiscop_init(struct Qdisc *qd, struct rtattr *opt) -{ - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct net_device *dev = qd->dev; - struct ieee80211_local *local = dev->priv; - int queues = local->hw->queues; - int err = 0, i; - - /* check this device is an ieee80211 master type device */ - if (dev->type != ARPHRD_IEEE80211) - return -EINVAL; - - /* check that there is no qdisc currently attached to device - * this ensures that we will be the root qdisc. (I can't find a better - * way to test this explicitly) */ - if (dev->qdisc_sleeping != &noop_qdisc) - return -EINVAL; - - if (qd->flags & TCQ_F_INGRESS) - return -EINVAL; - - /* if options were passed in, set them */ - if (opt) { - err = wme_qdiscop_tune(qd, opt); - } - - /* create child queues */ - for (i = 0; i < queues; i++) { - skb_queue_head_init(&q->requeued[i]); - q->queues[i] = qdisc_create_dflt(qd->dev, &CHILD_QDISC_OPS); - if (q->queues[i] == 0) { - q->queues[i] = &noop_qdisc; - printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i); - } - } - - return err; -} - -static int wme_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb) -{ -/* struct ieee80211_sched_data *q = qdisc_priv(qd); - unsigned char *p = skb->tail; - struct tc_ieee80211_qopt opt; - - memcpy(&opt.tag2queue, q->tag2queue, TC_80211_MAX_TAG + 1); - RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); -*/ return skb->len; -/* -rtattr_failure: - skb_trim(skb, p - skb->data);*/ - return -1; -} - - -static int wme_classop_graft(struct Qdisc *qd, unsigned long arg, - struct Qdisc *new, struct Qdisc **old) -{ - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_hw *hw = local->hw; - unsigned long queue = arg - 1; - - if (queue >= hw->queues) - return -EINVAL; - - if (new == NULL) - new = &noop_qdisc; - - sch_tree_lock(qd); - *old = q->queues[queue]; - q->queues[queue] = new; - qdisc_reset(*old); - sch_tree_unlock(qd); - - return 0; -} - - -static struct Qdisc * -wme_classop_leaf(struct Qdisc *qd, unsigned long arg) -{ - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_hw *hw = local->hw; - unsigned long queue = arg - 1; - - if (queue >= hw->queues) - return NULL; - - return q->queues[queue]; -} - - -static unsigned long wme_classop_get(struct Qdisc *qd, u32 classid) -{ - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_hw *hw = local->hw; - unsigned long queue = TC_H_MIN(classid); - - if (queue - 1 >= hw->queues) - return 0; - - return queue; -} - - -static unsigned long wme_classop_bind(struct Qdisc *qd, unsigned long parent, - u32 classid) -{ - return wme_classop_get(qd, classid); -} - - -static void wme_classop_put(struct Qdisc *q, unsigned long cl) -{ - /* printk(KERN_DEBUG "entering %s\n", __func__); */ -} - - -static int wme_classop_change(struct Qdisc *qd, u32 handle, u32 parent, - struct rtattr **tca, unsigned long *arg) -{ - unsigned long cl = *arg; - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_hw *hw = local->hw; - /* printk(KERN_DEBUG "entering %s\n", __func__); */ - - if (cl - 1 > hw->queues) - return -ENOENT; - - /* TODO: put code to program hardware queue parameters here, - * to allow programming from tc command line */ - - return 0; -} - - -/* we don't support deleting hardware queues - * when we add WMM-SA support - TSPECs may be deleted here */ -static int wme_classop_delete(struct Qdisc *qd, unsigned long cl) -{ - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_hw *hw = local->hw; - /* printk(KERN_DEBUG "entering %s\n", __func__); */ - - if (cl - 1 > hw->queues) - return -ENOENT; - return 0; -} - - -static int wme_classop_dump_class(struct Qdisc *qd, unsigned long cl, - struct sk_buff *skb, struct tcmsg *tcm) -{ - struct ieee80211_sched_data *q = qdisc_priv(qd); - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_hw *hw = local->hw; - /* printk(KERN_DEBUG "entering %s\n", __func__); */ - - if (cl - 1 > hw->queues) - return -ENOENT; - tcm->tcm_handle = TC_H_MIN(cl); - tcm->tcm_parent = qd->handle; - tcm->tcm_info = q->queues[cl-1]->handle; /* do we need this? */ - return 0; -} - - -static void wme_classop_walk(struct Qdisc *qd, struct qdisc_walker *arg) -{ - struct ieee80211_local *local = qd->dev->priv; - struct ieee80211_hw *hw = local->hw; - int queue; - /* printk(KERN_DEBUG "entering %s\n", __func__); */ - - if (arg->stop) - return; - - for (queue = 0; queue < hw->queues; queue++) { - if (arg->count < arg->skip) { - arg->count++; - continue; - } - /* we should return classids for our internal queues here - * as well as the external ones */ - if (arg->fn(qd, queue+1, arg) < 0) { - arg->stop = 1; - break; - } - arg->count++; - } -} - - -static struct tcf_proto ** wme_classop_find_tcf(struct Qdisc *qd, - unsigned long cl) -{ - struct ieee80211_sched_data *q = qdisc_priv(qd); - /* printk("entering %s\n", __func__); */ - - if (cl) - return NULL; - - return &q->filter_list; -} - - -/* this qdisc is classful (i.e. has classes, some of which may have leaf qdiscs attached) - * - these are the operations on the classes */ -static struct Qdisc_class_ops class_ops = -{ - .graft = wme_classop_graft, - .leaf = wme_classop_leaf, - - .get = wme_classop_get, - .put = wme_classop_put, - .change = wme_classop_change, - .delete = wme_classop_delete, - .walk = wme_classop_walk, - - .tcf_chain = wme_classop_find_tcf, - .bind_tcf = wme_classop_bind, - .unbind_tcf = wme_classop_put, - - .dump = wme_classop_dump_class, -}; - - -/* queueing discipline operations */ -static struct Qdisc_ops wme_qdisc_ops = -{ - .next = NULL, - .cl_ops = &class_ops, - .id = "ieee80211", - .priv_size = sizeof(struct ieee80211_sched_data), - - .enqueue = wme_qdiscop_enqueue, - .dequeue = wme_qdiscop_dequeue, - .requeue = wme_qdiscop_requeue, - .drop = NULL, /* drop not needed since we are always the root qdisc */ - - .init = wme_qdiscop_init, - .reset = wme_qdiscop_reset, - .destroy = wme_qdiscop_destroy, - .change = wme_qdiscop_tune, - - .dump = wme_qdiscop_dump, -}; - - -void ieee80211_install_qdisc(struct net_device *dev) -{ - struct Qdisc *qdisc; - - qdisc = qdisc_create_dflt(dev, &wme_qdisc_ops); - if (qdisc == NULL) { - printk(KERN_ERR "%s: qdisc installation failed\n", dev->name); - return; - } - - /* same handle as would be allocated by qdisc_alloc_handle() */ - qdisc->handle = 0x80010000; - - write_lock(&qdisc_tree_lock); - list_add_tail(&qdisc->list, &dev->qdisc_list); - dev->qdisc_sleeping = qdisc; - write_unlock(&qdisc_tree_lock); -} - - -int ieee80211_wme_register(void) -{ - int err = 0; - -#ifdef CONFIG_NET_SCHED - err = register_qdisc(&wme_qdisc_ops); -#endif - return err; -} - - -void ieee80211_wme_unregister(void) -{ -#ifdef CONFIG_NET_SCHED - unregister_qdisc(&wme_qdisc_ops); -#endif -} diff --git a/target/linux/package/ieee80211-dscape/src/wme.h b/target/linux/package/ieee80211-dscape/src/wme.h deleted file mode 100644 index 9b27947807..0000000000 --- a/target/linux/package/ieee80211-dscape/src/wme.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * IEEE 802.11 driver (80211.o) - QoS datatypes - * Copyright 2004, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include - -#define QOS_CONTROL_LEN 2 - -#define QOS_CONTROL_ACK_POLICY_NORMAL 0 -#define QOS_CONTROL_ACK_POLICY_NOACK 1 - -#define QOS_CONTROL_TID_MASK 0x0f -#define QOS_CONTROL_ACK_POLICY_SHIFT 5 - -/* This bit field structure should not be used; it can cause compiler to - * generate unaligned accesses and inefficient code. */ -struct qos_control { -#if defined(__LITTLE_ENDIAN_BITFIELD) - u8 tag1d:3, /* bits 0-2 */ - reserved1:1, - eosp:1, - ack_policy:2, - reserved2:1; -#elif defined (__BIG_ENDIAN_BITFIELD) - u8 reserved2:1, - ack_policy:2, - eosp:1, - reserved1:1, - tag1d:3; /* bits 0-2 */ -#else -#error "Please fix " -#endif - u8 reserved; -} __attribute__ ((packed)); - -ieee80211_txrx_result -ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx); - -ieee80211_txrx_result -ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx); - -void ieee80211_install_qdisc(struct net_device *dev); - -int ieee80211_wme_register(void); -void ieee80211_wme_unregister(void); - diff --git a/target/linux/package/ieee80211-dscape/src/wpa.c b/target/linux/package/ieee80211-dscape/src/wpa.c deleted file mode 100644 index e0050dbd8f..0000000000 --- a/target/linux/package/ieee80211-dscape/src/wpa.c +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright 2002-2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "ieee80211_i.h" -#include "michael.h" -#include "tkip.h" -#include "aes_ccm.h" -#include "wpa.h" -#ifdef CONFIG_HOSTAPD_WPA_TESTING -#include "hostapd_ioctl.h" -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - -#define MICHAEL_MIC_HWACCEL - - -int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da, - u8 *qos_tid, u8 **data, size_t *data_len) -{ - struct ieee80211_hdr *hdr; - size_t hdrlen; - u16 fc; - int a4_included; - u8 *pos; - - hdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(hdr->frame_control); - - hdrlen = 24; - if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) == - (WLAN_FC_FROMDS | WLAN_FC_TODS)) { - hdrlen += ETH_ALEN; - *sa = hdr->addr4; - *da = hdr->addr3; - } else if (fc & WLAN_FC_FROMDS) { - *sa = hdr->addr3; - *da = hdr->addr1; - } else if (fc & WLAN_FC_TODS) { - *sa = hdr->addr2; - *da = hdr->addr3; - } else { - *sa = hdr->addr2; - *da = hdr->addr1; - } - - if (fc & 0x80) - hdrlen += 2; - - *data = skb->data + hdrlen; - *data_len = skb->len - hdrlen; - - a4_included = (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == - (WLAN_FC_TODS | WLAN_FC_FROMDS); - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA && - WLAN_FC_GET_STYPE(fc) & 0x08) { - pos = (u8 *) &hdr->addr4; - if (a4_included) - pos += 6; - *qos_tid = pos[0] & 0x0f; - *qos_tid |= 0x80; /* qos_included flag */ - } else - *qos_tid = 0; - - return skb->len < hdrlen ? -1 : 0; -} - - -ieee80211_txrx_result -ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx) -{ - u8 *data, *sa, *da, *key, *mic, qos_tid; - size_t data_len; - u16 fc; - struct sk_buff *skb = tx->skb; - int authenticator; -#if defined(CONFIG_HOSTAPD_WPA_TESTING) || defined(MICHAEL_MIC_HWACCEL) - int wpa_test = 0; -#endif - - fc = tx->fc; - - if (!tx->key || tx->key->alg != ALG_TKIP || skb->len < 24 || - !WLAN_FC_DATA_PRESENT(fc)) - return TXRX_CONTINUE; - - if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)) - return TXRX_DROP; - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if ((tx->sta && tx->sta->wpa_trigger & WPA_TRIGGER_FAIL_TX_MIC) || - (!tx->u.tx.unicast && - tx->local->wpa_trigger & WPA_TRIGGER_FAIL_TX_MIC)) { - wpa_test = 1; - } -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - -#ifdef MICHAEL_MIC_HWACCEL - if (!tx->key->force_sw_encrypt && !tx->local->conf.sw_decrypt && - !tx->fragmented && !wpa_test) { - /* hwaccel - with no need for preallocated room for Michael MIC - */ - return TXRX_CONTINUE; - } -#endif /* MICHAEL_MIC_HWACCEL */ - - if (skb_tailroom(skb) < MICHAEL_MIC_LEN) { - I802_DEBUG_INC(tx->local->tx_expand_skb_head); - if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN, - MICHAEL_MIC_LEN + TKIP_ICV_LEN, - GFP_ATOMIC))) { - printk(KERN_DEBUG "%s: failed to allocate more memory " - "for Michael MIC\n", tx->dev->name); - return TXRX_DROP; - } - } - -#if 0 - authenticator = fc & WLAN_FC_FROMDS; /* FIX */ -#else - authenticator = 1; -#endif - key = &tx->key->key[authenticator ? ALG_TKIP_TEMP_AUTH_TX_MIC_KEY : - ALG_TKIP_TEMP_AUTH_RX_MIC_KEY]; - mic = skb_put(skb, MICHAEL_MIC_LEN); - michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (tx->sta && tx->sta->wpa_trigger & WPA_TRIGGER_FAIL_TX_MIC) { - printk(KERN_INFO "%s: WPA testing - corrupting TX Michael MIC " - "for STA " MACSTR "\n", - tx->dev->name, MAC2STR(tx->sta->addr)); - tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID; - tx->sta->wpa_trigger &= ~WPA_TRIGGER_FAIL_TX_MIC; - tx->wpa_test = 1; - mic[0]++; - } else if (!tx->u.tx.unicast && - tx->local->wpa_trigger & WPA_TRIGGER_FAIL_TX_MIC) { - printk(KERN_INFO "%s: WPA testing - corrupting TX Michael MIC " - "for Group Key\n", tx->dev->name); - tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID; - tx->local->wpa_trigger &= ~WPA_TRIGGER_FAIL_TX_MIC; - tx->wpa_test = 1; - mic[0]++; - } -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - return TXRX_CONTINUE; -} - - -ieee80211_txrx_result -ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx) -{ - u8 *data, *sa, *da, *key = NULL, qos_tid; - size_t data_len; - u16 fc; - u8 mic[MICHAEL_MIC_LEN]; - struct sk_buff *skb = rx->skb; - int authenticator = 1, wpa_test = 0; - - fc = rx->fc; - - /* If device handles decryption totally, skip this check */ - if (rx->local->hw->device_hides_wep || - rx->local->hw->device_strips_mic) - return TXRX_CONTINUE; - - if (!rx->key || rx->key->alg != ALG_TKIP || - !(rx->fc & WLAN_FC_ISWEP) || !WLAN_FC_DATA_PRESENT(fc)) - return TXRX_CONTINUE; - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (rx->sta && rx->sta->wpa_trigger & WPA_TRIGGER_FAIL_RX_MIC) { - wpa_test = 1; - } -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - -#ifdef MICHAEL_MIC_HWACCEL - if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && - !rx->key->force_sw_encrypt && !rx->local->conf.sw_decrypt) { - if (rx->local->hw->wep_include_iv) { - if (skb->len < MICHAEL_MIC_LEN) - return TXRX_DROP; - } - /* Need to verify Michael MIC sometimes in software even when - * hwaccel is used. Atheros ar5212: fragmented frames and QoS - * frames. */ - if (!rx->fragmented && !wpa_test) - goto remove_mic; - } -#endif /* MICHAEL_MIC_HWACCEL */ - - if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len) - || data_len < MICHAEL_MIC_LEN) - return TXRX_DROP; - - data_len -= MICHAEL_MIC_LEN; - -#if 0 - authenticator = fc & WLAN_FC_TODS; /* FIX */ -#else - authenticator = 1; -#endif - key = &rx->key->key[authenticator ? ALG_TKIP_TEMP_AUTH_RX_MIC_KEY : - ALG_TKIP_TEMP_AUTH_TX_MIC_KEY]; - michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (rx->sta && rx->sta->wpa_trigger & WPA_TRIGGER_FAIL_RX_MIC) { - printk(KERN_INFO "%s: WPA testing - corrupting RX Michael MIC " - "for STA " MACSTR "\n", - rx->dev->name, MAC2STR(rx->sta->addr)); - rx->sta->wpa_trigger &= ~WPA_TRIGGER_FAIL_RX_MIC; - mic[0]++; - } -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { -#ifdef CONFIG_HOSTAPD_WPA_TESTING - int i; -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from " - MACSTR "\n", rx->dev->name, MAC2STR(sa)); -#ifdef CONFIG_HOSTAPD_WPA_TESTING - printk(KERN_DEBUG " received"); - for (i = 0; i < MICHAEL_MIC_LEN; i++) - printk(" %02x", data[data_len + i]); - printk(" expected"); - for (i = 0; i < MICHAEL_MIC_LEN; i++) - printk(" %02x", mic[i]); - printk("\n"); - printk(KERN_DEBUG " SA=" MACSTR " DA=" MACSTR " key", - MAC2STR(sa), MAC2STR(da)); - for (i = 0; i < 8; i++) - printk(" %02x", key[i]); - printk(" (%d)\n", authenticator); -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - do { - struct ieee80211_hdr *hdr; - union iwreq_data wrqu; - char *buf = kmalloc(128, GFP_ATOMIC); - if (buf == NULL) - break; - - /* TODO: needed parameters: count, key type, TSC */ - hdr = (struct ieee80211_hdr *) skb->data; - sprintf(buf, "MLME-MICHAELMICFAILURE.indication(" - "keyid=%d %scast addr=" MACSTR ")", - rx->key->keyidx, - hdr->addr1[0] & 0x01 ? "broad" : "uni", - MAC2STR(hdr->addr2)); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = strlen(buf); - wireless_send_event(rx->dev, IWEVCUSTOM, &wrqu, buf); - kfree(buf); - } while (0); - - ieee80211_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status, - ieee80211_msg_michael_mic_failure); - - return TXRX_QUEUED; - } - -#ifdef MICHAEL_MIC_HWACCEL - remove_mic: -#endif /* MICHAEL_MIC_HWACCEL */ - /* remove Michael MIC from payload */ - skb_trim(skb, skb->len - MICHAEL_MIC_LEN); - - return TXRX_CONTINUE; -} - - -static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx, - struct sk_buff *skb, int test) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_key *key = tx->key; - int hdrlen, len, tailneed; - u16 fc; - u8 *pos; - - fc = le16_to_cpu(hdr->frame_control); - hdrlen = ieee80211_get_hdrlen(fc); - len = skb->len - hdrlen; - - tailneed = (!tx->key->force_sw_encrypt && !tx->local->conf.sw_decrypt) - ? 0 : TKIP_ICV_LEN; - if ((skb_headroom(skb) < TKIP_IV_LEN || - skb_tailroom(skb) < tailneed)) { - I802_DEBUG_INC(tx->local->tx_expand_skb_head); - if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN, tailneed, - GFP_ATOMIC))) - return -1; - } - - pos = skb_push(skb, TKIP_IV_LEN); - memmove(pos, pos + TKIP_IV_LEN, hdrlen); - pos += hdrlen; - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (test & WPA_TRIGGER_TX_REPLAY) - goto skip_iv_inc; -iv_inc: -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - /* Increase IV for the frame */ - key->u.tkip.iv16++; - if (key->u.tkip.iv16 == 0) - key->u.tkip.iv32++; - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (test & WPA_TRIGGER_TX_SKIP_SEQ) { - test = 0; - goto iv_inc; - } -skip_iv_inc: -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - if (!tx->key->force_sw_encrypt && !tx->local->conf.sw_decrypt -#ifdef CONFIG_HOSTAPD_WPA_TESTING - && !tx->wpa_test -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - ) { - /* hwaccel - with preallocated room for IV */ - - ieee80211_tkip_add_iv(pos, key, - (u8) (key->u.tkip.iv16 >> 8), - (u8) (((key->u.tkip.iv16 >> 8) | 0x20) & - 0x7f), - (u8) key->u.tkip.iv16); - - tx->u.tx.control->key_idx = tx->key->hw_key_idx; - return 0; - } - - /* Add room for ICV */ - skb_put(skb, TKIP_ICV_LEN); - - hdr = (struct ieee80211_hdr *) skb->data; - ieee80211_tkip_encrypt_data(key, pos, len, hdr->addr2); - return 0; -} - - -ieee80211_txrx_result -ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; - u16 fc; - struct ieee80211_key *key = tx->key; - struct sk_buff *skb = tx->skb; - int wpa_test = 0, test = 0; - - fc = le16_to_cpu(hdr->frame_control); - - if (!key || key->alg != ALG_TKIP || !WLAN_FC_DATA_PRESENT(fc)) - return TXRX_CONTINUE; - - tx->u.tx.control->icv_len = TKIP_ICV_LEN; - tx->u.tx.control->iv_len = TKIP_IV_LEN; - ieee80211_tx_set_iswep(tx); - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if ((tx->sta && tx->sta->wpa_trigger & WPA_TRIGGER_FAIL_TX_ICV) || - (!tx->u.tx.unicast && - tx->local->wpa_trigger & WPA_TRIGGER_FAIL_TX_ICV)) { - wpa_test = 1; - } - - if (tx->sta) { - test = tx->sta->wpa_trigger; - tx->sta->wpa_trigger &= - ~(WPA_TRIGGER_TX_REPLAY | WPA_TRIGGER_TX_REPLAY_FRAG | - WPA_TRIGGER_TX_SKIP_SEQ); - } else { - test = tx->local->wpa_trigger; - tx->local->wpa_trigger &= - ~(WPA_TRIGGER_TX_REPLAY | WPA_TRIGGER_TX_REPLAY_FRAG | - WPA_TRIGGER_TX_SKIP_SEQ); - } - if (test & - (WPA_TRIGGER_TX_REPLAY | WPA_TRIGGER_TX_REPLAY_FRAG | - WPA_TRIGGER_TX_SKIP_SEQ)) { - printk(KERN_INFO "%s: WPA testing - TKIP TX packet number " - "%s%s%s%s\n", tx->dev->name, - tx->sta ? "[UNICAST]" : "[MULTICAST]", - test & WPA_TRIGGER_TX_REPLAY ? "[REPLAY]" : "", - test & WPA_TRIGGER_TX_REPLAY_FRAG ? - "[REPLAY FRAG]" : "", - test & WPA_TRIGGER_TX_SKIP_SEQ ? "[SKIP SEQ]" : ""); - } -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - if (!tx->key->force_sw_encrypt && !tx->local->conf.sw_decrypt && - !tx->local->hw->wep_include_iv && !wpa_test) { - /* hwaccel - with no need for preallocated room for IV/ICV */ - tx->u.tx.control->key_idx = tx->key->hw_key_idx; - return TXRX_CONTINUE; - } - - if (tkip_encrypt_skb(tx, skb, test) < 0) - return TXRX_DROP; - - if (tx->u.tx.extra_frag) { - int i; -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (test & WPA_TRIGGER_TX_REPLAY_FRAG) - test |= WPA_TRIGGER_TX_REPLAY; -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - for (i = 0; i < tx->u.tx.num_extra_frag; i++) { - if (tkip_encrypt_skb(tx, tx->u.tx.extra_frag[i], test) - < 0) - return TXRX_DROP; - } - } - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (tx->sta && tx->sta->wpa_trigger & WPA_TRIGGER_FAIL_TX_ICV) { - printk(KERN_INFO "%s: WPA testing - corrupting TX TKIP ICV " - "for STA " MACSTR "\n", - tx->dev->name, MAC2STR(tx->sta->addr)); - tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID; - tx->sta->wpa_trigger &= ~WPA_TRIGGER_FAIL_TX_ICV; - skb->data[skb->len - 1]++; - } else if (!tx->u.tx.unicast && - tx->local->wpa_trigger & WPA_TRIGGER_FAIL_TX_ICV) { - printk(KERN_INFO "%s: WPA testing - corrupting TX TKIP ICV " - "for Group Key\n", - tx->dev->name); - tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID; - tx->local->wpa_trigger &= ~WPA_TRIGGER_FAIL_TX_ICV; - skb->data[skb->len - 1]++; - } -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - return TXRX_CONTINUE; -} - - -ieee80211_txrx_result -ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - u16 fc; - int hdrlen, res, hwaccel = 0, wpa_test = 0; - struct ieee80211_key *key = rx->key; - struct sk_buff *skb = rx->skb; - - fc = le16_to_cpu(hdr->frame_control); - hdrlen = ieee80211_get_hdrlen(fc); - - if (!rx->key || rx->key->alg != ALG_TKIP || - !(rx->fc & WLAN_FC_ISWEP) || - WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_DATA) - return TXRX_CONTINUE; - - if (!rx->sta || skb->len - hdrlen < 12) - return TXRX_DROP; - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (rx->sta && rx->sta->wpa_trigger & WPA_TRIGGER_FAIL_RX_ICV) { - printk(KERN_INFO "%s: WPA testing - corrupting RX TKIP ICV " - "for STA " MACSTR "\n", - rx->dev->name, MAC2STR(rx->sta->addr)); - rx->sta->wpa_trigger &= ~WPA_TRIGGER_FAIL_RX_ICV; - skb->data[skb->len - 1]++; - wpa_test = 1; - } -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && - !rx->key->force_sw_encrypt && !rx->local->conf.sw_decrypt) { - if (!rx->local->hw->wep_include_iv) { - /* Hardware takes care of all processing, including - * replay protection, so no need to continue here. */ - return TXRX_CONTINUE; - } - - /* let TKIP code verify IV, but skip decryption */ - hwaccel = 1; - } - - res = ieee80211_tkip_decrypt_data(key, skb->data + hdrlen, - skb->len - hdrlen, rx->sta->addr, - hwaccel, rx->u.rx.queue); - if (res != TKIP_DECRYPT_OK || wpa_test) { - printk(KERN_DEBUG "%s: TKIP decrypt failed for RX frame from " - MACSTR " (res=%d)\n", - rx->dev->name, MAC2STR(rx->sta->addr), res); - return TXRX_DROP; - } - - /* Trim ICV */ - skb_trim(skb, skb->len - TKIP_ICV_LEN); - - /* Remove IV */ - memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen); - skb_pull(skb, TKIP_IV_LEN); - - return TXRX_CONTINUE; -} - - -static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, - int encrypted) -{ - u16 fc; - int a4_included, qos_included; - u8 qos_tid, *fc_pos, *data, *sa, *da; - int len_a; - size_t data_len; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - fc_pos = (u8 *) &hdr->frame_control; - fc = fc_pos[0] ^ (fc_pos[1] << 8); - a4_included = (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == - (WLAN_FC_TODS | WLAN_FC_FROMDS); - - ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len); - data_len -= CCMP_HDR_LEN + (encrypted ? CCMP_MIC_LEN : 0); - if (qos_tid & 0x80) { - qos_included = 1; - qos_tid &= 0x0f; - } else - qos_included = 0; - /* First block, b_0 */ - - b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ - /* Nonce: QoS Priority | A2 | PN */ - b_0[1] = qos_tid; - memcpy(&b_0[2], hdr->addr2, 6); - memcpy(&b_0[8], pn, CCMP_PN_LEN); - /* l(m) */ - b_0[14] = (data_len >> 8) & 0xff; - b_0[15] = data_len & 0xff; - - - /* AAD (extra authenticate-only data) / masked 802.11 header - * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ - - len_a = a4_included ? 28 : 22; - if (qos_included) - len_a += 2; - - aad[0] = 0; /* (len_a >> 8) & 0xff; */ - aad[1] = len_a & 0xff; - /* Mask FC: zero subtype b4 b5 b6 */ - aad[2] = fc_pos[0] & ~(BIT(4) | BIT(5) | BIT(6)); - /* Retry, PwrMgt, MoreData; set Protected */ - aad[3] = (fc_pos[1] & ~(BIT(3) | BIT(4) | BIT(5))) | BIT(6); - memcpy(&aad[4], &hdr->addr1, 18); - - /* Mask Seq#, leave Frag# */ - aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f; - aad[23] = 0; - if (a4_included) { - memcpy(&aad[24], hdr->addr4, 6); - aad[30] = 0; - aad[31] = 0; - } else - memset(&aad[24], 0, 8); - if (qos_included) { - u8 *dpos = &aad[a4_included ? 30 : 24]; - - /* Mask QoS Control field */ - dpos[0] = qos_tid; - dpos[1] = 0; - } -} - - -static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn, int key_id) -{ - hdr[0] = pn[5]; - hdr[1] = pn[4]; - hdr[2] = 0; - hdr[3] = 0x20 | (key_id << 6); - hdr[4] = pn[3]; - hdr[5] = pn[2]; - hdr[6] = pn[1]; - hdr[7] = pn[0]; -} - - -static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr) -{ - pn[0] = hdr[7]; - pn[1] = hdr[6]; - pn[2] = hdr[5]; - pn[3] = hdr[4]; - pn[4] = hdr[1]; - pn[5] = hdr[0]; - return (hdr[3] >> 6) & 0x03; -} - - -static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx, - struct sk_buff *skb, int test) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_key *key = tx->key; - int hdrlen, len, tailneed; - u16 fc; - u8 *pos, *pn; - u8 b_0[AES_BLOCK_LEN], aad[2 * AES_BLOCK_LEN]; - int i; - - fc = le16_to_cpu(hdr->frame_control); - hdrlen = ieee80211_get_hdrlen(fc); - len = skb->len - hdrlen; - - tailneed = (!tx->key->force_sw_encrypt && !tx->local->conf.sw_decrypt) - ? 0 : CCMP_MIC_LEN; - - if ((skb_headroom(skb) < CCMP_HDR_LEN || - skb_tailroom(skb) < tailneed)) { - I802_DEBUG_INC(tx->local->tx_expand_skb_head); - if (unlikely(pskb_expand_head(skb, CCMP_HDR_LEN, tailneed, - GFP_ATOMIC))) - return -1; - } - - pos = skb_push(skb, CCMP_HDR_LEN); - memmove(pos, pos + CCMP_HDR_LEN, hdrlen); - hdr = (struct ieee80211_hdr *) pos; - pos += hdrlen; - - /* PN = PN + 1 */ - pn = key->u.ccmp.tx_pn; - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (test & WPA_TRIGGER_TX_REPLAY) - goto skip_pn_inc; -pn_inc: -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - for (i = CCMP_PN_LEN - 1; i >= 0; i--) { - pn[i]++; - if (pn[i]) - break; - } - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (test & WPA_TRIGGER_TX_SKIP_SEQ) { - test = 0; - goto pn_inc; - } -skip_pn_inc: -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - ccmp_pn2hdr(pos, pn, key->keyidx); - - if (!tx->key->force_sw_encrypt && !tx->local->conf.sw_decrypt) { - /* hwaccel - with preallocated room for CCMP header */ - tx->u.tx.control->key_idx = tx->key->hw_key_idx; - return 0; - } - - pos += CCMP_HDR_LEN; - ccmp_special_blocks(skb, pn, b_0, aad, 0); - ieee80211_aes_ccm_encrypt(key->u.ccmp.aes_state, b_0, aad, pos, len, - pos, skb_put(skb, CCMP_MIC_LEN)); - - return 0; -} - - -ieee80211_txrx_result -ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; - struct ieee80211_key *key = tx->key; - u16 fc; - struct sk_buff *skb = tx->skb; - int test = 0; - - fc = le16_to_cpu(hdr->frame_control); - - if (!key || key->alg != ALG_CCMP || !WLAN_FC_DATA_PRESENT(fc)) - return TXRX_CONTINUE; - -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (tx->sta) { - test = tx->sta->wpa_trigger; - tx->sta->wpa_trigger = 0; - } else { - test = tx->local->wpa_trigger; - tx->local->wpa_trigger = 0; - } - if (test & - (WPA_TRIGGER_TX_REPLAY | WPA_TRIGGER_TX_REPLAY_FRAG | - WPA_TRIGGER_TX_SKIP_SEQ)) { - printk(KERN_INFO "%s: WPA testing - CCMP TX packet number " - "%s%s%s%s\n", tx->dev->name, - tx->sta ? "[UNICAST]" : "[MULTICAST]", - test & WPA_TRIGGER_TX_REPLAY ? "[REPLAY]" : "", - test & WPA_TRIGGER_TX_REPLAY_FRAG ? - "[REPLAY FRAG]" : "", - test & WPA_TRIGGER_TX_SKIP_SEQ ? "[SKIP SEQ]" : ""); - } -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - - tx->u.tx.control->icv_len = CCMP_MIC_LEN; - tx->u.tx.control->iv_len = CCMP_HDR_LEN; - ieee80211_tx_set_iswep(tx); - - if (!tx->key->force_sw_encrypt && !tx->local->conf.sw_decrypt && - !tx->local->hw->wep_include_iv) { - /* hwaccel - with no need for preallocated room for CCMP " - * header or MIC fields */ - tx->u.tx.control->key_idx = tx->key->hw_key_idx; - return TXRX_CONTINUE; - } - - if (ccmp_encrypt_skb(tx, skb, test) < 0) - return TXRX_DROP; - - if (tx->u.tx.extra_frag) { - int i; -#ifdef CONFIG_HOSTAPD_WPA_TESTING - if (test & WPA_TRIGGER_TX_REPLAY_FRAG) - test |= WPA_TRIGGER_TX_REPLAY; -#endif /* CONFIG_HOSTAPD_WPA_TESTING */ - for (i = 0; i < tx->u.tx.num_extra_frag; i++) { - if (ccmp_encrypt_skb(tx, tx->u.tx.extra_frag[i], test) - < 0) - return TXRX_DROP; - } - } - - return TXRX_CONTINUE; -} - - -ieee80211_txrx_result -ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - u16 fc; - int hdrlen; - struct ieee80211_key *key = rx->key; - struct sk_buff *skb = rx->skb; - u8 b_0[AES_BLOCK_LEN], aad[2 * AES_BLOCK_LEN]; - u8 pn[CCMP_PN_LEN]; - int data_len; - - fc = le16_to_cpu(hdr->frame_control); - hdrlen = ieee80211_get_hdrlen(fc); - - if (!rx->key || rx->key->alg != ALG_CCMP || - !(rx->fc & WLAN_FC_ISWEP) || - WLAN_FC_GET_TYPE(rx->fc) != WLAN_FC_TYPE_DATA) - return TXRX_CONTINUE; - - data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; - if (!rx->sta || data_len < 0) - return TXRX_DROP; - - if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && - !rx->key->force_sw_encrypt && !rx->local->conf.sw_decrypt && - !rx->local->hw->wep_include_iv) - return TXRX_CONTINUE; - - (void) ccmp_hdr2pn(pn, skb->data + hdrlen); - - if (memcmp(pn, key->u.ccmp.rx_pn[rx->u.rx.queue], CCMP_PN_LEN) <= 0) { -#ifdef CONFIG_IEEE80211_DEBUG - u8 *ppn = key->u.ccmp.rx_pn[rx->u.rx.queue]; - printk(KERN_DEBUG "%s: CCMP replay detected for RX frame from " - MACSTR " (RX PN %02x%02x%02x%02x%02x%02x <= prev. PN " - "%02x%02x%02x%02x%02x%02x)\n", rx->dev->name, - MAC2STR(rx->sta->addr), - pn[0], pn[1], pn[2], pn[3], pn[4], pn[5], - ppn[0], ppn[1], ppn[2], ppn[3], ppn[4], ppn[5]); -#endif /* CONFIG_IEEE80211_DEBUG */ - key->u.ccmp.replays++; - return TXRX_DROP; - } - - if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && - !rx->key->force_sw_encrypt && !rx->local->conf.sw_decrypt) { - /* hwaccel has already decrypted frame and verified MIC */ - } else { - ccmp_special_blocks(skb, pn, b_0, aad, 1); - - if (ieee80211_aes_ccm_decrypt( - key->u.ccmp.aes_state, b_0, aad, - skb->data + hdrlen + CCMP_HDR_LEN, data_len, - skb->data + skb->len - CCMP_MIC_LEN, - skb->data + hdrlen + CCMP_HDR_LEN)) { - printk(KERN_DEBUG "%s: CCMP decrypt failed for RX " - "frame from " MACSTR "\n", rx->dev->name, - MAC2STR(rx->sta->addr)); - return TXRX_DROP; - } - } - - memcpy(key->u.ccmp.rx_pn[rx->u.rx.queue], pn, CCMP_PN_LEN); - - /* Remove CCMP header and MIC */ - skb_trim(skb, skb->len - CCMP_MIC_LEN); - memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen); - skb_pull(skb, CCMP_HDR_LEN); - - return TXRX_CONTINUE; -} - diff --git a/target/linux/package/ieee80211-dscape/src/wpa.h b/target/linux/package/ieee80211-dscape/src/wpa.h deleted file mode 100644 index 9ad7c0813e..0000000000 --- a/target/linux/package/ieee80211-dscape/src/wpa.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2002-2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef WPA_H -#define WPA_H - -ieee80211_txrx_result -ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx); -ieee80211_txrx_result -ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx); - -ieee80211_txrx_result -ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx); -ieee80211_txrx_result -ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx); - -ieee80211_txrx_result -ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx); -ieee80211_txrx_result -ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx); - -int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da, - u8 *qos_tid, u8 **data, size_t *data_len); - -#endif /* WPA_H */ diff --git a/target/linux/package/madwifi/Config.in b/target/linux/package/madwifi/Config.in index 6eda342f81..168f1e7b8b 100644 --- a/target/linux/package/madwifi/Config.in +++ b/target/linux/package/madwifi/Config.in @@ -1,7 +1,7 @@ config PACKAGE_KMOD_MADWIFI prompt "kmod-madwifi...................... Atheros Wifi driver" tristate - default y if LINUX_2_6_BRCM || LINUX_2_6_ARUBA || LINUX_2_4_AR531X + default y if LINUX_2_6_BRCM || LINUX_2_6_ARUBA || LINUX_2_4_AR531X || LINUX_2_6_XSCALE default m if DEVEL default n help diff --git a/target/linux/package/madwifi/Makefile b/target/linux/package/madwifi/Makefile index d42372b52e..97cb0bd5e5 100644 --- a/target/linux/package/madwifi/Makefile +++ b/target/linux/package/madwifi/Makefile @@ -4,9 +4,9 @@ include $(TOPDIR)/rules.mk include ../../rules.mk PKG_NAME:=madwifi-ng -PKG_VERSION:=r1486-20060329 +PKG_VERSION:=r1543-20060506 PKG_RELEASE:=1 -PKG_MD5SUM:=71f1c654531ca8516bf7cdb5e80eb10f +PKG_MD5SUM:=3d89e5197c7e43eb37564c176140b2bf PKG_SOURCE_URL:=http://snapshots.madwifi.org/$(PKG_NAME) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz @@ -23,6 +23,9 @@ endif ifeq ($(ARCH),i386) HAL_TARGET:=i386-elf endif +ifeq ($(ARCH),armeb) +HAL_TARGET:=xscale-be-elf +endif BUS := PCI diff --git a/target/linux/package/madwifi/patches/100-kernel_cflags.patch b/target/linux/package/madwifi/patches/100-kernel_cflags.patch index 39aac7626a..b67183c384 100644 --- a/target/linux/package/madwifi/patches/100-kernel_cflags.patch +++ b/target/linux/package/madwifi/patches/100-kernel_cflags.patch @@ -30,3 +30,14 @@ diff -ru madwifi-ng-r1486-20060329/hal/public/mips-le-elf.inc madwifi-ng-r1486-2 -COPTS+= -G 0 -EL -mno-abicalls -fno-pic -Wa,--trap \ +COPTS+= -G 0 -EL -mno-abicalls -fno-pic -Wa,--trap -mips32 \ -fno-strict-aliasing -fno-common -fomit-frame-pointer -mlong-calls +diff -ur madwifi-ng-r1486-20060329/hal/public/xscale-be-elf.inc madwifi-ng-r1486-20060329-patch/hal/public/xscale-be-elf.inc +--- madwifi-ng-r1486-20060329/hal/public/xscale-be-elf.inc 2006-02-11 13:04:39.000000000 +0100 ++++ madwifi-ng-r1486-20060329-patch/hal/public/xscale-be-elf.inc 2006-04-16 15:07:59.000000000 +0200 +@@ -72,5 +72,5 @@ + + LDOPTS= -EB + COPTS+= -DAH_BYTE_ORDER=AH_BIG_ENDIAN -DAH_REGOPS_FUNC +-COPTS+= -march=armv4 -mbig-endian -fno-strict-aliasing -fno-common -mapcs-32 \ +- -mtune=xscale -mshort-load-bytes -msoft-float -mfp=2 ++COPTS+= -mcpu=xscale -mbig-endian -fno-strict-aliasing -fno-common \ ++ -msoft-float -mfp=2 diff --git a/target/linux/package/wlcompat/Config.in b/target/linux/package/wlcompat/Config.in index 904d1e6645..00774c1792 100644 --- a/target/linux/package/wlcompat/Config.in +++ b/target/linux/package/wlcompat/Config.in @@ -2,7 +2,7 @@ config PACKAGE_KMOD_WLCOMPAT prompt "kmod-wlcompat..................... Wrapper providing Wireless Extensions for Broadcom wl module" tristate default y - depends PACKAGE_KMOD_BRCM_WL || PACKAGE_KMOD_BRCM_WL2 + depends PACKAGE_KMOD_BRCM_WL help A wrapper module, that provides Wireless Extension support for the proprietary Broadcom wl module. @@ -11,7 +11,7 @@ config PACKAGE_KMOD_WLCOMPAT_DEBUG prompt "kmod-wlcompat-debug............... Wrapper providing Wireless Extensions for Broadcom wl module (debug)" tristate default m - depends PACKAGE_KMOD_BRCM_WL || PACKAGE_KMOD_BRCM_WL2 + depends PACKAGE_KMOD_BRCM_WL help A wrapper module, that provides Wireless Extension support for the proprietary Broadcom wl module. (debug version) diff --git a/target/linux/package/wlcompat/wlcompat.c b/target/linux/package/wlcompat/wlcompat.c index 7063c809a6..1540a21167 100644 --- a/target/linux/package/wlcompat/wlcompat.c +++ b/target/linux/package/wlcompat/wlcompat.c @@ -980,13 +980,13 @@ static int new_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { static int __init wlcompat_init() { int found = 0, i; - char *devname = "eth0"; + char devname[4] = "wl0"; bss_force = 0; while (!found && (dev = dev_get_by_name(devname))) { if ((dev->wireless_handlers == NULL) && ((wl_ioctl(dev, WLC_GET_MAGIC, &i, sizeof(i)) == 0) && i == WLC_IOCTL_MAGIC)) found = 1; - devname[3]++; + devname[2]++; } if (!found) { diff --git a/target/linux/rules.mk b/target/linux/rules.mk index 8490d110de..da32ed8b04 100644 --- a/target/linux/rules.mk +++ b/target/linux/rules.mk @@ -20,6 +20,7 @@ LINUX_KARCH:=$(shell echo $(ARCH) | sed -e 's/i[3-9]86/i386/' \ -e 's/mipseb/mips/' \ -e 's/powerpc/ppc/' \ -e 's/sh[234]/sh/' \ + -e 's/armeb/arm/' \ ) KPKG_MAKEOPTS:= IPKG="$(IPKG_KERNEL)" \ @@ -75,6 +76,11 @@ ifneq ($(6),) for module in $(7); do \ echo $$$$module >> $$(I_$(1))/etc/modules.d/$(6)-$(2); \ done + echo "#!/bin/sh" >> $$(I_$(1))/CONTROL/postinst + echo "[ -z \"\$$$$IPKG_INSTROOT\" ] || exit" >> $$(I_$(1))/CONTROL/postinst + echo ". /etc/functions.sh" >> $$(I_$(1))/CONTROL/postinst + echo "load_modules /etc/modules.d/$(6)-$(2)" >> $$(I_$(1))/CONTROL/postinst + chmod 0755 $$(I_$(1))/CONTROL/postinst endif $(8) $(IPKG_BUILD) $$(I_$(1)) $(PACKAGE_DIR) diff --git a/target/linux/sibyte-2.6/Makefile b/target/linux/sibyte-2.6/Makefile new file mode 100644 index 0000000000..3309a84e55 --- /dev/null +++ b/target/linux/sibyte-2.6/Makefile @@ -0,0 +1,19 @@ +include $(TOPDIR)/rules.mk + +LINUX_VERSION:=2.6.16.7 +LINUX_RELEASE:=1 +LINUX_KERNEL_MD5SUM:=9682b2bd6e02f3087982d7c3f5ba824e + +include ../rules.mk +include ./config + +include ../generic-$(KERNEL)/modules.mk +include ../kernel.mk + + +$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked + [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches + [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches + @$(CP) config $(LINUX_DIR)/.config + touch $@ + diff --git a/target/linux/sibyte-2.6/config b/target/linux/sibyte-2.6/config new file mode 100644 index 0000000000..221d833b89 --- /dev/null +++ b/target/linux/sibyte-2.6/config @@ -0,0 +1,1311 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.16.4 +# Fri Apr 21 16:08:33 2006 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MIPS_MTX1 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_3 is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_PNX8550_V2PCI is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_QEMU is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +CONFIG_SIBYTE_SWARM=y +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_PTSWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +CONFIG_SIBYTE_SB1250=y +CONFIG_SIBYTE_SB1xxx_SOC=y +# CONFIG_CPU_SB1_PASS_1 is not set +# CONFIG_CPU_SB1_PASS_2_1250 is not set +# CONFIG_CPU_SB1_PASS_2_2 is not set +CONFIG_CPU_SB1_PASS_4=y +# CONFIG_CPU_SB1_PASS_2_112x is not set +# CONFIG_CPU_SB1_PASS_3 is not set +CONFIG_SIBYTE_HAS_LDT=y +# CONFIG_SIMULATION is not set +# CONFIG_SB1_CEX_ALWAYS_FATAL is not set +# CONFIG_SB1_CERR_STALL is not set +CONFIG_SIBYTE_CFE=y +CONFIG_SIBYTE_CFE_CONSOLE=y +# CONFIG_SIBYTE_BUS_WATCHER is not set +# CONFIG_SIBYTE_SB1250_PROF is not set +# CONFIG_SIBYTE_TBPROF is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_DMA_COHERENT=y +CONFIG_CPU_BIG_ENDIAN=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_MIPS32_R1 is not set +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +CONFIG_CPU_SB1=y +CONFIG_SYS_HAS_CPU_SB1=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y + +# +# Kernel type +# +# CONFIG_32BIT is not set +CONFIG_64BIT=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_SIBYTE_DMA_PAGEOPS is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_MIPS_MT is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_SYS_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_PREEMPT_BKL is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_INITRAMFS_SOURCE="../root" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_SLAB is not set +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_SLOB=y +CONFIG_OBSOLETE_INTERMODULE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set +CONFIG_STOP_MACHINE=y + +# +# Block layer +# + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +# CONFIG_PCI_LEGACY_PROC is not set +CONFIG_MMU=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_BUILD_ELF64=y +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +# CONFIG_NET_IPGRE_BROADCAST is not set +CONFIG_IPSEC_NAT_TRAVERSAL=y +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=y +CONFIG_TCP_CONG_SCALABLE=m + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_IPV6_TUNNEL is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_BRIDGE_NETFILTER is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +CONFIG_NETFILTER_XTABLES=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_STATE=y +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=y +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=y +CONFIG_IP_NF_IRC=y +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_LAYER7=m +# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_IPP2P=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_TIME=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_HASHLIMIT is not set +# CONFIG_IP_NF_MATCH_POLICY is not set +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_TARGET_IMQ=m +# CONFIG_IP_NF_TARGET_LOG is not set +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_REDIRECT=y +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_SAME is not set +# CONFIG_IP_NF_NAT_SNMP_BASIC is not set +CONFIG_IP_NF_NAT_IRC=y +CONFIG_IP_NF_NAT_FTP=y +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_SIP=m +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_TTL=m +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_ARPTABLES is not set +CONFIG_IP_NF_SET=m +CONFIG_IP_NF_SET_MAX=256 +CONFIG_IP_NF_SET_HASHSIZE=1024 +CONFIG_IP_NF_SET_IPMAP=m +CONFIG_IP_NF_SET_MACIPMAP=m +CONFIG_IP_NF_SET_PORTMAP=m +CONFIG_IP_NF_SET_IPHASH=m +CONFIG_IP_NF_SET_NETHASH=m +CONFIG_IP_NF_SET_IPTREE=m +CONFIG_IP_NF_MATCH_SET=m +CONFIG_IP_NF_TARGET_SET=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_HL is not set +CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OWNER=m +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_AHESP is not set +CONFIG_IP6_NF_MATCH_EUI64=m +# CONFIG_IP6_NF_MATCH_POLICY is not set +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_IMQ=m +# CONFIG_IP6_NF_TARGET_LOG is not set +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +# CONFIG_IP6_NF_TARGET_HL is not set +# CONFIG_IP6_NF_RAW is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +CONFIG_ATM_CLIP_NO_ICMP=y +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CLK_JIFFIES=y +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_ESFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +# CONFIG_NET_SCH_NETEM is not set +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +# CONFIG_CLS_U32_PERF is not set +# CONFIG_CLS_U32_MARK is not set +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_POLICE=y +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +CONFIG_AX25=m +# CONFIG_AX25_DAMA_SLAVE is not set +# CONFIG_NETROM is not set +# CONFIG_ROSE is not set + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +# CONFIG_6PACK is not set +# CONFIG_BPQETHER is not set +# CONFIG_BAYCOM_SER_FDX is not set +# CONFIG_BAYCOM_SER_HDX is not set +# CONFIG_YAM is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=m + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_AMDSTD_RETRY=0 +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_IMQ=m +# CONFIG_IMQ_BEHAVIOR_AA is not set +# CONFIG_IMQ_BEHAVIOR_AB is not set +CONFIG_IMQ_BEHAVIOR_BA=y +# CONFIG_IMQ_BEHAVIOR_BB is not set +CONFIG_IMQ_NUM_DEVS=2 +CONFIG_TUN=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_NET_SB1250_MAC=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_DM9000 is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +# CONFIG_PRISM54 is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +# CONFIG_HOSTAP_PLX is not set +# CONFIG_HOSTAP_PCI is not set +CONFIG_NET_WIRELESS=y + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +CONFIG_ATM_DUMMY=m +CONFIG_ATM_TCP=m +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_FORE200E_MAYBE is not set +# CONFIG_ATM_HE is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=m + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_SYNCLINK_GT is not set +# CONFIG_N_HDLC is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_STALDRV is not set +CONFIG_SIBYTE_SB1250_DUART=y +CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y +# CONFIG_AU1000_UART is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# File systems +# +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_REISERFS_FS_XATTR is not set +CONFIG_JFS_FS=m +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_XFS_FS=m +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_SECURITY is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_OCFS2_FS is not set +CONFIG_MINIX_FS=m +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=m +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_SB1XXX_CORELIS is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/target/linux/sibyte-2.6/patches/000-DUART.patch b/target/linux/sibyte-2.6/patches/000-DUART.patch new file mode 100644 index 0000000000..480287ffa0 --- /dev/null +++ b/target/linux/sibyte-2.6/patches/000-DUART.patch @@ -0,0 +1,956 @@ +--- linux-2.6.16.7/drivers/char/Kconfig 2006-04-21 14:38:30.000000000 -0700 ++++ linux-2.6.16.7/drivers/char/Kconfig 2006-04-21 14:39:29.000000000 -0700 +@@ -340,6 +340,14 @@ + To compile this driver as a module, choose M here: the + module will be called istallion. + ++config SIBYTE_SB1250_DUART ++ bool "Support for BCM1xxx onchip DUART" ++ depends on MIPS && SIBYTE_SB1xxx_SOC=y ++ ++config SIBYTE_SB1250_DUART_CONSOLE ++ bool "Console on BCM1xxx DUART" ++ depends on SIBYTE_SB1250_DUART ++ + config AU1000_UART + bool "Enable Au1000 UART Support" + depends on SERIAL_NONSTANDARD && MIPS +diff -Nurb linux-2.6.16.7/drivers/char/Makefile linux-2.6.16.7/drivers/char/Makefile +--- linux-2.6.16.7/drivers/char/Makefile 2006-04-17 14:53:25.000000000 -0700 ++++ linux-2.6.16.7/drivers/char/Makefile 2006-04-28 12:14:24.000000000 -0700 +@@ -31,6 +31,7 @@ + obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o + obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o + obj-$(CONFIG_MOXA_SMARTIO) += mxser.o ++obj-$(CONFIG_SIBYTE_SB1250_DUART) += sb1250_duart.o + obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o + obj-$(CONFIG_RISCOM8) += riscom8.o + obj-$(CONFIG_ISI) += isicom.o +diff -Nurb linux-2.6.16.7/drivers/char/sb1250_duart.c linux-2.6.16.7/drivers/char/sb1250_duart.c +--- linux-2.6.16.7/drivers/char/sb1250_duart.c 1969-12-31 16:00:00.000000000 -0800 ++++ linux-2.6.16.7/drivers/char/sb1250_duart.c 2006-04-28 12:13:49.000000000 -0700 +@@ -0,0 +1,911 @@ ++/* ++ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++/* ++ * Driver support for the on-chip sb1250 dual-channel serial port, ++ * running in asynchronous mode. Also, support for doing a serial console ++ * on one of those ports ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) ++#include ++#include ++#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) ++#include ++#include ++#else ++#error invalid SiByte UART configuation ++#endif ++#include ++#include ++ ++#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) ++#define UNIT_CHANREG(n,reg) A_BCM1480_DUART_CHANREG((n),(reg)) ++#define UNIT_IMRREG(n) A_BCM1480_DUART_IMRREG(n) ++#define UNIT_INT(n) (K_BCM1480_INT_UART_0 + (n)) ++#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) ++#define UNIT_CHANREG(n,reg) A_DUART_CHANREG((n),(reg)) ++#define UNIT_IMRREG(n) A_DUART_IMRREG(n) ++#define UNIT_INT(n) (K_INT_UART_0 + (n)) ++#else ++#error invalid SiByte UART configuation ++#endif ++ ++/* Toggle spewing of debugging output */ ++#undef DEBUG ++ ++#define DEFAULT_CFLAGS (CS8 | B115200) ++ ++#define TX_INTEN 1 ++#define DUART_INITIALIZED 2 ++ ++#define DUART_MAX_LINE 4 ++char sb1250_duart_present[DUART_MAX_LINE]; ++EXPORT_SYMBOL(sb1250_duart_present); ++ ++/* ++ * Still not sure what the termios structures set up here are for, ++ * but we have to supply pointers to them to register the tty driver ++ */ ++static struct tty_driver *sb1250_duart_driver; //, sb1250_duart_callout_driver; ++ ++/* ++ * This lock protects both the open flags for all the uart states as ++ * well as the reference count for the module ++ */ ++static DEFINE_SPINLOCK(open_lock); ++ ++typedef struct { ++ unsigned char outp_buf[SERIAL_XMIT_SIZE]; ++ unsigned int outp_head; ++ unsigned int outp_tail; ++ unsigned int outp_count; ++ spinlock_t outp_lock; ++ unsigned int open; ++ unsigned int line; ++ unsigned int last_cflags; ++ unsigned long flags; ++ struct tty_struct *tty; ++ /* CSR addresses */ ++ volatile u32 *status; ++ volatile u32 *imr; ++ volatile u32 *tx_hold; ++ volatile u32 *rx_hold; ++ volatile u32 *mode_1; ++ volatile u32 *mode_2; ++ volatile u32 *clk_sel; ++ volatile u32 *cmd; ++} uart_state_t; ++ ++static uart_state_t uart_states[DUART_MAX_LINE]; ++ ++/* ++ * Inline functions local to this module ++ */ ++ ++/* ++ * In bug 1956, we get glitches that can mess up uart registers. This ++ * "write-mode-1 after any register access" is the accepted ++ * workaround. ++ */ ++#if SIBYTE_1956_WAR ++static unsigned int last_mode1[DUART_MAX_LINE]; ++#endif ++ ++static inline u32 READ_SERCSR(volatile u32 *addr, int line) ++{ ++ u32 val = csr_in32(addr); ++#if SIBYTE_1956_WAR ++ csr_out32(last_mode1[line], uart_states[line].mode_1); ++#endif ++ return val; ++} ++ ++static inline void WRITE_SERCSR(u32 val, volatile u32 *addr, int line) ++{ ++ csr_out32(val, addr); ++#if SIBYTE_1956_WAR ++ csr_out32(last_mode1[line], uart_states[line].mode_1); ++#endif ++} ++ ++static void init_duart_port(uart_state_t *port, int line) ++{ ++ if (!(port->flags & DUART_INITIALIZED)) { ++ port->line = line; ++ port->status = IOADDR(UNIT_CHANREG(line, R_DUART_STATUS)); ++ port->imr = IOADDR(UNIT_IMRREG(line)); ++ port->tx_hold = IOADDR(UNIT_CHANREG(line, R_DUART_TX_HOLD)); ++ port->rx_hold = IOADDR(UNIT_CHANREG(line, R_DUART_RX_HOLD)); ++ port->mode_1 = IOADDR(UNIT_CHANREG(line, R_DUART_MODE_REG_1)); ++ port->mode_2 = IOADDR(UNIT_CHANREG(line, R_DUART_MODE_REG_2)); ++ port->clk_sel = IOADDR(UNIT_CHANREG(line, R_DUART_CLK_SEL)); ++ port->cmd = IOADDR(UNIT_CHANREG(line, R_DUART_CMD)); ++ port->flags |= DUART_INITIALIZED; ++ } ++} ++ ++/* ++ * Mask out the passed interrupt lines at the duart level. This should be ++ * called while holding the associated outp_lock. ++ */ ++static inline void duart_mask_ints(unsigned int line, unsigned int mask) ++{ ++ uart_state_t *port = uart_states + line; ++ u64 tmp = READ_SERCSR(port->imr, line); ++ WRITE_SERCSR(tmp & ~mask, port->imr, line); ++} ++ ++ ++/* Unmask the passed interrupt lines at the duart level */ ++static inline void duart_unmask_ints(unsigned int line, unsigned int mask) ++{ ++ uart_state_t *port = uart_states + line; ++ u64 tmp = READ_SERCSR(port->imr, line); ++ WRITE_SERCSR(tmp | mask, port->imr, line); ++} ++ ++static inline void transmit_char_pio(uart_state_t *us) ++{ ++ struct tty_struct *tty = us->tty; ++ int blocked = 0; ++ ++ if (spin_trylock(&us->outp_lock)) { ++ for (;;) { ++ if (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_RDY)) ++ break; ++ if (us->outp_count <= 0 || tty->stopped || tty->hw_stopped) { ++ break; ++ } else { ++ WRITE_SERCSR(us->outp_buf[us->outp_head], ++ us->tx_hold, us->line); ++ us->outp_head = (us->outp_head + 1) & (SERIAL_XMIT_SIZE-1); ++ if (--us->outp_count <= 0) ++ break; ++ } ++ udelay(10); ++ } ++ spin_unlock(&us->outp_lock); ++ } else { ++ blocked = 1; ++ } ++ ++ if (!us->outp_count || tty->stopped || ++ tty->hw_stopped || blocked) { ++ us->flags &= ~TX_INTEN; ++ duart_mask_ints(us->line, M_DUART_IMR_TX); ++ } ++ ++ if (us->open && ++ (us->outp_count < (SERIAL_XMIT_SIZE/2))) { ++ /* ++ * We told the discipline at one point that we had no ++ * space, so it went to sleep. Wake it up when we hit ++ * half empty ++ */ ++ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && ++ tty->ldisc.write_wakeup) ++ tty->ldisc.write_wakeup(tty); ++ wake_up_interruptible(&tty->write_wait); ++ } ++} ++ ++/* ++ * Generic interrupt handler for both channels. dev_id is a pointer ++ * to the proper uart_states structure, so from that we can derive ++ * which port interrupted ++ */ ++ ++static irqreturn_t duart_int(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ uart_state_t *us = (uart_state_t *)dev_id; ++ struct tty_struct *tty = us->tty; ++ unsigned int status = READ_SERCSR(us->status, us->line); ++ ++ pr_debug("DUART INT\n"); ++ ++ if (status & M_DUART_RX_RDY) { ++ int counter = 2048; ++ unsigned int ch; ++ ++ if (status & M_DUART_OVRUN_ERR) ++ tty_insert_flip_char(tty, 0, TTY_OVERRUN); ++ if (status & M_DUART_PARITY_ERR) { ++ printk("Parity error!\n"); ++ } else if (status & M_DUART_FRM_ERR) { ++ printk("Frame error!\n"); ++ } ++ ++ while (counter > 0) { ++ if (!(READ_SERCSR(us->status, us->line) & M_DUART_RX_RDY)) ++ break; ++ ch = READ_SERCSR(us->rx_hold, us->line); ++ tty_insert_flip_char(tty, ch, 0); ++ udelay(1); ++ counter--; ++ } ++ tty_flip_buffer_push(tty); ++ } ++ ++ if (status & M_DUART_TX_RDY) { ++ transmit_char_pio(us); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Actual driver functions ++ */ ++ ++/* Return the number of characters we can accomodate in a write at this instant */ ++static int duart_write_room(struct tty_struct *tty) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ int retval; ++ ++ retval = SERIAL_XMIT_SIZE - us->outp_count; ++ ++ pr_debug("duart_write_room called, returning %i\n", retval); ++ ++ return retval; ++} ++ ++/* memcpy the data from src to destination, but take extra care if the ++ data is coming from user space */ ++static inline int copy_buf(char *dest, const char *src, int size, int from_user) ++{ ++ if (from_user) { ++ (void) copy_from_user(dest, src, size); ++ } else { ++ memcpy(dest, src, size); ++ } ++ return size; ++} ++ ++/* ++ * Buffer up to count characters from buf to be written. If we don't have ++ * other characters buffered, enable the tx interrupt to start sending ++ */ ++static int duart_write(struct tty_struct *tty, const unsigned char *buf, ++ int count) ++{ ++ uart_state_t *us; ++ int c, t, total = 0; ++ unsigned long flags; ++ ++ if (!tty) return 0; ++ ++ us = tty->driver_data; ++ if (!us) return 0; ++ ++ pr_debug("duart_write called for %i chars by %i (%s)\n", count, current->pid, current->comm); ++ ++ spin_lock_irqsave(&us->outp_lock, flags); ++ ++ for (;;) { ++ c = count; ++ ++ t = SERIAL_XMIT_SIZE - us->outp_tail; ++ if (t < c) c = t; ++ ++ t = SERIAL_XMIT_SIZE - 1 - us->outp_count; ++ if (t < c) c = t; ++ ++ if (c <= 0) break; ++ ++ memcpy(us->outp_buf + us->outp_tail, buf, c); ++ ++ us->outp_count += c; ++ us->outp_tail = (us->outp_tail + c) & (SERIAL_XMIT_SIZE - 1); ++ buf += c; ++ count -= c; ++ total += c; ++ } ++ ++ spin_unlock_irqrestore(&us->outp_lock, flags); ++ ++ if (us->outp_count && !tty->stopped && ++ !tty->hw_stopped && !(us->flags & TX_INTEN)) { ++ us->flags |= TX_INTEN; ++ duart_unmask_ints(us->line, M_DUART_IMR_TX); ++ } ++ ++ return total; ++} ++ ++ ++/* Buffer one character to be written. If there's not room for it, just drop ++ it on the floor. This is used for echo, among other things */ ++static void duart_put_char(struct tty_struct *tty, u_char ch) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ unsigned long flags; ++ ++ pr_debug("duart_put_char called. Char is %x (%c)\n", (int)ch, ch); ++ ++ spin_lock_irqsave(&us->outp_lock, flags); ++ ++ if (us->outp_count == SERIAL_XMIT_SIZE) { ++ spin_unlock_irqrestore(&us->outp_lock, flags); ++ return; ++ } ++ ++ us->outp_buf[us->outp_tail] = ch; ++ us->outp_tail = (us->outp_tail + 1) &(SERIAL_XMIT_SIZE-1); ++ us->outp_count++; ++ ++ spin_unlock_irqrestore(&us->outp_lock, flags); ++} ++ ++static void duart_flush_chars(struct tty_struct * tty) ++{ ++ uart_state_t *port; ++ ++ if (!tty) return; ++ ++ port = tty->driver_data; ++ ++ if (!port) return; ++ ++ if (port->outp_count <= 0 || tty->stopped || tty->hw_stopped) { ++ return; ++ } ++ ++ port->flags |= TX_INTEN; ++ duart_unmask_ints(port->line, M_DUART_IMR_TX); ++} ++ ++/* Return the number of characters in the output buffer that have yet to be ++ written */ ++static int duart_chars_in_buffer(struct tty_struct *tty) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ int retval; ++ ++ retval = us->outp_count; ++ ++ pr_debug("duart_chars_in_buffer returning %i\n", retval); ++ ++ return retval; ++} ++ ++/* Kill everything we haven't yet shoved into the FIFO. Turn off the ++ transmit interrupt since we've nothing more to transmit */ ++static void duart_flush_buffer(struct tty_struct *tty) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ unsigned long flags; ++ ++ pr_debug("duart_flush_buffer called\n"); ++ spin_lock_irqsave(&us->outp_lock, flags); ++ us->outp_head = us->outp_tail = us->outp_count = 0; ++ spin_unlock_irqrestore(&us->outp_lock, flags); ++ ++ wake_up_interruptible(&us->tty->write_wait); ++ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && ++ tty->ldisc.write_wakeup) ++ tty->ldisc.write_wakeup(tty); ++} ++ ++ ++/* See sb1250 user manual for details on these registers */ ++static inline void duart_set_cflag(unsigned int line, unsigned int cflag) ++{ ++ unsigned int mode_reg1 = 0, mode_reg2 = 0; ++ unsigned int clk_divisor; ++ uart_state_t *port = uart_states + line; ++ ++ switch (cflag & CSIZE) { ++ case CS7: ++ mode_reg1 |= V_DUART_BITS_PER_CHAR_7; ++ ++ default: ++ /* We don't handle CS5 or CS6...is there a way we're supposed to flag this? ++ right now we just force them to CS8 */ ++ mode_reg1 |= 0x0; ++ break; ++ } ++ if (cflag & CSTOPB) { ++ mode_reg2 |= M_DUART_STOP_BIT_LEN_2; ++ } ++ if (!(cflag & PARENB)) { ++ mode_reg1 |= V_DUART_PARITY_MODE_NONE; ++ } ++ if (cflag & PARODD) { ++ mode_reg1 |= M_DUART_PARITY_TYPE_ODD; ++ } ++ ++ /* Formula for this is (5000000/baud)-1, but we saturate ++ at 12 bits, which means we can't actually do anything less ++ that 1200 baud */ ++ switch (cflag & CBAUD) { ++ case B200: ++ case B300: ++ case B1200: clk_divisor = 4095; break; ++ case B1800: clk_divisor = 2776; break; ++ case B2400: clk_divisor = 2082; break; ++ case B4800: clk_divisor = 1040; break; ++ default: ++ case B9600: clk_divisor = 519; break; ++ case B19200: clk_divisor = 259; break; ++ case B38400: clk_divisor = 129; break; ++ case B57600: clk_divisor = 85; break; ++ case B115200: clk_divisor = 42; break; ++ } ++ WRITE_SERCSR(mode_reg1, port->mode_1, port->line); ++ WRITE_SERCSR(mode_reg2, port->mode_2, port->line); ++ WRITE_SERCSR(clk_divisor, port->clk_sel, port->line); ++ port->last_cflags = cflag; ++} ++ ++ ++/* Handle notification of a termios change. */ ++static void duart_set_termios(struct tty_struct *tty, struct termios *old) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ ++ pr_debug("duart_set_termios called by %i (%s)\n", current->pid, current->comm); ++ if (old && tty->termios->c_cflag == old->c_cflag) ++ return; ++ duart_set_cflag(us->line, tty->termios->c_cflag); ++} ++ ++static int get_serial_info(uart_state_t *us, struct serial_struct * retinfo) { ++ ++ struct serial_struct tmp; ++ ++ memset(&tmp, 0, sizeof(tmp)); ++ ++ tmp.type=PORT_SB1250; ++ tmp.line=us->line; ++ tmp.port=UNIT_CHANREG(tmp.line,0); ++ tmp.irq=UNIT_INT(tmp.line); ++ tmp.xmit_fifo_size=16; /* fixed by hw */ ++ tmp.baud_base=5000000; ++ tmp.io_type=SERIAL_IO_MEM; ++ ++ if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static int duart_ioctl(struct tty_struct *tty, struct file * file, ++ unsigned int cmd, unsigned long arg) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ ++/* if (serial_paranoia_check(info, tty->device, "rs_ioctl")) ++ return -ENODEV;*/ ++ switch (cmd) { ++ case TIOCMGET: ++ printk("Ignoring TIOCMGET\n"); ++ break; ++ case TIOCMBIS: ++ printk("Ignoring TIOCMBIS\n"); ++ break; ++ case TIOCMBIC: ++ printk("Ignoring TIOCMBIC\n"); ++ break; ++ case TIOCMSET: ++ printk("Ignoring TIOCMSET\n"); ++ break; ++ case TIOCGSERIAL: ++ return get_serial_info(us,(struct serial_struct *) arg); ++ case TIOCSSERIAL: ++ printk("Ignoring TIOCSSERIAL\n"); ++ break; ++ case TIOCSERCONFIG: ++ printk("Ignoring TIOCSERCONFIG\n"); ++ break; ++ case TIOCSERGETLSR: /* Get line status register */ ++ printk("Ignoring TIOCSERGETLSR\n"); ++ break; ++ case TIOCSERGSTRUCT: ++ printk("Ignoring TIOCSERGSTRUCT\n"); ++ break; ++ case TIOCMIWAIT: ++ printk("Ignoring TIOCMIWAIT\n"); ++ break; ++ case TIOCGICOUNT: ++ printk("Ignoring TIOCGICOUNT\n"); ++ break; ++ case TIOCSERGWILD: ++ printk("Ignoring TIOCSERGWILD\n"); ++ break; ++ case TIOCSERSWILD: ++ printk("Ignoring TIOCSERSWILD\n"); ++ break; ++ default: ++ break; ++ } ++// printk("Ignoring IOCTL %x from pid %i (%s)\n", cmd, current->pid, current->comm); ++ return -ENOIOCTLCMD; ++} ++ ++/* XXXKW locking? */ ++static void duart_start(struct tty_struct *tty) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ ++ pr_debug("duart_start called\n"); ++ ++ if (us->outp_count && !(us->flags & TX_INTEN)) { ++ us->flags |= TX_INTEN; ++ duart_unmask_ints(us->line, M_DUART_IMR_TX); ++ } ++} ++ ++/* XXXKW locking? */ ++static void duart_stop(struct tty_struct *tty) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ ++ pr_debug("duart_stop called\n"); ++ ++ if (us->outp_count && (us->flags & TX_INTEN)) { ++ us->flags &= ~TX_INTEN; ++ duart_mask_ints(us->line, M_DUART_IMR_TX); ++ } ++} ++ ++/* Not sure on the semantics of this; are we supposed to wait until the stuff ++ already in the hardware FIFO drains, or are we supposed to wait until ++ we've drained the output buffer, too? I'm assuming the former, 'cause thats ++ what the other drivers seem to assume ++*/ ++ ++static void duart_wait_until_sent(struct tty_struct *tty, int timeout) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ unsigned long orig_jiffies; ++ ++ orig_jiffies = jiffies; ++ pr_debug("duart_wait_until_sent(%d)+\n", timeout); ++ while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT)) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(1); ++ if (signal_pending(current)) ++ break; ++ if (timeout && time_after(jiffies, orig_jiffies + timeout)) ++ break; ++ } ++ pr_debug("duart_wait_until_sent()-\n"); ++} ++ ++/* ++ * duart_hangup() --- called by tty_hangup() when a hangup is signaled. ++ */ ++static void duart_hangup(struct tty_struct *tty) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ ++ duart_flush_buffer(tty); ++ us->open = 0; ++ us->tty = 0; ++} ++ ++/* ++ * Open a tty line. Note that this can be called multiple times, so ->open can ++ * be >1. Only set up the tty struct if this is a "new" open, e.g. ->open was ++ * zero ++ */ ++static int duart_open(struct tty_struct *tty, struct file *filp) ++{ ++ uart_state_t *us; ++ unsigned int line = tty->index; ++ unsigned long flags; ++ ++ if ((line >= tty->driver->num) || !sb1250_duart_present[line]) ++ return -ENODEV; ++ ++ pr_debug("duart_open called by %i (%s), tty is %p, rw is %p, ww is %p\n", ++ current->pid, current->comm, tty, tty->read_wait, ++ tty->write_wait); ++ ++ us = uart_states + line; ++ tty->driver_data = us; ++ ++ spin_lock_irqsave(&open_lock, flags); ++ if (!us->open) { ++ us->tty = tty; ++ us->tty->termios->c_cflag = us->last_cflags; ++ } ++ us->open++; ++ us->flags &= ~TX_INTEN; ++ duart_unmask_ints(line, M_DUART_IMR_RX); ++ spin_unlock_irqrestore(&open_lock, flags); ++ ++ return 0; ++} ++ ++ ++/* ++ * Close a reference count out. If reference count hits zero, null the ++ * tty, kill the interrupts. The tty_io driver is responsible for making ++ * sure we've cleared out our internal buffers before calling close() ++ */ ++static void duart_close(struct tty_struct *tty, struct file *filp) ++{ ++ uart_state_t *us = (uart_state_t *) tty->driver_data; ++ unsigned long flags; ++ ++ pr_debug("duart_close called by %i (%s)\n", current->pid, current->comm); ++ ++ if (!us || !us->open) ++ return; ++ ++ spin_lock_irqsave(&open_lock, flags); ++ if (tty_hung_up_p(filp)) { ++ spin_unlock_irqrestore(&open_lock, flags); ++ return; ++ } ++ ++ if (--us->open < 0) { ++ us->open = 0; ++ printk(KERN_ERR "duart: bad open count: %d\n", us->open); ++ } ++ if (us->open) { ++ spin_unlock_irqrestore(&open_lock, flags); ++ return; ++ } ++ ++ spin_unlock_irqrestore(&open_lock, flags); ++ ++ tty->closing = 1; ++ ++ /* Stop accepting input */ ++ duart_mask_ints(us->line, M_DUART_IMR_RX); ++ /* Wait for FIFO to drain */ ++ while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT)) ++ ; ++ ++ if (tty->driver->flush_buffer) ++ tty->driver->flush_buffer(tty); ++ if (tty->ldisc.flush_buffer) ++ tty->ldisc.flush_buffer(tty); ++ tty->closing = 0; ++} ++ ++ ++static struct tty_operations duart_ops = { ++ .open = duart_open, ++ .close = duart_close, ++ .write = duart_write, ++ .put_char = duart_put_char, ++ .flush_chars = duart_flush_chars, ++ .write_room = duart_write_room, ++ .chars_in_buffer = duart_chars_in_buffer, ++ .flush_buffer = duart_flush_buffer, ++ .ioctl = duart_ioctl, ++// .throttle = duart_throttle, ++// .unthrottle = duart_unthrottle, ++ .set_termios = duart_set_termios, ++ .stop = duart_stop, ++ .start = duart_start, ++ .hangup = duart_hangup, ++ .wait_until_sent = duart_wait_until_sent, ++}; ++ ++/* Initialize the sb1250_duart_present array based on SOC type. */ ++static void __init sb1250_duart_init_present_lines(void) ++{ ++ int i, max_lines; ++ ++ /* Set the number of available units based on the SOC type. */ ++ switch (soc_type) { ++ case K_SYS_SOC_TYPE_BCM1x55: ++ case K_SYS_SOC_TYPE_BCM1x80: ++ max_lines = 4; ++ break; ++ default: ++ /* Assume at least two serial ports at the normal address. */ ++ max_lines = 2; ++ break; ++ } ++ if (max_lines > DUART_MAX_LINE) ++ max_lines = DUART_MAX_LINE; ++ ++ for (i = 0; i < max_lines; i++) ++ sb1250_duart_present[i] = 1; ++} ++ ++/* Set up the driver and register it, register the UART interrupts. This ++ is called from tty_init, or as a part of the module init */ ++static int __init sb1250_duart_init(void) ++{ ++ int i; ++ ++ sb1250_duart_init_present_lines(); ++ ++ sb1250_duart_driver = alloc_tty_driver(DUART_MAX_LINE); ++ if (!sb1250_duart_driver) ++ return -ENOMEM; ++ ++ sb1250_duart_driver->owner = THIS_MODULE; ++ sb1250_duart_driver->name = "duart"; ++ sb1250_duart_driver->devfs_name = "duart/"; ++ sb1250_duart_driver->major = TTY_MAJOR; ++ sb1250_duart_driver->minor_start = SB1250_DUART_MINOR_BASE; ++ sb1250_duart_driver->type = TTY_DRIVER_TYPE_SERIAL; ++ sb1250_duart_driver->subtype = SERIAL_TYPE_NORMAL; ++ sb1250_duart_driver->init_termios = tty_std_termios; ++ sb1250_duart_driver->flags = TTY_DRIVER_REAL_RAW; ++ tty_set_operations(sb1250_duart_driver, &duart_ops); ++ ++ for (i=0; ioutp_lock); ++ duart_mask_ints(i, M_DUART_IMR_ALL); ++ if (request_irq(UNIT_INT(i), duart_int, 0, "uart", port)) { ++ panic("Couldn't get uart0 interrupt line"); ++ } ++ __raw_writeq(M_DUART_RX_EN|M_DUART_TX_EN, ++ IOADDR(UNIT_CHANREG(i, R_DUART_CMD))); ++ duart_set_cflag(i, DEFAULT_CFLAGS); ++ } ++ ++ /* Interrupts are now active, our ISR can be called. */ ++ ++ if (tty_register_driver(sb1250_duart_driver)) { ++ printk(KERN_ERR "Couldn't register sb1250 duart serial driver\n"); ++ put_tty_driver(sb1250_duart_driver); ++ return 1; ++ } ++ return 0; ++} ++ ++/* Unload the driver. Unregister stuff, get ready to go away */ ++static void __exit sb1250_duart_fini(void) ++{ ++ unsigned long flags; ++ int i; ++ ++ local_irq_save(flags); ++ tty_unregister_driver(sb1250_duart_driver); ++ put_tty_driver(sb1250_duart_driver); ++ ++ for (i=0; istatus, line) & M_DUART_TX_RDY)) ; ++ WRITE_SERCSR(c, port->tx_hold, line); ++ while (!(READ_SERCSR(port->status, port->line) & M_DUART_TX_EMT)) ; ++} ++ ++static void ser_console_write(struct console *cons, const char *s, ++ unsigned int count) ++{ ++ int line = cons->index; ++ uart_state_t *port = uart_states + line; ++ u32 imr; ++ ++ imr = READ_SERCSR(port->imr, line); ++ WRITE_SERCSR(0, port->imr, line); ++ while (count--) { ++ if (*s == '\n') ++ serial_outc('\r', line); ++ serial_outc(*s++, line); ++ } ++ WRITE_SERCSR(imr, port->imr, line); ++} ++ ++static struct tty_driver *ser_console_device(struct console *c, int *index) ++{ ++ *index = c->index; ++ return sb1250_duart_driver; ++} ++ ++static int ser_console_setup(struct console *cons, char *str) ++{ ++ int i; ++ ++ sb1250_duart_init_present_lines(); ++ ++ for (i=0; imode_1, i); ++ WRITE_SERCSR(M_DUART_STOP_BIT_LEN_1, ++ port->mode_2, i); ++ WRITE_SERCSR(V_DUART_BAUD_RATE(115200), ++ port->clk_sel, i); ++ WRITE_SERCSR(M_DUART_RX_EN|M_DUART_TX_EN, ++ port->cmd, i); ++ } ++ return 0; ++} ++ ++static struct console sb1250_ser_cons = { ++ .name = "duart", ++ .write = ser_console_write, ++ .device = ser_console_device, ++ .setup = ser_console_setup, ++ .flags = CON_PRINTBUFFER, ++ .index = -1, ++}; ++ ++static int __init sb1250_serial_console_init(void) ++{ ++ register_console(&sb1250_ser_cons); ++ return 0; ++} ++ ++console_initcall(sb1250_serial_console_init); ++ ++#endif /* CONFIG_SIBYTE_SB1250_DUART_CONSOLE */ +diff -Nurb linux-2.6.16.7/include/linux/serial.h linux-2.6.16.7/include/linux/serial.h +--- linux-2.6.16.7/include/linux/serial.h 2006-04-17 14:53:25.000000000 -0700 ++++ linux-2.6.16.7/include/linux/serial.h 2006-04-28 12:25:19.000000000 -0700 +@@ -76,7 +76,8 @@ + #define PORT_16654 11 + #define PORT_16850 12 + #define PORT_RSA 13 /* RSA-DV II/S card */ +-#define PORT_MAX 13 ++#define PORT_SB1250 14 ++#define PORT_MAX 14 + + #define SERIAL_IO_PORT 0 + #define SERIAL_IO_HUB6 1 diff --git a/target/linux/sibyte-2.6/patches/001-bcm112x_ax.patch b/target/linux/sibyte-2.6/patches/001-bcm112x_ax.patch new file mode 100644 index 0000000000..c80d4aea54 --- /dev/null +++ b/target/linux/sibyte-2.6/patches/001-bcm112x_ax.patch @@ -0,0 +1,17 @@ +--- linux-2.6.16.4/arch/mips/sibyte/sb1250/setup.c 2006-04-21 16:16:18.000000000 -0700 ++++ linux-2.6.16.4/arch/mips/sibyte/sb1250/setup.c 2006-04-21 16:15:22.000000000 -0700 +@@ -140,6 +140,14 @@ + periph_rev = 3; + pass_str = "A2"; + break; ++ case K_SYS_REVISION_BCM112x_A3: ++ periph_rev = 3; ++ pass_str = "A3"; ++ break; ++ case K_SYS_REVISION_BCM112x_A4: ++ periph_rev = 3; ++ pass_str = "A4"; ++ break; + default: + prom_printf("Unknown %s rev %x\n", soc_str, soc_pass); + ret = 1; diff --git a/target/linux/x86-2.6/Makefile b/target/linux/x86-2.6/Makefile index 48417d20c8..2a9ab2c971 100644 --- a/target/linux/x86-2.6/Makefile +++ b/target/linux/x86-2.6/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk -LINUX_VERSION:=2.6.16.4 +LINUX_VERSION:=2.6.16.7 LINUX_RELEASE:=1 -LINUX_KERNEL_MD5SUM:=cb675279c9711237a06ebb8379a4da27 +LINUX_KERNEL_MD5SUM:=9682b2bd6e02f3087982d7c3f5ba824e include ../rules.mk include ./config diff --git a/target/linux/xscale-2.6/Makefile b/target/linux/xscale-2.6/Makefile new file mode 100644 index 0000000000..4f6a5db833 --- /dev/null +++ b/target/linux/xscale-2.6/Makefile @@ -0,0 +1,18 @@ +include $(TOPDIR)/rules.mk + +LINUX_VERSION:=2.6.16.7 +LINUX_RELEASE:=1 +LINUX_KERNEL_MD5SUM:=9682b2bd6e02f3087982d7c3f5ba824e + +include ../rules.mk +include ./config + +include ../generic-$(KERNEL)/modules.mk +include ../kernel.mk + + +$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked + [ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches + [ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches + @$(CP) config $(LINUX_DIR)/.config + touch $@ diff --git a/target/linux/xscale-2.6/config b/target/linux/xscale-2.6/config new file mode 100644 index 0000000000..92d4657e3e --- /dev/null +++ b/target/linux/xscale-2.6/config @@ -0,0 +1,1363 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.16.4 +# Mon Apr 17 16:00:49 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +# CONFIG_SHMEM is not set +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_SLAB is not set +CONFIG_TINY_SHMEM=y +CONFIG_BASE_SMALL=0 +CONFIG_SLOB=y +CONFIG_OBSOLETE_INTERMODULE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +CONFIG_ARCH_IXP4XX=y +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set +CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y + +# +# Intel IXP4xx Implementation Options +# + +# +# IXP4xx Platforms +# +# CONFIG_MACH_NSLU2 is not set +# CONFIG_ARCH_AVILA is not set +# CONFIG_ARCH_ADI_COYOTE is not set +CONFIG_MACH_GATEWAY7001=y +# CONFIG_ARCH_IXDP425 is not set +# CONFIG_MACH_IXDPG425 is not set +# CONFIG_MACH_IXDP465 is not set +# CONFIG_ARCH_PRPMC1100 is not set +# CONFIG_MACH_NAS100D is not set +# CONFIG_MACH_GTWX5715 is not set + +# +# IXP4xx Options +# +# CONFIG_IXP4XX_INDIRECT_PCI is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_XSCALE_PMU=y +CONFIG_DMABOUNCE=y + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=jffs2 init=/etc/preinit noinitrd console=ttyS0,115200" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=m +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_ASK_IP_FIB_HASH is not set +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IPSEC_NAT_TRAVERSAL=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=m +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +CONFIG_TCP_CONG_VEGAS=m +# CONFIG_TCP_CONG_SCALABLE is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_IPV6_TUNNEL is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +CONFIG_NETFILTER_XTABLES=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +CONFIG_NETFILTER_XT_TARGET_MARK=m +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +CONFIG_NETFILTER_XT_MATCH_HELPER=m +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_STATE=y +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=y +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=y +CONFIG_IP_NF_IRC=y +# CONFIG_IP_NF_NETBIOS_NS is not set +# CONFIG_IP_NF_TFTP is not set +# CONFIG_IP_NF_AMANDA is not set +# CONFIG_IP_NF_PPTP is not set +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_LAYER7=m +# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_IPP2P=m +CONFIG_IP_NF_MATCH_TOS=m +# CONFIG_IP_NF_MATCH_TIME is not set +# CONFIG_IP_NF_MATCH_RECENT is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_DSCP is not set +# CONFIG_IP_NF_MATCH_AH_ESP is not set +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_HASHLIMIT is not set +# CONFIG_IP_NF_MATCH_POLICY is not set +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_TARGET_IMQ=m +# CONFIG_IP_NF_TARGET_LOG is not set +# CONFIG_IP_NF_TARGET_ULOG is not set +CONFIG_IP_NF_TARGET_TCPMSS=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_REDIRECT=m +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_SAME is not set +# CONFIG_IP_NF_NAT_SNMP_BASIC is not set +CONFIG_IP_NF_NAT_IRC=y +CONFIG_IP_NF_NAT_FTP=y +CONFIG_IP_NF_NAT_SIP=m +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_TARGET_TOS=m +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_DSCP is not set +# CONFIG_IP_NF_TARGET_TTL is not set +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_SET is not set + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_MULTIPORT is not set +# CONFIG_IP6_NF_MATCH_OWNER is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_AHESP is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_POLICY is not set +CONFIG_IP6_NF_FILTER=m +# CONFIG_IP6_NF_TARGET_LOG is not set +CONFIG_IP6_NF_TARGET_REJECT=m +# CONFIG_IP6_NF_MANGLE is not set +# CONFIG_IP6_NF_RAW is not set + +# +# Bridge: Netfilter Configuration +# +# CONFIG_BRIDGE_NF_EBTABLES is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CLK_JIFFIES=y +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_ESFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +# CONFIG_NET_SCH_NETEM is not set +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_POLICE=y +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_IXP4XX=y +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_IMQ=m +# CONFIG_IMQ_BEHAVIOR_AA is not set +# CONFIG_IMQ_BEHAVIOR_AB is not set +CONFIG_IMQ_BEHAVIOR_BA=y +# CONFIG_IMQ_BEHAVIOR_BB is not set +CONFIG_IMQ_NUM_DEVS=2 +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +# CONFIG_IPW2200_DEBUG is not set +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +# CONFIG_PRISM54 is not set +# CONFIG_HOSTAP is not set +CONFIG_NET_WIRELESS=y + +# +# Wan interfaces +# +CONFIG_WAN=y +# CONFIG_DSCC4 is not set +# CONFIG_LANMEDIA is not set +# CONFIG_SYNCLINK_SYNCPPP is not set +CONFIG_HDLC=m +CONFIG_HDLC_RAW=y +# CONFIG_HDLC_RAW_ETH is not set +CONFIG_HDLC_CISCO=y +CONFIG_HDLC_FR=y +CONFIG_HDLC_PPP=y + +# +# X.25/LAPB support is disabled +# +# CONFIG_PCI200SYN is not set +# CONFIG_WANXL is not set +# CONFIG_PC300 is not set +# CONFIG_FARSYNC is not set +CONFIG_DLCI=m +CONFIG_DLCI_COUNT=24 +CONFIG_DLCI_MAX=8 +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_IXP4XX_WATCHDOG=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_BANDWIDTH=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# File systems +# +CONFIG_EXT2_FS=m +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=m +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/target/linux/xscale-2.6/patches/001-gateway_7001.patch b/target/linux/xscale-2.6/patches/001-gateway_7001.patch new file mode 100644 index 0000000000..8942679000 --- /dev/null +++ b/target/linux/xscale-2.6/patches/001-gateway_7001.patch @@ -0,0 +1,159 @@ +diff -Nur linux-2.6.16.4/arch/arm/boot/compressed/head-xscale.S linux-2.6.16.4-owrt/arch/arm/boot/compressed/head-xscale.S +--- linux-2.6.16.4/arch/arm/boot/compressed/head-xscale.S 2006-04-11 19:19:28.000000000 +0200 ++++ linux-2.6.16.4-owrt/arch/arm/boot/compressed/head-xscale.S 2006-04-16 16:51:05.000000000 +0200 +@@ -47,6 +47,11 @@ + orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00) + #endif + ++#ifdef CONFIG_MACH_GATEWAY7001 ++ mov r7, #(MACH_TYPE_GATEWAY7001 & 0xff) ++ orr r7, r7, #(MACH_TYPE_GATEWAY7001 & 0xff00) ++#endif ++ + #ifdef CONFIG_ARCH_IXP2000 + mov r1, #-1 + mov r0, #0xd6000000 +diff -Nur linux-2.6.16.4/arch/arm/mach-ixp4xx/gateway7001-pci.c linux-2.6.16.4-owrt/arch/arm/mach-ixp4xx/gateway7001-pci.c +--- linux-2.6.16.4/arch/arm/mach-ixp4xx/gateway7001-pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.4-owrt/arch/arm/mach-ixp4xx/gateway7001-pci.c 2006-04-17 19:21:55.000000000 +0200 +@@ -0,0 +1,67 @@ ++/* ++ * arch/arch/mach-ixp4xx/gateway7001-pci.c ++ * ++ * PCI setup routines for Gateway 7001 ++ * ++ * Copyright (C) 2006 Imre Kaloz ++ * ++ * based on coyote-pci.c: ++ * Copyright (C) 2002 Jungo Software Technologies. ++ * Copyright (C) 2003 MontaVista Softwrae, Inc. ++ * ++ * Maintainer: Imre Kaloz ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++extern void ixp4xx_pci_preinit(void); ++extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); ++extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); ++ ++void __init gateway7001_pci_preinit(void) ++{ ++ set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW); ++ set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW); ++ ++ ixp4xx_pci_preinit(); ++} ++ ++static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (slot == 0) ++ return IRQ_IXP4XX_GPIO10; ++ else if (slot == 1) ++ return IRQ_IXP4XX_GPIO11; ++ else return -1; ++} ++ ++struct hw_pci gateway7001_pci __initdata = { ++ .nr_controllers = 1, ++ .preinit = gateway7001_pci_preinit, ++ .swizzle = pci_std_swizzle, ++ .setup = ixp4xx_setup, ++ .scan = ixp4xx_scan_bus, ++ .map_irq = gateway7001_map_irq, ++}; ++ ++int __init gateway7001_pci_init(void) ++{ ++ if (machine_is_gateway7001()) ++ pci_common_init(&gateway7001_pci); ++ return 0; ++} ++ ++subsys_initcall(gateway7001_pci_init); +diff -Nur linux-2.6.16.4/arch/arm/mach-ixp4xx/Kconfig linux-2.6.16.4-owrt/arch/arm/mach-ixp4xx/Kconfig +--- linux-2.6.16.4/arch/arm/mach-ixp4xx/Kconfig 2006-04-11 19:19:28.000000000 +0200 ++++ linux-2.6.16.4-owrt/arch/arm/mach-ixp4xx/Kconfig 2006-04-16 15:58:37.000000000 +0200 +@@ -30,6 +30,13 @@ + Engineering Coyote Gateway Reference Platform. For more + information on this platform, see . + ++config MACH_GATEWAY7001 ++ bool "Gateway 7001" ++ help ++ Say 'Y' here if you want your kernel to support Gateway's ++ 7001 Access Point. For more information on this platform, ++ see http://openwrt.org ++ + config ARCH_IXDP425 + bool "IXDP425" + help +diff -Nur linux-2.6.16.4/arch/arm/mach-ixp4xx/Makefile linux-2.6.16.4-owrt/arch/arm/mach-ixp4xx/Makefile +--- linux-2.6.16.4/arch/arm/mach-ixp4xx/Makefile 2006-04-11 19:19:28.000000000 +0200 ++++ linux-2.6.16.4-owrt/arch/arm/mach-ixp4xx/Makefile 2006-04-16 16:03:42.000000000 +0200 +@@ -10,4 +10,5 @@ + obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o + obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o + obj-$(CONFIG_MACH_NAS100D) += nas100d-pci.o nas100d-setup.o nas100d-power.o ++obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-pci.o coyote-setup.o + +diff -Nur linux-2.6.16.4/include/asm-arm/arch-ixp4xx/uncompress.h linux-2.6.16.4-owrt/include/asm-arm/arch-ixp4xx/uncompress.h +--- linux-2.6.16.4/include/asm-arm/arch-ixp4xx/uncompress.h 2006-04-11 19:19:28.000000000 +0200 ++++ linux-2.6.16.4-owrt/include/asm-arm/arch-ixp4xx/uncompress.h 2006-04-16 16:25:34.000000000 +0200 +@@ -48,7 +48,7 @@ + /* + * Coyote and gtwx5715 only have UART2 connected + */ +- if (machine_is_adi_coyote() || machine_is_gtwx5715()) ++ if (machine_is_adi_coyote() || machine_is_gtwx5715() || machine_is_gateway7001()) + uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; + else + uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; +diff -Nur linux-2.6.16.4/arch/arm/mach-ixp4xx/coyote-setup.c linux-2.6.16.4-owrt/arch/arm/mach-ixp4xx/coyote-setup.c +--- linux-2.6.16.4/arch/arm/mach-ixp4xx/coyote-setup.c 2006-04-11 19:19:28.000000000 +0200 ++++ linux-2.6.16.4-owrt/arch/arm/mach-ixp4xx/coyote-setup.c 2006-04-16 16:03:23.000000000 +0200 +@@ -1,9 +1,10 @@ + /* + * arch/arm/mach-ixp4xx/coyote-setup.c + * +- * Board setup for ADI Engineering and IXDGP425 boards ++ * Board setup for ADI Engineering, IXDGP425 and Gateway 7001 boards + * + * Copyright (C) 2003-2005 MontaVista Software, Inc. ++ * Copyright (C) 2006 Imre Kaloz + * + * Author: Deepak Saxena + */ +@@ -111,6 +112,19 @@ + MACHINE_END + #endif + ++#ifdef CONFIG_MACH_GATEWAY7001 ++MACHINE_START(GATEWAY7001, "Gateway 7001") ++ /* Maintainer: Imre Kaloz */ ++ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, ++ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, ++ .map_io = ixp4xx_map_io, ++ .init_irq = ixp4xx_init_irq, ++ .timer = &ixp4xx_timer, ++ .boot_params = 0x0100, ++ .init_machine = coyote_init, ++MACHINE_END ++#endif ++ + /* + * IXDPG425 is identical to Coyote except for which serial port + * is connected. -- cgit v1.2.3