From: Felix Fietkau Date: Thu, 6 Apr 2006 15:52:01 +0000 (+0000) Subject: integrate the newer broadcom wl driver from us robotics X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=ab9e191898c7ad88ccf5146fa409d14c346486c8;p=librecmc%2Flibrecmc.git integrate the newer broadcom wl driver from us robotics SVN-Revision: 3596 --- diff --git a/openwrt/target/linux/brcm-2.4/Makefile b/openwrt/target/linux/brcm-2.4/Makefile index ab68b7ae88..17473be323 100644 --- a/openwrt/target/linux/brcm-2.4/Makefile +++ b/openwrt/target/linux/brcm-2.4/Makefile @@ -13,7 +13,7 @@ $(eval $(call KMOD_template,BRCM_WL,brcm-wl,\ ,CONFIG_WL,,20,wl)) $(eval $(call KMOD_template,BRCM_WL2,brcm-wl2,\ - $(BUILD_DIR)/wl/wl2/wl.o \ + $(MODULES_DIR)/kernel/drivers/net/wl2/wl.o \ ,CONFIG_WL,,20,wl)) $(eval $(call KMOD_template,LP,lp,\ @@ -40,8 +40,8 @@ $(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked LINUX_BINARY_DRIVER_SITE=http://openwrt.org/downloads/sources # proprietary driver, extracted from Linksys GPL sourcetree WRT54GS 4.70.6 -LINUX_BINARY_WL_DRIVER=kernel-binary-wl-0.5.tar.gz -LINUX_BINARY_WL_MD5SUM=78e839842bdc04022bb44469f92b1131 +LINUX_BINARY_WL_DRIVER=kernel-binary-wl-0.6.tar.gz +LINUX_BINARY_WL_MD5SUM=4fc1d5b46bcb7a17d6d5dd31da9c8d7f $(DL_DIR)/$(LINUX_BINARY_WL_DRIVER): $(SCRIPT_DIR)/download.pl $(DL_DIR) $(LINUX_BINARY_WL_DRIVER) $(LINUX_BINARY_WL_MD5SUM) $(LINUX_BINARY_DRIVER_SITE) $(MAKE_TRACE) @@ -56,12 +56,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)/wl/*.o $(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 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 diff --git a/openwrt/target/linux/brcm-2.4/config b/openwrt/target/linux/brcm-2.4/config index c4cf5340ea..9759b90f5f 100644 --- a/openwrt/target/linux/brcm-2.4/config +++ b/openwrt/target/linux/brcm-2.4/config @@ -833,6 +833,7 @@ 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/openwrt/target/linux/brcm-2.4/patches/001-bcm47xx.patch b/openwrt/target/linux/brcm-2.4/patches/001-bcm47xx.patch index 2e64b0fc3e..d662b4c015 100644 --- a/openwrt/target/linux/brcm-2.4/patches/001-bcm47xx.patch +++ b/openwrt/target/linux/brcm-2.4/patches/001-bcm47xx.patch @@ -1,6 +1,56 @@ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/cfe_env.c linux-2.4.32-brcm/arch/mips/bcm947xx/cfe_env.c ---- linux-2.4.32/arch/mips/bcm947xx/cfe_env.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/cfe_env.c 2005-12-19 01:56:35.104829500 +0100 +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 +@@ -726,6 +726,19 @@ + endif + + # ++# Broadcom BCM947XX variants ++# ++ifdef CONFIG_BCM947XX ++LIBS += arch/mips/bcm947xx/generic/brcm.o arch/mips/bcm947xx/bcm947xx.o ++SUBDIRS += arch/mips/bcm947xx/generic arch/mips/bcm947xx ++LOADADDR := 0x80001000 ++ ++zImage: vmlinux ++ $(MAKE) -C arch/$(ARCH)/bcm947xx/compressed ++export LOADADDR ++endif ++ ++# + # Choosing incompatible machines durings configuration will result in + # error messages during linking. Select a default linkscript if + # none has been choosen above. +@@ -778,6 +791,7 @@ + $(MAKE) -C arch/$(ARCH)/tools clean + $(MAKE) -C arch/mips/baget clean + $(MAKE) -C arch/mips/lasat clean ++ $(MAKE) -C arch/mips/bcm947xx/compressed clean + + archmrproper: + @$(MAKEBOOT) mrproper +diff -Naur 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 @@ ++# ++# Makefile for the BCM947xx specific kernel interface routines ++# under Linux. ++# ++ ++EXTRA_CFLAGS+=-I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER ++ ++O_TARGET := bcm947xx.o ++ ++export-objs := nvram_linux.o setup.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-$(CONFIG_PCI) += sbpci.o pcibios.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 @@ +/* + * NVRAM variable manipulation (Linux kernel half) @@ -236,9 +286,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/cfe_env.c linux-2.4.32-brcm/arch/mips/ + +} + -diff -Nur linux-2.4.32/arch/mips/bcm947xx/compressed/Makefile linux-2.4.32-brcm/arch/mips/bcm947xx/compressed/Makefile ---- linux-2.4.32/arch/mips/bcm947xx/compressed/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/compressed/Makefile 2005-12-16 23:39:10.668819500 +0100 +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 @@ -273,9 +323,28 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/compressed/Makefile linux-2.4.32-brcm/ + +clean: + rm -f vmlinuz piggy -diff -Nur linux-2.4.32/arch/mips/bcm947xx/generic/int-handler.S linux-2.4.32-brcm/arch/mips/bcm947xx/generic/int-handler.S ---- linux-2.4.32/arch/mips/bcm947xx/generic/int-handler.S 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/generic/int-handler.S 2005-12-16 23:39:10.668819500 +0100 +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. ++# ++ ++.S.s: ++ $(CPP) $(AFLAGS) $< -o $*.s ++.S.o: ++ $(CC) $(AFLAGS) -c $< -o $*.o ++ ++O_TARGET := brcm.o ++ ++obj-y := int-handler.o irq.o ++ ++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 @@ -328,9 +397,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/generic/int-handler.S linux-2.4.32-brc + nop + + END(brcmIRQ) -diff -Nur linux-2.4.32/arch/mips/bcm947xx/generic/irq.c linux-2.4.32-brcm/arch/mips/bcm947xx/generic/irq.c ---- linux-2.4.32/arch/mips/bcm947xx/generic/irq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/generic/irq.c 2005-12-16 23:39:10.668819500 +0100 +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 @@ -462,28 +531,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/generic/irq.c linux-2.4.32-brcm/arch/m + breakpoint(); +#endif +} -diff -Nur linux-2.4.32/arch/mips/bcm947xx/generic/Makefile linux-2.4.32-brcm/arch/mips/bcm947xx/generic/Makefile ---- linux-2.4.32/arch/mips/bcm947xx/generic/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/generic/Makefile 2005-12-16 23:39:10.668819500 +0100 -@@ -0,0 +1,15 @@ -+# -+# Makefile for the BCM947xx specific kernel interface routines -+# under Linux. -+# -+ -+.S.s: -+ $(CPP) $(AFLAGS) $< -o $*.s -+.S.o: -+ $(CC) $(AFLAGS) -c $< -o $*.o -+ -+O_TARGET := brcm.o -+ -+obj-y := int-handler.o irq.o -+ -+include $(TOPDIR)/Rules.make -diff -Nur linux-2.4.32/arch/mips/bcm947xx/gpio.c linux-2.4.32-brcm/arch/mips/bcm947xx/gpio.c ---- linux-2.4.32/arch/mips/bcm947xx/gpio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/gpio.c 2005-12-16 23:39:10.668819500 +0100 +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 @@ -643,9 +693,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/gpio.c linux-2.4.32-brcm/arch/mips/bcm + +module_init(gpio_init); +module_exit(gpio_exit); -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmdevs.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmdevs.h ---- linux-2.4.32/arch/mips/bcm947xx/include/bcmdevs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmdevs.h 2005-12-16 23:39:10.672819750 +0100 +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. @@ -1038,9 +1088,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmdevs.h linux-2.4.32-brcm/ar +#define GPIO_NUMPINS 16 + +#endif /* _BCMDEVS_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmendian.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmendian.h ---- linux-2.4.32/arch/mips/bcm947xx/include/bcmendian.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmendian.h 2005-12-16 23:39:10.672819750 +0100 +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 @@ -1194,9 +1244,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmendian.h linux-2.4.32-brcm/ +) + +#endif /* _BCMENDIAN_H_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmnvram.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmnvram.h ---- linux-2.4.32/arch/mips/bcm947xx/include/bcmnvram.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmnvram.h 2005-12-16 23:39:10.700821500 +0100 +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 @@ +/* + * NVRAM variable manipulation @@ -1339,9 +1389,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmnvram.h linux-2.4.32-brcm/a +#define NVRAM_MAX_PARAM_LEN 64 + +#endif /* _bcmnvram_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmsrom.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmsrom.h ---- linux-2.4.32/arch/mips/bcm947xx/include/bcmsrom.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmsrom.h 2005-12-16 23:39:10.704821750 +0100 +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 . @@ -1366,10 +1416,10 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmsrom.h linux-2.4.32-brcm/ar +extern int srom_write(uint bus, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf); + +#endif /* _bcmsrom_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmutils.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmutils.h ---- linux-2.4.32/arch/mips/bcm947xx/include/bcmutils.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/bcmutils.h 2005-12-16 23:39:10.704821750 +0100 -@@ -0,0 +1,313 @@ +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. + * @@ -1429,32 +1479,6 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmutils.h linux-2.4.32-brcm/a + } \ +} + -+/* 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 -+ -+#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)) -+ -+/* 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); +/* string */ +extern uint bcm_atoi(char *s); +extern uchar bcm_toupper(uchar c); @@ -1683,84 +1707,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/bcmutils.h linux-2.4.32-brcm/a +extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); + +#endif /* _bcmutils_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/hnddma.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/hnddma.h ---- linux-2.4.32/arch/mips/bcm947xx/include/hnddma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/hnddma.h 2005-12-16 23:39:10.708822000 +0100 -@@ -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_ -+ -+/* 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; -+ -+#ifndef di_t -+#define di_t void -+#endif -+ -+#ifndef osl_t -+#define osl_t void -+#endif -+ -+/* externs */ -+extern 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); -+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 *); -+ -+ -+#endif /* _hnddma_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/hndmips.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/hndmips.h ---- linux-2.4.32/arch/mips/bcm947xx/include/hndmips.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/hndmips.h 2005-12-16 23:39:10.708822000 +0100 +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 @@ -1778,9 +1727,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/hndmips.h linux-2.4.32-brcm/ar + */ + +#include "sbmips.h" -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/linux_osl.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/linux_osl.h ---- linux-2.4.32/arch/mips/bcm947xx/include/linux_osl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/linux_osl.h 2005-12-16 23:39:10.708822000 +0100 +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 @@ +/* + * Linux OS Independent Layer @@ -2153,9 +2102,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/linux_osl.h linux-2.4.32-brcm/ +#define PKTBUFSZ 2048 + +#endif /* _linux_osl_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/linuxver.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/linuxver.h ---- linux-2.4.32/arch/mips/bcm947xx/include/linuxver.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/linuxver.h 2005-12-16 23:39:10.748824500 +0100 +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 @@ +/* + * Linux-specific abstractions to gain some independence from linux kernel versions. @@ -2568,9 +2517,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/linuxver.h linux-2.4.32-brcm/a +#endif + +#endif /* _linuxver_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/mipsinc.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/mipsinc.h ---- linux-2.4.32/arch/mips/bcm947xx/include/mipsinc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/mipsinc.h 2005-12-16 23:39:10.748824500 +0100 +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. @@ -3124,9 +3073,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/mipsinc.h linux-2.4.32-brcm/ar +#endif /* !_LANGUAGE_ASSEMBLY */ + +#endif /* _MISPINC_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/osl.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/osl.h ---- linux-2.4.32/arch/mips/bcm947xx/include/osl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/osl.h 2005-12-16 23:39:10.748824500 +0100 +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 @@ -3170,9 +3119,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/osl.h linux-2.4.32-brcm/arch/m +#define MAXPRIO 7 /* 0-7 */ + +#endif /* _osl_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/pcicfg.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/pcicfg.h ---- linux-2.4.32/arch/mips/bcm947xx/include/pcicfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/pcicfg.h 2005-12-16 23:39:10.752824750 +0100 +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 @@ +/* + * pcicfg.h: PCI configuration constants and structures. @@ -3625,9 +3574,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/pcicfg.h linux-2.4.32-brcm/arc +#define PCI_CFG_CMD_STAT_TA 0x08000000 /* target abort status */ + +#endif -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbchipc.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbchipc.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbchipc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbchipc.h 2005-12-16 23:39:10.932836000 +0100 +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. @@ -4069,9 +4018,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbchipc.h linux-2.4.32-brcm/ar +#define OTP_MAGIC 0x4e56 + +#endif /* _SBCHIPC_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbconfig.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbconfig.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbconfig.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbconfig.h 2005-12-16 23:39:10.932836000 +0100 +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. @@ -4415,9 +4364,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbconfig.h linux-2.4.32-brcm/a +#define BISZ_SIZE 7 /* descriptor size in 32-bit intergers */ + +#endif /* _SBCONFIG_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbextif.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbextif.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbextif.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbextif.h 2005-12-16 23:39:10.932836000 +0100 +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 @@ -4661,13 +4610,12 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbextif.h linux-2.4.32-brcm/ar +#define CC_CLOCK_BASE 24000000 /* Half the clock freq. in the 4710 */ + +#endif /* _SBEXTIF_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbhnddma.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbhnddma.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbhnddma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbhnddma.h 2005-12-16 23:39:10.932836000 +0100 -@@ -0,0 +1,312 @@ +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 @@ +/* -+ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface -+ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * BCM47XX Sonics SiliconBackplane DDR/SDRAM controller core hardware definitions. + * + * Copyright 2005, Broadcom Corporation + * All Rights Reserved. @@ -4676,314 +4624,344 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbhnddma.h linux-2.4.32-brcm/a + * 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_ ++#ifndef _SBMEMC_H ++#define _SBMEMC_H + -+ -+/* 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; ++#ifdef _LANGUAGE_ASSEMBLY + -+/* a pair of pio channels(tx and rx) */ -+typedef volatile struct { -+ pio2regs_t tx; -+ pio2regs_t rx; -+} pio2regp_t; ++#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 + -+/* 4byte-wide pio register set per channel(xmt or rcv) */ -+typedef volatile struct { -+ uint32 fifocontrol; -+ uint32 fifodata; -+} pio4regs_t; + -+/* a pair of pio channels(tx and rx) */ -+typedef volatile struct { -+ pio4regs_t tx; -+ pio4regs_t rx; -+} pio4regp_t; ++#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 + -+/* 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 -+ */ ++/* 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 + -+/*** 32 bits addressing ***/ + -+/* 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; ++/* 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) */ + -+typedef volatile struct { -+ dma32regs_t xmt; /* dma tx channel */ -+ dma32regs_t rcv; /* dma rx channel */ -+} dma32regp_t; ++/* 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 + -+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; ++/* 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) */ + -+/* -+ * 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)) ++/* mask for sdr/ddr calibration registers */ ++#define MEMC_RDNCDLCOR_RD_MASK 0x000000ff ++#define MEMC_WRNCDLCOR_WR_MASK 0x000000ff ++#define MEMC_DQSGATENCDL_G_MASK 0x000000ff + -+/* 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 ++/* 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 + -+/* transmit descriptor table pointer */ -+#define XP_LD_MASK 0xfff /* last valid descriptor */ ++/* hw threshhold for calculating wr/rd for sdr memc */ ++#define MEMC_CD_THRESHOLD 128 + -+/* 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 ++/* Low bit of init register says if memc is ddr or sdr */ ++#define MEMC_CONFIG_DDR 0x00000001 + -+/* 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 ++#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 @@ ++/* ++ * 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 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$ ++ */ + -+/* receive descriptor table pointer */ -+#define RP_LD_MASK 0xfff /* last valid descriptor */ ++#ifndef _SBMIPS_H ++#define _SBMIPS_H + -+/* 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 ++#include + -+/* 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 */ ++#ifndef _LANGUAGE_ASSEMBLY + -+/* 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 */ ++/* 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 */ + -+/* control flags in the range [27:20] are core-specific and not defined here */ -+#define CTRL_CORE_MASK 0x0ff00000 ++typedef volatile struct { ++ uint32 corecontrol; ++ uint32 PAD[2]; ++ uint32 biststatus; ++ uint32 PAD[4]; ++ uint32 intstatus; ++ uint32 intmask; ++ uint32 timer; ++} mipsregs_t; + -+/*** 64 bits addressing ***/ ++extern uint32 sb_flag(sb_t *sbh); ++extern uint sb_irq(sb_t *sbh); + -+/* 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; ++extern void BCMINIT(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift)); + -+typedef volatile struct { -+ dma64regs_t tx; /* dma64 tx channel */ -+ dma64regs_t rx; /* dma64 rx channel */ -+} dma64regp_t; ++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); + -+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; + ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++#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 @@ +/* -+ * 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; -+ -+/* -+ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. ++ * 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. + */ -+#define D64MAXRINGSZ 8192 -+#define D64RINGALIGN 8192 -+#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) + -+/* 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 ++#ifndef _SBPCI_H ++#define _SBPCI_H + -+/* transmit descriptor table pointer */ -+#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif + -+/* 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 */ ++/* 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; + -+#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 */ ++/* 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 */ + -+/* 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 ++/* 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 */ + -+/* receive descriptor table pointer */ -+#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ ++/* 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 */ + -+/* 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 */ ++/* (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 */ + -+#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 */ ++/* Sonics broadcast address */ ++#define BCAST_ADDR_MASK 0xff /* Broadcast register address */ + -+/* 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 */ ++/* 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 */ + -+/* 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 */ ++/* 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 */ + -+/* 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 ++/* 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] + -+/* control flags in the range [27:20] are core-specific and not defined here */ -+#define D64_CTRL_CORE_MASK 0x0ff00000 ++#ifndef _LANGUAGE_ASSEMBLY ++ ++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); + ++#endif /* !_LANGUAGE_ASSEMBLY */ + -+#endif /* _sbhnddma_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbmemc.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbmemc.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbmemc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbmemc.h 2005-12-16 23:39:10.932836000 +0100 -@@ -0,0 +1,148 @@ ++#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 @@ +/* -+ * BCM47XX Sonics SiliconBackplane DDR/SDRAM controller core hardware definitions. ++ * BCM43XX SiliconBackplane PCIE core hardware definitions. + * ++ * $Id: + * Copyright 2005, Broadcom Corporation + * All Rights Reserved. + * @@ -4991,254 +4969,35 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbmemc.h linux-2.4.32-brcm/arc + * 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 _SBMEMC_H -+#define _SBMEMC_H ++#ifndef _SBPCIE_H ++#define _SBPCIE_H + -+#ifdef _LANGUAGE_ASSEMBLY ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#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 ++/* 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 + ++/* 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 + -+#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 -+ -+/* Low bit of init register says if memc is ddr or sdr */ -+#define MEMC_CONFIG_DDR 0x00000001 -+ -+#endif /* _SBMEMC_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbmips.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbmips.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbmips.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbmips.h 2005-12-16 23:39:10.936836250 +0100 -@@ -0,0 +1,62 @@ -+/* -+ * 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 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 _SBMIPS_H -+#define _SBMIPS_H -+ -+#include -+ -+#ifndef _LANGUAGE_ASSEMBLY -+ -+/* 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 */ -+ -+typedef volatile struct { -+ uint32 corecontrol; -+ uint32 PAD[2]; -+ uint32 biststatus; -+ uint32 PAD[4]; -+ uint32 intstatus; -+ uint32 intmask; -+ uint32 timer; -+} mipsregs_t; -+ -+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)); -+ -+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); -+ -+ -+#endif /* _LANGUAGE_ASSEMBLY */ -+ -+#endif /* _SBMIPS_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbpcie.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbpcie.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbpcie.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbpcie.h 2005-12-16 23:39:10.936836250 +0100 -@@ -0,0 +1,199 @@ -+/* -+ * BCM43XX SiliconBackplane PCIE 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. -+ */ -+ -+#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__) -+#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 -+ -+/* 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 -+ -+/* SB side: PCIE core and host control registers */ -+typedef struct sbpcieregs { ++/* SB side: PCIE core and host control registers */ ++typedef struct sbpcieregs { + + uint32 PAD[3]; + uint32 biststatus; /* bist Status: 0x00C*/ @@ -5398,12 +5157,12 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbpcie.h linux-2.4.32-brcm/arc +#define SERDES_RX_CDRBW 7 /* CDR BW */ + +#endif /* _SBPCIE_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbpci.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbpci.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbpci.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbpci.h 2005-12-16 23:39:10.936836250 +0100 -@@ -0,0 +1,122 @@ +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 @@ +/* -+ * BCM47XX Sonics SiliconBackplane PCI core hardware definitions. ++ * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions. + * + * $Id$ + * Copyright 2005, Broadcom Corporation @@ -5415,145 +5174,19 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbpci.h linux-2.4.32-brcm/arch + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + */ + -+#ifndef _SBPCI_H -+#define _SBPCI_H ++#ifndef _SBPCMCIA_H ++#define _SBPCMCIA_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 + -+/* 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; ++/* 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. ++ */ + -+/* 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 */ -+ -+/* 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 */ -+ -+/* 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 */ -+ -+/* (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 */ -+ -+/* Sonics broadcast address */ -+#define BCAST_ADDR_MASK 0xff /* Broadcast register address */ -+ -+/* 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 */ -+ -+/* 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 */ -+ -+/* 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] -+ -+#ifndef _LANGUAGE_ASSEMBLY -+ -+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); -+ -+#endif /* !_LANGUAGE_ASSEMBLY */ -+ -+#endif /* _SBPCI_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbpcmcia.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbpcmcia.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbpcmcia.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbpcmcia.h 2005-12-16 23:39:10.936836250 +0100 -@@ -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. -+ */ -+ -+#ifndef _SBPCMCIA_H -+#define _SBPCMCIA_H -+ -+ -+/* 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. -+ */ -+ -+/* PCMCIA Function Configuration Registers */ -+#define PCMCIA_FCR (0x700 / 2) ++/* PCMCIA Function Configuration Registers */ ++#define PCMCIA_FCR (0x700 / 2) + +#define FCR0_OFF 0 +#define FCR1_OFF (0x40 / 2) @@ -5674,9 +5307,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbpcmcia.h linux-2.4.32-brcm/a +#define SBTMH_INT_STATUS 0x40000 /* sb interrupt status */ + +#endif /* _SBPCMCIA_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbsdram.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbsdram.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbsdram.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbsdram.h 2005-12-16 23:39:10.936836250 +0100 +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. @@ -5753,9 +5386,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbsdram.h linux-2.4.32-brcm/ar +#define MEM8MX16X2 0xc29 /* 32 MB */ + +#endif /* _SBSDRAM_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbsocram.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbsocram.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbsocram.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbsocram.h 2005-12-16 23:39:10.936836250 +0100 +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 @@ -5794,9 +5427,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbsocram.h linux-2.4.32-brcm/a +#define SOCRAM_MEMSIZE_BASESHIFT 16 + +#endif /* _SBSOCRAM_H */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbutils.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbutils.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sbutils.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sbutils.h 2005-12-16 23:39:10.936836250 +0100 +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 @@ -5938,9 +5571,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sbutils.h linux-2.4.32-brcm/ar +#define SB_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ + +#endif /* _sbutils_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sflash.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/sflash.h ---- linux-2.4.32/arch/mips/bcm947xx/include/sflash.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/sflash.h 2005-12-16 23:39:10.936836250 +0100 +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 @@ -5978,9 +5611,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/sflash.h linux-2.4.32-brcm/arc +extern struct sflash * sflash_init(chipcregs_t *cc); + +#endif /* _sflash_h_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/trxhdr.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/trxhdr.h ---- linux-2.4.32/arch/mips/bcm947xx/include/trxhdr.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/trxhdr.h 2005-12-16 23:39:10.940836500 +0100 +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. @@ -6015,9 +5648,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/trxhdr.h linux-2.4.32-brcm/arc + +/* Compatibility */ +typedef struct trx_header TRXHDR, *PTRXHDR; -diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/typedefs.h linux-2.4.32-brcm/arch/mips/bcm947xx/include/typedefs.h ---- linux-2.4.32/arch/mips/bcm947xx/include/typedefs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/include/typedefs.h 2005-12-16 23:39:10.940836500 +0100 +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 @@ -6345,28 +5978,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/include/typedefs.h linux-2.4.32-brcm/a +#endif /* USE_TYPEDEF_DEFAULTS */ + +#endif /* _TYPEDEFS_H_ */ -diff -Nur linux-2.4.32/arch/mips/bcm947xx/Makefile linux-2.4.32-brcm/arch/mips/bcm947xx/Makefile ---- linux-2.4.32/arch/mips/bcm947xx/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/Makefile 2005-12-19 01:56:51.733868750 +0100 -@@ -0,0 +1,15 @@ -+# -+# Makefile for the BCM947xx specific kernel interface routines -+# under Linux. -+# -+ -+EXTRA_CFLAGS+=-I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER -+ -+O_TARGET := bcm947xx.o -+ -+export-objs := nvram_linux.o setup.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-$(CONFIG_PCI) += sbpci.o pcibios.o -+ -+include $(TOPDIR)/Rules.make -diff -Nur linux-2.4.32/arch/mips/bcm947xx/nvram.c linux-2.4.32-brcm/arch/mips/bcm947xx/nvram.c ---- linux-2.4.32/arch/mips/bcm947xx/nvram.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/nvram.c 2005-12-19 01:05:00.079582750 +0100 +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) @@ -6688,9 +6302,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/nvram.c linux-2.4.32-brcm/arch/mips/bc +{ + BCMINIT(nvram_free)(); +} -diff -Nur linux-2.4.32/arch/mips/bcm947xx/nvram_linux.c linux-2.4.32-brcm/arch/mips/bcm947xx/nvram_linux.c ---- linux-2.4.32/arch/mips/bcm947xx/nvram_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/nvram_linux.c 2005-12-19 01:09:59.782313000 +0100 +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 @@ +/* + * NVRAM variable manipulation (Linux kernel half) @@ -7345,9 +6959,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/nvram_linux.c linux-2.4.32-brcm/arch/m + +module_init(dev_nvram_init); +module_exit(dev_nvram_exit); -diff -Nur linux-2.4.32/arch/mips/bcm947xx/pcibios.c linux-2.4.32-brcm/arch/mips/bcm947xx/pcibios.c ---- linux-2.4.32/arch/mips/bcm947xx/pcibios.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/pcibios.c 2005-12-16 23:39:10.944836750 +0100 +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) @@ -7704,9 +7318,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/pcibios.c linux-2.4.32-brcm/arch/mips/ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} + -diff -Nur linux-2.4.32/arch/mips/bcm947xx/prom.c linux-2.4.32-brcm/arch/mips/bcm947xx/prom.c ---- linux-2.4.32/arch/mips/bcm947xx/prom.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/prom.c 2005-12-16 23:39:10.944836750 +0100 +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 @@ -7749,9 +7363,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/prom.c linux-2.4.32-brcm/arch/mips/bcm +prom_free_prom_memory(void) +{ +} -diff -Nur linux-2.4.32/arch/mips/bcm947xx/sbmips.c linux-2.4.32-brcm/arch/mips/bcm947xx/sbmips.c ---- linux-2.4.32/arch/mips/bcm947xx/sbmips.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/sbmips.c 2005-12-16 23:39:10.944836750 +0100 +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 @@ +/* + * BCM47XX Sonics SiliconBackplane MIPS core routines @@ -8791,9 +8405,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/sbmips.c linux-2.4.32-brcm/arch/mips/b + return ret; +} + -diff -Nur linux-2.4.32/arch/mips/bcm947xx/sbpci.c linux-2.4.32-brcm/arch/mips/bcm947xx/sbpci.c ---- linux-2.4.32/arch/mips/bcm947xx/sbpci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/sbpci.c 2005-12-16 23:39:10.948837000 +0100 +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 @@ +/* + * Low-Level PCI and SB support for BCM47xx @@ -9383,9 +8997,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/sbpci.c linux-2.4.32-brcm/arch/mips/bc + sb_setcoreidx(sbh, coreidx); +} + -diff -Nur linux-2.4.32/arch/mips/bcm947xx/setup.c linux-2.4.32-brcm/arch/mips/bcm947xx/setup.c ---- linux-2.4.32/arch/mips/bcm947xx/setup.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/setup.c 2005-12-20 00:29:40.187416500 +0100 +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 @@ -9621,9 +9235,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/setup.c linux-2.4.32-brcm/arch/mips/bc +} + +EXPORT_SYMBOL(bcm947xx_sbh); -diff -Nur linux-2.4.32/arch/mips/bcm947xx/sflash.c linux-2.4.32-brcm/arch/mips/bcm947xx/sflash.c ---- linux-2.4.32/arch/mips/bcm947xx/sflash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/sflash.c 2005-12-16 23:39:10.948837000 +0100 +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 @@ +/* + * Broadcom SiliconBackplane chipcommon serial flash interface @@ -10043,9 +9657,9 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/sflash.c linux-2.4.32-brcm/arch/mips/b + return ret; +} + -diff -Nur linux-2.4.32/arch/mips/bcm947xx/time.c linux-2.4.32-brcm/arch/mips/bcm947xx/time.c ---- linux-2.4.32/arch/mips/bcm947xx/time.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/bcm947xx/time.c 2005-12-16 23:39:10.948837000 +0100 +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 @@ -10165,10 +9779,10 @@ diff -Nur linux-2.4.32/arch/mips/bcm947xx/time.c linux-2.4.32-brcm/arch/mips/bcm + /* Enable the timer interrupt */ + setup_irq(7, &bcm947xx_timer_irqaction); +} -diff -Nur linux-2.4.32/arch/mips/config-shared.in linux-2.4.32-brcm/arch/mips/config-shared.in ---- linux-2.4.32/arch/mips/config-shared.in 2005-01-19 15:09:27.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/config-shared.in 2005-12-16 23:39:11.080845250 +0100 -@@ -205,6 +205,14 @@ +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 @@ -10183,7 +9797,7 @@ diff -Nur linux-2.4.32/arch/mips/config-shared.in linux-2.4.32-brcm/arch/mips/co 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 -@@ -226,6 +234,11 @@ +@@ -229,6 +237,11 @@ define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n # @@ -10195,7 +9809,7 @@ diff -Nur linux-2.4.32/arch/mips/config-shared.in linux-2.4.32-brcm/arch/mips/co # Select some configuration options automatically based on user selections. # if [ "$CONFIG_ACER_PICA_61" = "y" ]; then -@@ -533,6 +546,13 @@ +@@ -554,6 +567,13 @@ define_bool CONFIG_SWAP_IO_SPACE_L y define_bool CONFIG_BOOT_ELF32 y fi @@ -10209,7 +9823,7 @@ diff -Nur linux-2.4.32/arch/mips/config-shared.in linux-2.4.32-brcm/arch/mips/co if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then define_bool CONFIG_ARC32 y define_bool CONFIG_ARC_MEMORY y -@@ -1011,7 +1031,11 @@ +@@ -1042,7 +1062,11 @@ bool 'Are you using a crosscompiler' CONFIG_CROSSCOMPILE bool 'Enable run-time debugging' CONFIG_RUNTIME_DEBUG @@ -10222,10 +9836,10 @@ diff -Nur linux-2.4.32/arch/mips/config-shared.in linux-2.4.32-brcm/arch/mips/co dep_bool ' Console output to GDB' CONFIG_GDB_CONSOLE $CONFIG_KGDB if [ "$CONFIG_KGDB" = "y" ]; then define_bool CONFIG_DEBUG_INFO y -diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/kernel/cpu-probe.c ---- linux-2.4.32/arch/mips/kernel/cpu-probe.c 2005-01-19 15:09:29.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/kernel/cpu-probe.c 2005-12-16 23:39:11.084845500 +0100 -@@ -174,7 +174,7 @@ +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) { @@ -10234,7 +9848,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/ case PRID_IMP_R2000: c->cputype = CPU_R2000; c->isa_level = MIPS_CPU_ISA_I; -@@ -184,7 +184,7 @@ +@@ -172,7 +172,7 @@ c->tlbsize = 64; break; case PRID_IMP_R3000: @@ -10243,7 +9857,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/ if (cpu_has_confreg()) c->cputype = CPU_R3081E; else -@@ -199,12 +199,12 @@ +@@ -187,12 +187,12 @@ break; case PRID_IMP_R4000: if (read_c0_config() & CONF_SC) { @@ -10258,7 +9872,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/ c->cputype = CPU_R4400SC; else c->cputype = CPU_R4000SC; -@@ -450,7 +450,7 @@ +@@ -438,7 +438,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c) { decode_config1(c); @@ -10267,7 +9881,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/ case PRID_IMP_4KC: c->cputype = CPU_4KC; c->isa_level = MIPS_CPU_ISA_M32; -@@ -491,10 +491,10 @@ +@@ -479,10 +479,10 @@ { decode_config1(c); c->options |= MIPS_CPU_PREFETCH; @@ -10280,7 +9894,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/ case 0: c->cputype = CPU_AU1000; break; -@@ -522,10 +522,34 @@ +@@ -510,10 +510,34 @@ } } @@ -10316,7 +9930,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/ case PRID_IMP_SB1: c->cputype = CPU_SB1; c->isa_level = MIPS_CPU_ISA_M64; -@@ -547,7 +571,7 @@ +@@ -535,7 +559,7 @@ static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c) { decode_config1(c); @@ -10325,7 +9939,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/ case PRID_IMP_SR71000: c->cputype = CPU_SR71000; c->isa_level = MIPS_CPU_ISA_M64; -@@ -572,7 +596,7 @@ +@@ -560,7 +584,7 @@ c->cputype = CPU_UNKNOWN; c->processor_id = read_c0_prid(); @@ -10334,7 +9948,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/ case PRID_COMP_LEGACY: cpu_probe_legacy(c); -@@ -583,6 +607,9 @@ +@@ -571,6 +595,9 @@ case PRID_COMP_ALCHEMY: cpu_probe_alchemy(c); break; @@ -10344,9 +9958,9 @@ diff -Nur linux-2.4.32/arch/mips/kernel/cpu-probe.c linux-2.4.32-brcm/arch/mips/ case PRID_COMP_SIBYTE: cpu_probe_sibyte(c); break; -diff -Nur linux-2.4.32/arch/mips/kernel/head.S linux-2.4.32-brcm/arch/mips/kernel/head.S ---- linux-2.4.32/arch/mips/kernel/head.S 2005-01-19 15:09:29.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/kernel/head.S 2005-12-16 23:39:11.084845500 +0100 +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 @@ -10369,9 +9983,9 @@ diff -Nur linux-2.4.32/arch/mips/kernel/head.S linux-2.4.32-brcm/arch/mips/kerne /* The following two symbols are used for kernel profiling. */ EXPORT(stext) -diff -Nur linux-2.4.32/arch/mips/kernel/proc.c linux-2.4.32-brcm/arch/mips/kernel/proc.c ---- linux-2.4.32/arch/mips/kernel/proc.c 2005-01-19 15:09:29.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/kernel/proc.c 2005-12-16 23:39:11.084845500 +0100 +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", @@ -10384,10 +9998,10 @@ diff -Nur linux-2.4.32/arch/mips/kernel/proc.c linux-2.4.32-brcm/arch/mips/kerne static int show_cpuinfo(struct seq_file *m, void *v) { unsigned int version = current_cpu_data.processor_id; -diff -Nur linux-2.4.32/arch/mips/kernel/setup.c linux-2.4.32-brcm/arch/mips/kernel/setup.c ---- linux-2.4.32/arch/mips/kernel/setup.c 2005-01-19 15:09:29.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/kernel/setup.c 2005-12-16 23:39:11.140849000 +0100 -@@ -495,6 +495,7 @@ +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); @@ -10395,7 +10009,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/setup.c linux-2.4.32-brcm/arch/mips/kern void frame_info_init(void); frame_info_init(); -@@ -693,6 +694,11 @@ +@@ -691,6 +692,11 @@ pmc_yosemite_setup(); break; #endif @@ -10407,10 +10021,10 @@ diff -Nur linux-2.4.32/arch/mips/kernel/setup.c linux-2.4.32-brcm/arch/mips/kern default: panic("Unsupported architecture"); } -diff -Nur linux-2.4.32/arch/mips/kernel/traps.c linux-2.4.32-brcm/arch/mips/kernel/traps.c ---- linux-2.4.32/arch/mips/kernel/traps.c 2005-01-19 15:09:29.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/kernel/traps.c 2005-12-16 23:39:11.140849000 +0100 -@@ -913,6 +913,7 @@ +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; @@ -10418,7 +10032,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/traps.c linux-2.4.32-brcm/arch/mips/kern extern char except_vec3_generic, except_vec3_r4000; extern char except_vec_ejtag_debug; extern char except_vec4; -@@ -922,6 +923,7 @@ +@@ -927,6 +928,7 @@ /* Copy the generic exception handler code to it's final destination. */ memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80); @@ -10426,7 +10040,7 @@ diff -Nur linux-2.4.32/arch/mips/kernel/traps.c linux-2.4.32-brcm/arch/mips/kern /* * Setup default vectors -@@ -980,6 +982,12 @@ +@@ -985,6 +987,12 @@ set_except_vector(13, handle_tr); set_except_vector(22, handle_mdmx); @@ -10439,41 +10053,10 @@ diff -Nur linux-2.4.32/arch/mips/kernel/traps.c linux-2.4.32-brcm/arch/mips/kern if (cpu_has_fpu && !cpu_has_nofpuex) set_except_vector(15, handle_fpe); -diff -Nur linux-2.4.32/arch/mips/Makefile linux-2.4.32-brcm/arch/mips/Makefile ---- linux-2.4.32/arch/mips/Makefile 2005-01-19 15:09:26.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/Makefile 2005-12-16 23:39:10.668819500 +0100 -@@ -715,6 +715,19 @@ - endif - - # -+# Broadcom BCM947XX variants -+# -+ifdef CONFIG_BCM947XX -+LIBS += arch/mips/bcm947xx/generic/brcm.o arch/mips/bcm947xx/bcm947xx.o -+SUBDIRS += arch/mips/bcm947xx/generic arch/mips/bcm947xx -+LOADADDR := 0x80001000 -+ -+zImage: vmlinux -+ $(MAKE) -C arch/$(ARCH)/bcm947xx/compressed -+export LOADADDR -+endif -+ -+# - # Choosing incompatible machines durings configuration will result in - # error messages during linking. Select a default linkscript if - # none has been choosen above. -@@ -767,6 +780,7 @@ - $(MAKE) -C arch/$(ARCH)/tools clean - $(MAKE) -C arch/mips/baget clean - $(MAKE) -C arch/mips/lasat clean -+ $(MAKE) -C arch/mips/bcm947xx/compressed clean - - archmrproper: - @$(MAKEBOOT) mrproper -diff -Nur linux-2.4.32/arch/mips/mm/c-r4k.c linux-2.4.32-brcm/arch/mips/mm/c-r4k.c ---- linux-2.4.32/arch/mips/mm/c-r4k.c 2005-01-19 15:09:29.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/mm/c-r4k.c 2005-12-16 23:39:11.144849250 +0100 -@@ -1114,3 +1114,47 @@ +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(); } @@ -10521,9 +10104,9 @@ diff -Nur linux-2.4.32/arch/mips/mm/c-r4k.c linux-2.4.32-brcm/arch/mips/mm/c-r4k +} + + -diff -Nur linux-2.4.32/arch/mips/pci/Makefile linux-2.4.32-brcm/arch/mips/pci/Makefile ---- linux-2.4.32/arch/mips/pci/Makefile 2005-01-19 15:09:29.000000000 +0100 -+++ linux-2.4.32-brcm/arch/mips/pci/Makefile 2005-12-16 23:39:11.144849250 +0100 +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 @@ -10534,10 +10117,10 @@ diff -Nur linux-2.4.32/arch/mips/pci/Makefile linux-2.4.32-brcm/arch/mips/pci/Ma obj-$(CONFIG_PCI_AUTO) += pci_auto.o include $(TOPDIR)/Rules.make -diff -Nur linux-2.4.32/drivers/char/serial.c linux-2.4.32-brcm/drivers/char/serial.c ---- linux-2.4.32/drivers/char/serial.c 2005-11-16 20:12:54.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/char/serial.c 2005-12-16 23:39:11.200852750 +0100 -@@ -422,6 +422,10 @@ +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: @@ -10548,7 +10131,7 @@ diff -Nur linux-2.4.32/drivers/char/serial.c linux-2.4.32-brcm/drivers/char/seri return readb((unsigned long) info->iomem_base + (offset<iomem_reg_shift)); default: -@@ -442,6 +446,9 @@ +@@ -464,6 +468,9 @@ case SERIAL_IO_MEM: writeb(value, (unsigned long) info->iomem_base + (offset<iomem_reg_shift)); @@ -10558,7 +10141,7 @@ diff -Nur linux-2.4.32/drivers/char/serial.c linux-2.4.32-brcm/drivers/char/seri break; default: outb(value, info->port+offset); -@@ -1704,7 +1711,7 @@ +@@ -1728,7 +1735,7 @@ /* Special case since 134 is really 134.5 */ quot = (2*baud_base / 269); else if (baud) @@ -10567,7 +10150,7 @@ diff -Nur linux-2.4.32/drivers/char/serial.c linux-2.4.32-brcm/drivers/char/seri } /* If the quotient is zero refuse the change */ if (!quot && old_termios) { -@@ -1721,12 +1728,12 @@ +@@ -1745,12 +1752,12 @@ /* Special case since 134 is really 134.5 */ quot = (2*baud_base / 269); else if (baud) @@ -10582,7 +10165,7 @@ diff -Nur linux-2.4.32/drivers/char/serial.c linux-2.4.32-brcm/drivers/char/seri /* * Work around a bug in the Oxford Semiconductor 952 rev B * chip which causes it to seriously miscalculate baud rates -@@ -5982,6 +5989,13 @@ +@@ -5994,6 +6001,13 @@ * Divisor, bytesize and parity */ state = rs_table + co->index; @@ -10596,7 +10179,7 @@ diff -Nur linux-2.4.32/drivers/char/serial.c linux-2.4.32-brcm/drivers/char/seri if (doflow) state->flags |= ASYNC_CONS_FLOW; info = &async_sercons; -@@ -5995,7 +6009,7 @@ +@@ -6007,7 +6021,7 @@ info->io_type = state->io_type; info->iomem_base = state->iomem_base; info->iomem_reg_shift = state->iomem_reg_shift; @@ -10605,9 +10188,9 @@ diff -Nur linux-2.4.32/drivers/char/serial.c linux-2.4.32-brcm/drivers/char/seri cval = cflag & (CSIZE | CSTOPB); #if defined(__powerpc__) || defined(__alpha__) cval >>= 8; -diff -Nur linux-2.4.32/drivers/net/Config.in linux-2.4.32-brcm/drivers/net/Config.in ---- linux-2.4.32/drivers/net/Config.in 2005-01-19 15:09:56.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/Config.in 2005-12-16 23:39:11.232854750 +0100 +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 # @@ -10617,9 +10200,65 @@ diff -Nur linux-2.4.32/drivers/net/Config.in linux-2.4.32-brcm/drivers/net/Confi source drivers/net/arcnet/Config.in tristate 'Dummy net driver support' CONFIG_DUMMY -diff -Nur linux-2.4.32/drivers/net/hnd/bcmsrom.c linux-2.4.32-brcm/drivers/net/hnd/bcmsrom.c ---- linux-2.4.32/drivers/net/hnd/bcmsrom.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/hnd/bcmsrom.c 2005-12-16 23:39:11.284858000 +0100 +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 . @@ -11559,10 +11198,10 @@ diff -Nur linux-2.4.32/drivers/net/hnd/bcmsrom.c linux-2.4.32-brcm/drivers/net/h + return (rc); +} + -diff -Nur linux-2.4.32/drivers/net/hnd/bcmutils.c linux-2.4.32-brcm/drivers/net/hnd/bcmutils.c ---- linux-2.4.32/drivers/net/hnd/bcmutils.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/hnd/bcmutils.c 2005-12-16 23:39:11.288858250 +0100 -@@ -0,0 +1,1081 @@ +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. + * @@ -11590,254 +11229,48 @@ diff -Nur linux-2.4.32/drivers/net/hnd/bcmutils.c linux-2.4.32-brcm/drivers/net/ +#include + +#ifdef BCMDRIVER -+/* copy a pkt buffer chain into a buffer */ -+uint -+pktcopy(osl_t *osh, void *p, uint offset, int len, 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); -+ } -+ -+ if (!p) -+ 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; -+ } ++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 */ ++}; + -+ return ret; ++uchar ++bcm_toupper(uchar c) ++{ ++ if (bcm_islower(c)) ++ c -= 'a'-'A'; ++ return (c); +} + -+/* return total length of buffer chain */ -+uint -+pkttotlen(osl_t *osh, void *p) ++ulong ++bcm_strtoul(char *cp, char **endp, uint base) +{ -+ uint total; -+ -+ total = 0; -+ for (; p; p = PKTNEXT(osh, p)) -+ total += PKTLEN(osh, p); -+ return (total); -+} -+ -+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; -+} -+ -+/* should always check pktq_full before calling pktenq */ -+void -+pktenq(struct pktq *q, void *p, bool lifo) -+{ -+ void *next, *prev; -+ -+ /* allow 10 pkts slack */ -+ ASSERT(q->len < (q->maxlen + 10)); -+ -+ /* Queueing chains not allowed */ -+ ASSERT(PKTLINK(p) == NULL); -+ -+ /* Queue is empty */ -+ if (q->tail == NULL) { -+ ASSERT(q->head == NULL); -+ q->head = q->tail = p; -+ } -+ -+ /* 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; -+ } -+ } -+ -+ /* 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; -+ } -+ } -+ -+ /* List invariants after insertion */ -+ ASSERT(q->head); -+ ASSERT(PKTLINK(q->tail) == NULL); -+ -+ q->len++; -+} -+ -+/* dequeue packet at head */ -+void* -+pktdeq(struct pktq *q) -+{ -+ void *p; -+ -+ 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); -+ } -+ -+ return (p); -+} -+ -+/* dequeue packet at tail */ -+void* -+pktdeqtail(struct pktq *q) -+{ -+ void *p; -+ void *next, *prev; -+ -+ 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); -+ } -+ -+ /* start walk at head */ -+ prev = NULL; -+ next = q->head; -+ -+ /* Walk the queue to find prev of q->tail */ -+ for (; next; prev = next, next = PKTLINK(next)) { -+ if (next == q->tail) -+ break; -+ } -+ -+ ASSERT(prev); -+ -+ PKTSETLINK(prev, NULL); -+ q->tail = prev; -+ q->len--; -+ p = next; -+ -+ return (p); -+} -+ -+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; ++ ulong result, value; ++ bool minus; ++ ++ minus = FALSE; + + while (bcm_isspace(*cp)) + cp++; @@ -12393,2530 +11826,5655 @@ diff -Nur linux-2.4.32/drivers/net/hnd/bcmutils.c linux-2.4.32-brcm/drivers/net/ + return crc; +} + -+#ifdef notdef -+#define CLEN 1499 -+#define CBUFSIZ (CLEN+4) -+#define CNBUFS 5 ++#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) ++{ ++ 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]; ++} ++ ++osl_t * ++osl_attach(void *pdev) ++{ ++ osl_t *osh; ++ ++ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); ++ ASSERT(osh); ++ ++ /* ++ * 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; ++ ++ return osh; ++} ++ ++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) ++{ ++ 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); ++} ++ ++void ++osl_pktfree(void *p) ++{ ++ struct sk_buff *skb, *nskb; ++ ++ skb = (struct sk_buff*) p; ++ ++ /* 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); ++ } ++ 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--); ++ ++ ++ return (val); ++} ++ ++void ++osl_pci_write_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_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--); ++ ++} ++ ++/* 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); ++ ++ return ((struct pci_dev *)osh->pdev)->bus->number; ++} ++ ++/* return slot # for the pci device pointed by osh->pdev */ ++uint ++osl_pci_slot(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); ++} ++ ++static void ++osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) ++{ ++} ++ ++void ++osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); ++} ++ ++void ++osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); ++} ++ ++ ++#ifdef BCMDBG_MEM ++ ++void* ++osl_debug_malloc(osl_t *osh, uint size, int line, char* file) ++{ ++ 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; ++} ++ ++void ++osl_debug_mfree(osl_t *osh, void *addr, uint size, int line, char* file) ++{ ++ bcm_mem_link_t *p = (bcm_mem_link_t *)((int8*)addr - sizeof(bcm_mem_link_t)); ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_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 (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; ++ } ++ ++ /* 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; ++ ++ 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); ++ ++ return (obuf); ++} ++ ++#endif /* BCMDBG_MEM */ ++ ++void* ++osl_malloc(osl_t *osh, uint size) ++{ ++ void *addr; ++ ++ /* only ASSERT if osh is defined */ ++ if (osh) ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ ++ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { ++ if(osh) ++ osh->failed++; ++ return (NULL); ++ } ++ 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); ++} ++ ++uint ++osl_malloced(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (osh->malloced); ++} ++ ++uint osl_malloc_failed(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (osh->failed); ++} ++ ++void* ++osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); ++} ++ ++void ++osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); ++} ++ ++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)); ++} ++ ++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); ++} ++ ++#if defined(BINOSL) ++void ++osl_assert(char *exp, char *file, int line) ++{ ++ char tempbuf[255]; ++ ++ sprintf(tempbuf, "assertion \"%s\" failed: file \"%s\", line %d\n", exp, file, line); ++ panic(tempbuf); ++} ++#endif /* BCMDBG || BINOSL */ ++ ++void ++osl_delay(uint usec) ++{ ++ uint d; ++ ++ while (usec > 0) { ++ d = MIN(usec, 1000); ++ udelay(d); ++ usec -= d; ++ } ++} ++ ++/* ++ * 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); ++} ++ ++int ++osl_strcmp(const char *s1, const char *s2) ++{ ++ return (strcmp(s1, s2)); ++} ++ ++int ++osl_strncmp(const char *s1, const char *s2, uint n) ++{ ++ return (strncmp(s1, s2, n)); ++} ++ ++int ++osl_strlen(const char *s) ++{ ++ return (strlen(s)); ++} ++ ++char* ++osl_strcpy(char *d, const char *s) ++{ ++ return (strcpy(d, s)); ++} ++ ++char* ++osl_strncpy(char *d, const char *s, uint n) ++{ ++ return (strncpy(d, s, n)); ++} ++ ++void ++bcopy(const void *src, void *dst, int len) ++{ ++ memcpy(dst, src, len); ++} ++ ++int ++bcmp(const void *b1, const void *b2, int len) ++{ ++ return (memcmp(b1, b2, len)); ++} ++ ++void ++bzero(void *b, int len) ++{ ++ memset(b, '\0', len); ++} ++ ++uint32 ++osl_readl(volatile uint32 *r) ++{ ++ return (readl(r)); ++} ++ ++uint16 ++osl_readw(volatile uint16 *r) ++{ ++ return (readw(r)); ++} ++ ++uint8 ++osl_readb(volatile uint8 *r) ++{ ++ return (readb(r)); ++} ++ ++void ++osl_writel(uint32 v, volatile uint32 *r) ++{ ++ writel(v, r); ++} ++ ++void ++osl_writew(uint16 v, volatile uint16 *r) ++{ ++ writew(v, r); ++} ++ ++void ++osl_writeb(uint8 v, volatile uint8 *r) ++{ ++ writeb(v, r); ++} ++ ++void * ++osl_uncached(void *va) ++{ ++#ifdef mips ++ return ((void*)KSEG1ADDR(va)); ++#else ++ return ((void*)va); ++#endif ++} ++ ++uint ++osl_getcycles(void) ++{ ++ uint cycles; ++ ++#if defined(mips) ++ cycles = read_c0_count() * 2; ++#elif defined(__i386__) ++ rdtscl(cycles); ++#else ++ cycles = 0; ++#endif ++ return cycles; ++} ++ ++void * ++osl_reg_map(uint32 pa, uint size) ++{ ++ return (ioremap_nocache((unsigned long)pa, (unsigned long)size)); ++} ++ ++void ++osl_reg_unmap(void *va) ++{ ++ iounmap(va); ++} ++ ++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) ++{ ++ return (((struct sk_buff*)skb)->data); ++} ++ ++uint ++osl_pktlen(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->len); ++} ++ ++uint ++osl_pktheadroom(osl_t *osh, void *skb) ++{ ++ return (uint) skb_headroom((struct sk_buff *) skb); ++} ++ ++uint ++osl_pkttailroom(osl_t *osh, void *skb) ++{ ++ return (uint) skb_tailroom((struct sk_buff *) skb); ++} ++ ++void* ++osl_pktnext(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->next); ++} ++ ++void ++osl_pktsetnext(void *skb, void *x) ++{ ++ ((struct sk_buff*)skb)->next = (struct sk_buff*)x; ++} ++ ++void ++osl_pktsetlen(osl_t *osh, void *skb, uint len) ++{ ++ __skb_trim((struct sk_buff*)skb, len); ++} ++ ++uchar* ++osl_pktpush(osl_t *osh, void *skb, int bytes) ++{ ++ return (skb_push((struct sk_buff*)skb, bytes)); ++} ++ ++uchar* ++osl_pktpull(osl_t *osh, void *skb, int bytes) ++{ ++ return (skb_pull((struct sk_buff*)skb, bytes)); ++} ++ ++void* ++osl_pktdup(osl_t *osh, void *skb) ++{ ++ return (skb_clone((struct sk_buff*)skb, GFP_ATOMIC)); ++} ++ ++void* ++osl_pktcookie(void *skb) ++{ ++ return ((void*)((struct sk_buff*)skb)->csum); ++} ++ ++void ++osl_pktsetcookie(void *skb, void *x) ++{ ++ ((struct sk_buff*)skb)->csum = (uint)x; ++} ++ ++void* ++osl_pktlink(void *skb) ++{ ++ return (((struct sk_buff*)skb)->prev); ++} ++ ++void ++osl_pktsetlink(void *skb, void *x) ++{ ++ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x; ++} ++ ++uint ++osl_pktprio(void *skb) ++{ ++ return (((struct sk_buff*)skb)->priority); ++} ++ ++void ++osl_pktsetprio(void *skb, uint x) ++{ ++ ((struct sk_buff*)skb)->priority = x; ++} ++ ++ ++#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 @@ ++/* ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom 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$ ++ */ ++ ++#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 { ++ ++ struct sb_pub sb; /* back plane public state(must be first field of sb_info */ ++ ++ void *osh; /* osl os handle */ ++ void *sdh; /* bcmsdh handle */ ++ ++ void *curmap; /* current regs va */ ++ void *regs[SB_MAXCORES]; /* other regs va */ ++ ++ uint curidx; /* current core index */ ++ uint dev_coreid; /* the core provides driver functions */ ++ ++ bool memseg; /* flag to toggle MEM_SEG register */ ++ ++ uint gpioidx; /* gpio control core index */ ++ uint gpioid; /* gpio control coretype */ ++ ++ uint numcores; /* # discovered cores */ ++ uint coreid[SB_MAXCORES]; /* id of each core */ ++ ++ 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 */ ++ ++} sb_info_t; ++ ++/* 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); ++ ++/* 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); ++ ++/* delay needed between the mdio control/ mdiodata register data access */ ++#define PR28829_DELAY() OSL_DELAY(10) ++ ++ ++/* global variable to indicate reservation/release of gpio's*/ ++static uint32 sb_gpioreservation = 0; ++ ++#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 ++ ++#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) ++ ++#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))) ++ ++/* ++ * 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); } ++ ++/* 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 */ ++ ++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ ++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ ++ ++#define MIN_DUMPBUFLEN 32 /* debug */ ++ ++/* different register spaces to access thr'u pcie indirect access*/ ++#define PCIE_CONFIGREGS 1 ++#define PCIE_PCIEREGS 2 ++ ++/* GPIO Based LED powersave defines */ ++#define DEFAULT_GPIO_ONTIME 10 ++#define DEFAULT_GPIO_OFFTIME 90 ++ ++#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) ++ ++static uint32 ++sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr) ++{ ++ uint8 tmp; ++ uint32 val, 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*/ ++ } ++ ++ val = R_REG(sbr); ++ ++ if(si->memseg) { ++ tmp = 0; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); ++ INTR_RESTORE(si, intr_val); ++ } ++ ++ return (val); ++} ++ ++static void ++sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v) ++{ ++ 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); ++ ++ if(si->memseg) { ++ tmp = 0; ++ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); ++ INTR_RESTORE(si, intr_val); ++ } ++} ++ ++/* ++ * 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) ++{ ++ 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); ++ } ++ ++ if (BCMINIT(sb_doattach)(si, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { ++ MFREE(osh, si, sizeof (sb_info_t)); ++ return (NULL); ++ } ++ return (sb_t *)si; ++} ++ ++/* 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)() ++{ ++ uint32 *regs; ++ ++ if (ksi.curmap == NULL) { ++ uint32 cid; ++ ++ 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; ++ ++ 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); ++ } ++ ++ if (BCMINIT(sb_doattach)(&ksi, BCM4710_DEVICE_ID, NULL, (void*)regs, ++ SB_BUS, NULL, NULL, NULL) == NULL) { ++ return NULL; ++ } ++ } ++ ++ return (sb_t *)&ksi; ++} ++#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) ++{ ++ uint origidx; ++ chipcregs_t *cc; ++ sbconfig_t *sb; ++ uint32 w; ++ ++ ASSERT(GOODREGS(regs)); ++ ++ bzero((uchar*)si, sizeof (sb_info_t)); ++ ++ si->sb.buscoreidx = si->gpioidx = BADIDX; ++ ++ si->osh = osh; ++ si->curmap = regs; ++ si->sdh = sdh; ++ ++ /* 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; ++ } ++ ++ 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; ++ } ++ ++ /* need to set memseg flag for CF card first before any sb registers access */ ++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) ++ si->memseg = TRUE; ++ ++ /* 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(osh, PCI_BAR0_WIN, sizeof (uint32)); ++ if (!GOODCOREADDR(w)) ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32), SB_ENUM_BASE); ++ } ++ ++ /* initialize current core index value */ ++ si->curidx = _sb_coreidx(si); ++ ++ if (si->curidx == BADIDX) { ++ SB_ERROR(("sb_doattach: bad core index\n")); ++ return NULL; ++ } ++ ++ /* get sonics backplane revision */ ++ sb = REGS2SB(si->curmap); ++ si->sb.sonicsrev = (R_SBREG(si, &(sb)->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT; ++ ++ /* keep and reuse the initial register mapping */ ++ origidx = si->curidx; ++ if (BUSTYPE(si->sb.bustype) == SB_BUS) ++ si->regs[origidx] = regs; ++ ++ /* 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(&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; ++ ++ /* 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; ++ } ++ } ++ ++ /* get chipcommon rev */ ++ si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV; ++ ++ /* 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); ++ ++ /* return to original core */ ++ sb_setcoreidx(&si->sb, origidx); ++ ++ /* sanity checks */ ++ ASSERT(si->sb.chip); ++ ++ /* scan for cores */ ++ BCMINIT(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, 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; ++ } ++ ++ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { ++ w = getintvar(*vars, "regwindowsz"); ++ si->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE; ++ } ++ ++ /* gpio control core is required */ ++ if (!GOODIDX(si->gpioidx)) { ++ SB_ERROR(("sb_doattach: gpio control core not found\n")); ++ return NULL; ++ } ++ ++ /* 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; ++ ++ case PCMCIA_BUS: ++ case SDIO_BUS: ++ si->sb.boardvendor = getintvar(*vars, "manfid"); ++ si->sb.boardtype = getintvar(*vars, "prodid"); ++ break; ++ ++ case SB_BUS: ++ case JTAG_BUS: ++ si->sb.boardvendor = VENDOR_BROADCOM; ++ if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0) ++ si->sb.boardtype = 0xffff; ++ break; ++ } ++ ++ if (si->sb.boardtype == 0) { ++ SB_ERROR(("sb_doattach: unknown board type\n")); ++ ASSERT(si->sb.boardtype); ++ } ++ ++ /* 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); ++ } ++ ++ ++ return (si); ++} ++ ++uint ++sb_coreid(sb_t *sbh) ++{ ++ sb_info_t *si; ++ sbconfig_t *sb; ++ ++ si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); ++ ++ return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT); ++} ++ ++uint ++sb_coreidx(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->curidx); ++} ++ ++/* return current index of core */ ++static uint ++_sb_coreidx(sb_info_t *si) ++{ ++ sbconfig_t *sb; ++ uint32 sbaddr = 0; ++ ++ ASSERT(si); ++ ++ switch (BUSTYPE(si->sb.bustype)) { ++ case SB_BUS: ++ sb = REGS2SB(si->curmap); ++ sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0)); ++ break; ++ ++ case PCI_BUS: ++ sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32)); ++ break; ++ ++ case PCMCIA_BUS: { ++ uint8 tmp = 0; ++ ++ 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; ++ } ++ ++#ifdef BCMJTAG ++ case JTAG_BUS: ++ sbaddr = (uint32)si->curmap; ++ 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) ++{ ++ sb_info_t *si; ++ sbconfig_t *sb; ++ ++ si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); ++ ++ return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT); ++} ++ ++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); ++ ++ return (SBCOREREV(sbidh)); ++} ++ ++void * ++sb_osh(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return si->osh; ++} ++ ++#define SBTML_ALLOW (SBTML_PE | SBTML_FGC | SBTML_FL_MASK) ++ ++/* 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; ++ ++ si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); ++ ++ ASSERT((val & ~mask) == 0); ++ ASSERT((mask & ~SBTML_ALLOW) == 0); ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val; ++ W_SBREG(si, &sb->sbtmstatelow, w); ++ } ++ ++ /* return the new value */ ++ return (R_SBREG(si, &sb->sbtmstatelow) & SBTML_ALLOW); ++} ++ ++/* 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; ++ ++ si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); ++ ++ ASSERT((val & ~mask) == 0); ++ ASSERT((mask & ~SBTMH_FL_MASK) == 0); ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_SBREG(si, &sb->sbtmstatehigh) & ~mask) | val; ++ W_SBREG(si, &sb->sbtmstatehigh, w); ++ } ++ ++ /* 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; ++ ++ si = SB_INFO(sbh); ++ ++ 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; ++ ++ sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), ~0, sblo); ++ } ++ ++ return result; ++} ++ ++bool ++sb_iscoreup(sb_t *sbh) ++{ ++ sb_info_t *si; ++ sbconfig_t *sb; ++ ++ si = SB_INFO(sbh); ++ sb = REGS2SB(si->curmap); ++ ++ return ((R_SBREG(si, &(sb)->sbtmstatelow) & (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK); ++} ++ ++/* ++ * 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(GOODIDX(coreidx)); ++ ASSERT(regoff < SB_CORE_SIZE); ++ ASSERT((val & ~mask) == 0); ++ ++ INTR_OFF(si, intr_val); ++ ++ /* save current core index */ ++ origidx = sb_coreidx(&si->sb); ++ ++ /* switch core */ ++ r = (uint32*) ((uchar*) sb_setcoreidx(&si->sb, coreidx) + regoff); ++ ++ /* 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); ++ } ++ } ++ ++ /* readback */ ++ if (regoff >= SBCONFIGOFF) ++ w = R_SBREG(si, r); ++ else ++ w = R_REG(r); ++ ++ /* restore core index */ ++ if (origidx != coreidx) ++ sb_setcoreidx(&si->sb, origidx); ++ ++ INTR_RESTORE(si, intr_val); ++ return (w); ++} ++ ++#define DWORD_ALIGN(x) (x & ~(0x03)) ++#define BYTE_POS(x) (x & 0x3) ++#define WORD_POS(x) (x & 0x1) ++ ++#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) ++ ++#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) ++ ++ ++/* 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; ++ ++ /* check for Header type 0*/ ++ byte_val = read_pci_cfg_byte(PCI_CFG_HDR); ++ if ((byte_val & 0x7f) != PCI_HEADER_NORMAL) ++ return FALSE; ++ ++ /* 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; ++ ++ ++ /* loop thr'u the capability list and see if the pcie capabilty exists */ ++ ++ cap_id = read_pci_cfg_byte(cap_ptr); ++ ++ 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; ++} ++ ++/* 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)); ++} ++ ++/* 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; ++ ++ ++ ++ /* numcores should already be set */ ++ ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES)); ++ ++ /* save current core index */ ++ origidx = sb_coreidx(&si->sb); ++ ++ si->sb.buscorerev = NOREV; ++ si->sb.buscoreidx = BADIDX; ++ ++ si->gpioidx = BADIDX; ++ ++ pci = pcie = FALSE; ++ pcirev = pcierev = NOREV; ++ pciidx = pcieidx = BADIDX; ++ ++ for (i = 0; i < si->numcores; i++) { ++ sb_setcoreidx(&si->sb, i); ++ si->coreid[i] = sb_coreid(&si->sb); ++ ++ 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; ++ } ++ ++ /* ++ * 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); ++ ++ /* return to original core index */ ++ sb_setcoreidx(&si->sb, origidx); ++} ++ ++/* may be called with core in reset */ ++void ++sb_detach(sb_t *sbh) ++{ ++ sb_info_t *si; ++ uint idx; ++ ++ si = SB_INFO(sbh); ++ ++ if (si == NULL) ++ return; ++ ++ 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; ++ } ++ ++ if (si != &ksi) ++ MFREE(si->osh, si, sizeof (sb_info_t)); ++} ++ ++/* 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); ++ ++ return (0); ++} ++ ++/* convert chip number to number of i/o cores */ ++static uint ++BCMINITFN(sb_chip2numcores)(uint chip) ++{ ++ 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); ++ ++ 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); ++} ++ ++/* ++ * 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) ++{ ++ 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)); ++ ++ sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE); ++ ++ 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; ++ ++ case PCI_BUS: ++ /* point bar0 window */ ++ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, 4, sbaddr); ++ break; ++ ++ 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 */ ++ } ++ ++ si->curidx = coreidx; ++ ++ return (si->curmap); ++} ++ ++/* ++ * 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 ++BCMINITFN(sb_chip)(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->sb.chip); ++} ++ ++/* return chip revision number */ ++uint ++BCMINITFN(sb_chiprev)(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->sb.chiprev); ++} ++ ++/* return chip common revision number */ ++uint ++BCMINITFN(sb_chipcrev)(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->sb.ccrev); ++} ++ ++/* return chip package option */ ++uint ++BCMINITFN(sb_chippkg)(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->sb.chippkg); ++} ++ ++/* return PCI core rev. */ ++uint ++BCMINITFN(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; ++ ++ si = SB_INFO(sbh); ++ ++ return (PCI(si) && (si->sb.buscorerev <= 10)); ++} ++ ++static void ++BCMINITFN(sb_war30841)(sb_info_t *si) ++{ ++ 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 PCMCIA core rev. */ ++uint ++BCMINITFN(sb_pcmciarev)(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->sb.buscorerev); ++} ++ ++/* return board vendor id */ ++uint ++BCMINITFN(sb_boardvendor)(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->sb.boardvendor); ++} ++ ++/* return boardtype */ ++uint ++BCMINITFN(sb_boardtype)(sb_t *sbh) ++{ ++ sb_info_t *si; ++ char *var; ++ ++ si = SB_INFO(sbh); ++ ++ if (BUSTYPE(si->sb.bustype) == SB_BUS && si->sb.boardtype == 0xffff) { ++ /* boardtype format is a hex string */ ++ si->sb.boardtype = getintvar(NULL, "boardtype"); ++ ++ /* 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 (si->sb.boardtype); ++} ++ ++/* return bus type of sbh device */ ++uint ++sb_bus(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ return (si->sb.bustype); ++} ++ ++/* return bus core type */ ++uint ++sb_buscoretype(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ ++ return (si->sb.buscoretype); ++} ++ ++/* return bus core revision */ ++uint ++sb_buscorerev(sb_t *sbh) ++{ ++ sb_info_t *si; ++ si = SB_INFO(sbh); ++ ++ return (si->sb.buscorerev); ++} ++ ++/* return list of found cores */ ++uint ++sb_corelist(sb_t *sbh, uint coreid[]) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ ++ bcopy((uchar*)si->coreid, (uchar*)coreid, (si->numcores * sizeof (uint))); ++ return (si->numcores); ++} ++ ++/* return current register mapping */ ++void * ++sb_coreregs(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ ASSERT(GOODREGS(si->curmap)); ++ ++ return (si->curmap); ++} ++ ++ ++/* do buffered registers update */ ++void ++sb_commit(sb_t *sbh) ++{ ++ sb_info_t *si; ++ uint origidx; ++ uint intr_val = 0; ++ ++ si = SB_INFO(sbh); ++ ++ 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(&ccregs->broadcastaddress, SB_COMMIT); ++ W_REG(&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(&pciregs->bcastaddr, SB_COMMIT); ++ W_REG(&pciregs->bcastdata, 0x0); ++ } else ++ ASSERT(0); ++ ++ /* restore core index */ ++ sb_setcoreidx(sbh, origidx); ++ INTR_RESTORE(si, intr_val); ++} ++ ++/* 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; ++ ++ si = SB_INFO(sbh); ++ ASSERT(GOODREGS(si->curmap)); ++ sb = REGS2SB(si->curmap); ++ ++ /* ++ * Must do the disable sequence first to work for arbitrary current core state. ++ */ ++ sb_core_disable(sbh, bits); ++ ++ /* ++ * Now do the initialization sequence. ++ */ ++ ++ /* 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); ++ ++ 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)); ++ } ++ ++ /* 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); ++ ++ /* leave clock enabled */ ++ W_SBREG(si, &sb->sbtmstatelow, (SBTML_CLK | bits)); ++ dummy = R_SBREG(si, &sb->sbtmstatelow); ++ OSL_DELAY(1); ++} ++ ++void ++sb_core_tofixup(sb_t *sbh) ++{ ++ sb_info_t *si; ++ sbconfig_t *sb; ++ ++ 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); ++ } ++ } ++ ++ sb_commit(sbh); ++} ++ ++/* ++ * 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) ++{ ++ sb_info_t *si; ++ uint origidx, idx; ++ uint intr_val = 0; ++ uint32 tmp, ret = 0xffffffff; ++ sbconfig_t *sb; ++ ++ si = SB_INFO(sbh); ++ ++ if ((to & ~TO_MASK) != 0) ++ return ret; ++ ++ /* 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; ++ ++ INTR_OFF(si, intr_val); ++ origidx = sb_coreidx(sbh); ++ ++ sb = REGS2SB(sb_setcoreidx(sbh, idx)); ++ ++ 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; ++} ++ ++void ++sb_core_disable(sb_t *sbh, uint32 bits) ++{ ++ sb_info_t *si; ++ volatile uint32 dummy; ++ uint32 rej; ++ sbconfig_t *sb; ++ ++ si = SB_INFO(sbh); ++ ++ ASSERT(GOODREGS(si->curmap)); ++ sb = REGS2SB(si->curmap); ++ ++ /* if core is already in reset, just return */ ++ if (R_SBREG(si, &sb->sbtmstatelow) & SBTML_RESET) ++ return; ++ ++ /* 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); ++ ++ /* if clocks are not enabled, put into reset and return */ ++ if ((R_SBREG(si, &sb->sbtmstatelow) & SBTML_CLK) == 0) ++ goto disable; ++ ++ /* 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->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); ++ } ++ ++ /* 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); ++ ++ /* don't forget to clear the initiator reject bit */ ++ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) ++ AND_SBREG(si, &sb->sbimstate, ~SBIM_RJ); ++ ++disable: ++ /* leave reset and reject asserted */ ++ W_SBREG(si, &sb->sbtmstatelow, (bits | rej | SBTML_RESET)); ++ OSL_DELAY(1); ++} ++ ++/* 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); ++ ++ /* instant NMI */ ++ switch (si->gpioid) { ++ case SB_CC: ++ sb_corereg(si, 0, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); ++ break; ++ case SB_EXTIF: ++ sb_corereg(si, si->gpioidx, OFFSETOF(extifregs_t, watchdog), ~0, ticks); ++ break; ++ } ++} ++ ++/* initialize the pcmcia core */ ++void ++sb_pcmcia_init(sb_t *sbh) ++{ ++ sb_info_t *si; ++ uint8 cor; ++ ++ si = SB_INFO(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); ++ } ++ ++} ++ ++ ++/* ++ * Configure the pci core for pci client (NIC) action ++ * coremask is the bitvec of cores by index to be enabled. ++ */ ++void ++sb_pci_setup(sb_t *sbh, uint coremask) ++{ ++ sb_info_t *si; ++ sbconfig_t *sb; ++ sbpciregs_t *pciregs; ++ uint32 sbflag; ++ uint32 w; ++ uint idx; ++ int reg_val; ++ ++ si = SB_INFO(sbh); ++ ++ /* if not pci bus, we're done */ ++ if (BUSTYPE(si->sb.bustype) != PCI_BUS) ++ return; ++ ++ ASSERT(PCI(si) || PCIE(si)); ++ ASSERT(si->sb.buscoreidx != BADIDX); ++ ++ /* get current core index */ ++ idx = si->curidx; ++ ++ /* we interrupt on this backplane flag number */ ++ ASSERT(GOODREGS(si->curmap)); ++ sb = REGS2SB(si->curmap); ++ sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK; ++ ++ /* switch over to pci core */ ++ pciregs = (sbpciregs_t*) sb_setcoreidx(sbh, si->sb.buscoreidx); ++ sb = REGS2SB(pciregs); ++ ++ /* ++ * 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(&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); ++ } ++ } ++ ++ 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); ++ ++ 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); ++ ++ BCMINIT(sb_war30841)(si); ++ } ++ ++ /* switch back to previous core */ ++ sb_setcoreidx(sbh, idx); ++} ++ ++uint32 ++sb_base(uint32 admatch) ++{ ++ uint32 base; ++ uint type; ++ ++ type = admatch & SBAM_TYPE_MASK; ++ ASSERT(type < 3); ++ ++ base = 0; ++ ++ 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) ++{ ++ 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); ++} ++ ++/* 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; ++ ++ si = SB_INFO(sbh); ++ coreunit = 0; ++ ++ idx = si->curidx; ++ ++ ASSERT(GOODREGS(si->curmap)); ++ coreid = sb_coreid(sbh); ++ ++ /* count the cores of our type */ ++ for (i = 0; i < idx; i++) ++ if (si->coreid[i] == coreid) ++ coreunit++; ++ ++ return (coreunit); ++} ++ ++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; ++ } ++} ++ ++/* 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) ++{ ++ uint32 n1, n2, clock, m1, m2, m3, mc; ++ ++ 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; ++ } ++ 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; ++ ++ return(clock); ++ } ++} ++ ++/* returns the current speed the SB is running at */ ++uint32 ++sb_clock(sb_t *sbh) ++{ ++ sb_info_t *si; ++ extifregs_t *eir; ++ chipcregs_t *cc; ++ uint32 n, m; ++ uint idx; ++ uint32 pll_type, rate; ++ uint intr_val = 0; ++ ++ si = SB_INFO(sbh); ++ idx = si->curidx; ++ pll_type = PLL_TYPE1; ++ ++ INTR_OFF(si, intr_val); ++ ++ /* 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 { ++ INTR_RESTORE(si, intr_val); ++ return 0; ++ } ++ ++ // 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); ++ if (pll_type == PLL_TYPE3) ++ rate = rate / 2; ++ } ++ ++ /* switch back to previous core */ ++ sb_setcoreidx(sbh, idx); ++ ++ INTR_RESTORE(si, intr_val); ++ ++ return rate; ++} ++ ++/* change logical "focus" to the gpio core for optimized access */ ++void* ++sb_gpiosetcore(sb_t *sbh) ++{ ++ sb_info_t *si; ++ ++ si = SB_INFO(sbh); ++ ++ return (sb_setcoreidx(sbh, si->gpioidx)); ++} ++ ++/* mask&set gpiocontrol bits */ ++uint32 ++sb_gpiocontrol(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 */ ++ ++ /* 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, gpiocontrol); ++ break; ++ ++ case SB_PCI: ++ regoff = OFFSETOF(sbpciregs_t, gpiocontrol); ++ break; ++ ++ case SB_EXTIF: ++ return (0); ++ } ++ ++ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); ++} ++ ++/* mask&set gpio output enable bits */ ++uint32 ++sb_gpioouten(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 */ ++ ++ /* 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, gpioouten); ++ break; ++ ++ case SB_PCI: ++ regoff = OFFSETOF(sbpciregs_t, gpioouten); ++ break; ++ ++ case SB_EXTIF: ++ regoff = OFFSETOF(extifregs_t, gpio[0].outen); ++ break; ++ } ++ ++ 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 */ ++ ++ /* 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, gpioout); ++ break; ++ ++ case SB_PCI: ++ regoff = OFFSETOF(sbpciregs_t, gpioout); ++ break; ++ ++ case SB_EXTIF: ++ regoff = OFFSETOF(extifregs_t, gpio[0].out); ++ break; ++ } ++ ++ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); ++} + -+void testcrc32(void) ++/* reserve one gpio */ ++uint32 ++sb_gpioreserve(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) +{ -+ uint j,k,l; -+ uint8 *buf; -+ uint len[CNBUFS]; -+ uint32 crcr; -+ uint32 crc32tv[CNBUFS] = -+ {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; ++ sb_info_t *si; + -+ ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); ++ si = SB_INFO(sbh); + -+ /* step through all possible alignments */ -+ for (l=0;l<=4;l++) { -+ for (j=0; jsb.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; + } + -+ MFREE(buf, CBUFSIZ*CNBUFS); -+ return; -+} -+#endif ++ /* already reserved */ ++ if (sb_gpioreservation & gpio_bitmask) ++ return -1; ++ /* set reservation */ ++ sb_gpioreservation |= gpio_bitmask; + ++ return sb_gpioreservation; ++} + ++/* release one gpio */ +/* -+ * 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) ++ * 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) +{ -+ int len; ++ sb_info_t *si; + -+ /* validate current elt */ -+ if (!bcm_valid_tlv(elt, *buflen)) -+ return NULL; -+ -+ /* advance to next elt */ -+ len = elt->len; -+ elt = (bcm_tlv_t*)(elt->data + len); -+ *buflen -= (2 + len); -+ -+ /* validate next elt */ -+ if (!bcm_valid_tlv(elt, *buflen)) -+ return NULL; ++ si = SB_INFO(sbh); ++ ++ 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; ++ } + -+ return elt; ++ /* already released */ ++ if (!(sb_gpioreservation & gpio_bitmask)) ++ return -1; ++ ++ /* clear reservation */ ++ sb_gpioreservation &= ~gpio_bitmask; ++ ++ return sb_gpioreservation; +} + -+/* -+ * 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) ++/* return the current gpioin register value */ ++uint32 ++sb_gpioin(sb_t *sbh) +{ -+ bcm_tlv_t *elt; -+ int totlen; ++ sb_info_t *si; ++ uint regoff; + -+ elt = (bcm_tlv_t*)buf; -+ totlen = buflen; ++ si = SB_INFO(sbh); ++ regoff = 0; + -+ /* find tagged parameter */ -+ while (totlen >= 2) { -+ int len = elt->len; ++ switch (si->gpioid) { ++ case SB_CC: ++ regoff = OFFSETOF(chipcregs_t, gpioin); ++ break; + -+ /* validate remaining totlen */ -+ if ((elt->id == key) && (totlen >= (len + 2))) -+ return (elt); ++ case SB_PCI: ++ regoff = OFFSETOF(sbpciregs_t, gpioin); ++ break; + -+ elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); -+ totlen -= (len + 2); ++ case SB_EXTIF: ++ regoff = OFFSETOF(extifregs_t, gpioin); ++ break; + } -+ -+ return NULL; ++ ++ return (sb_corereg(si, si->gpioidx, regoff, 0, 0)); +} + -+/* -+ * 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) ++/* mask&set gpio interrupt polarity bits */ ++uint32 ++sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +{ -+ bcm_tlv_t *elt; -+ int totlen; ++ sb_info_t *si; ++ uint regoff; + -+ elt = (bcm_tlv_t*)buf; -+ totlen = buflen; ++ si = SB_INFO(sbh); ++ regoff = 0; + -+ /* 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); ++ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ + -+ /* validate remaining totlen */ -+ if ((id == key) && (totlen >= (len + 2))) -+ return (elt); ++ /* 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; ++ } + -+ elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); -+ totlen -= (len + 2); ++ 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 NULL; ++ ++ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); +} -+/* 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) ++/* mask&set gpio interrupt mask bits */ ++uint32 ++sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) +{ -+ uint filled_len; -+ uint len; -+ struct fielddesc *cur_ptr; ++ sb_info_t *si; ++ uint regoff; + -+ filled_len = 0; -+ cur_ptr = fielddesc_array; ++ si = SB_INFO(sbh); ++ regoff = 0; + -+ 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++; ++ 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; + } -+ return filled_len; ++ ++ switch (si->gpioid) { ++ case SB_CC: ++ regoff = OFFSETOF(chipcregs_t, gpiointmask); ++ break; ++ ++ case SB_PCI: ++ /* pci gpio implementation does not support interrupt mask */ ++ ASSERT(0); ++ break; ++ ++ case SB_EXTIF: ++ regoff = OFFSETOF(extifregs_t, gpiointmask); ++ break; ++ } ++ ++ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); ++} ++ ++/* assign the gpio to an led */ ++uint32 ++sb_gpioled(sb_t *sbh, uint32 mask, uint32 val) ++{ ++ sb_info_t *si; ++ ++ 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)); +} + -+uint -+bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) ++/* mask&set gpio timer val */ ++uint32 ++sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 gpiotimerval) +{ -+ uint len; -+ -+ len = strlen(name) + 1; -+ -+ if ((len + datalen) > buflen) -+ return 0; -+ -+ strcpy(buf, name); ++ sb_info_t *si; ++ si = SB_INFO(sbh); + -+ /* append data onto the end of the name string */ -+ memcpy(&buf[len], data, datalen); -+ len += datalen; ++ if (si->sb.ccrev < 16) ++ return -1; + -+ return len; ++ return(sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); +} + -+/* 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 ++/* return the slow clock source - LPO, XTAL, or PCI */ ++static uint ++sb_slowclk_src(sb_info_t *si) ++{ ++ chipcregs_t *cc; + -+/* 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 -+}; ++ ASSERT(sb_coreid(&si->sb) == SB_CC); + -+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); ++ 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); +} + -+uint8 -+bcm_mw_to_qdbm(uint16 mw) ++/* return the ILP (slowclock) min or max frequency */ ++static uint ++sb_slowclk_freq(sb_info_t *si, bool max) +{ -+ 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; -+ } ++ chipcregs_t *cc; ++ uint32 slowclk; ++ uint div; + -+ 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; ++ ASSERT(sb_coreid(&si->sb) == SB_CC); + -+ return(qdbm); -+} -diff -Nur linux-2.4.32/drivers/net/hnd/hnddma.c linux-2.4.32-brcm/drivers/net/hnd/hnddma.c ---- linux-2.4.32/drivers/net/hnd/hnddma.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/hnd/hnddma.c 2005-12-16 23:39:11.288858250 +0100 -@@ -0,0 +1,1527 @@ -+/* -+ * 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$ -+ */ ++ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); + -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++ /* shouldn't be here unless we've established the chip has dynamic clk control */ ++ ASSERT(R_REG(&cc->capabilities) & CAP_PWR_CTL); + -+struct dma_info; /* forward declaration */ -+#define di_t struct dma_info ++ 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)); ++ } ++ return (0); ++} + -+#include -+#include ++static void ++sb_clkctl_setdelay(sb_info_t *si, void *chipcregs) ++{ ++ chipcregs_t * cc; ++ uint slowmaxfreq, pll_delay, slowclk; ++ uint pll_on_delay, fref_sel_delay; + -+/* debug/trace */ -+#define DMA_ERROR(args) -+#define DMA_TRACE(args) ++ pll_delay = PLL_DELAY; + -+/* default dma message level (if input msg_level pointer is null in dma_attach()) */ -+static uint dma_msg_level = -+ 0; ++ /* 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; + -+#define MAXNAMEL 8 ++ /* Starting with 4318 it is ILP that is used for the delays */ ++ slowmaxfreq = sb_slowclk_freq(si, (si->sb.ccrev >= 10) ? FALSE : TRUE); + -+/* 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 */ ++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; ++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; + -+ 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 */ ++ cc = (chipcregs_t *)chipcregs; ++ W_REG(&cc->pll_on_delay, pll_on_delay); ++ W_REG(&cc->fref_sel_delay, fref_sel_delay); ++} + -+ 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 */ ++int ++sb_pwrctl_slowclk(void *sbh, bool set, uint *div) ++{ ++ sb_info_t *si; ++ uint origidx; ++ chipcregs_t *cc; ++ uint intr_val = 0; ++ uint err = 0; ++ ++ si = SB_INFO(sbh); + -+ /* 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; ++ /* chipcommon cores prior to rev6 don't support slowclkcontrol */ ++ if (si->sb.ccrev < 6) ++ return 1; + -+#ifdef BCMDMA64 -+#define DMA64_ENAB(di) ((di)->dma64) -+#else -+#define DMA64_ENAB(di) (0) -+#endif ++ /* chipcommon cores rev10 are a whole new ball game */ ++ if (si->sb.ccrev >= 10) ++ return 1; + -+/* 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) ++ 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; ++ } + -+/* macros to convert between byte offsets and indexes */ -+#define B2I(bytes, type) ((bytes) / sizeof(type)) -+#define I2B(index, type) ((index) * sizeof(type)) ++ 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); + -+#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ -+#define PCI32ADDR_HIGH_SHIFT 30 ++done: ++ sb_setcoreidx(sbh, origidx); ++ INTR_RESTORE(si, intr_val); ++ return err; ++} + ++/* initialize power control delay registers */ ++void sb_clkctl_init(sb_t *sbh) ++{ ++ sb_info_t *si; ++ uint origidx; ++ chipcregs_t *cc; + -+/* prototypes */ -+static bool dma_isaddrext(dma_info_t *di); -+static bool dma_alloc(dma_info_t *di, uint direction); ++ si = SB_INFO(sbh); + -+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); ++ origidx = si->curidx; + -+/* 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 ++ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) ++ return; + -+/* 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; ++ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) ++ goto done; + -+typedef struct { -+ uint ddoffset; -+ uint dataoffset; -+} compat_data; ++ /* 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)); + -+static compat_data *ugly_hack = NULL; ++ /* 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); + -+void* -+dma_attold(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) ++done: ++ sb_setcoreidx(sbh, origidx); ++} ++void sb_pwrctl_init(sb_t *sbh) +{ -+ dma32regs_t *dtx = regs; -+ dma32regs_t *drx = dtx + 1; -+ -+ ugly_hack = kmalloc(sizeof(ugly_hack), GFP_KERNEL); -+ ugly_hack->ddoffset = ddoffset; -+ ugly_hack->dataoffset = dataoffset; -+ dma_attach((osl_t *) osh, name, NULL, dtx, drx, ntxd, nrxd, rxbufsize, nrxpost, rxoffset, msg_level); -+ ugly_hack = NULL; ++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; + ++ si = SB_INFO(sbh); ++ fpdelay = 0; ++ origidx = si->curidx; + -+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; ++ INTR_OFF(si, intr_val); + -+ /* allocate private info structure */ -+ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { -+ return (NULL); -+ } -+ bzero((char*)di, sizeof (dma_info_t)); ++ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) ++ goto done; + -+ di->msg_level = msg_level ? msg_level : &dma_msg_level; ++ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) ++ goto done; + -+ if (sbh != NULL) -+ di->dma64 = ((sb_coreflagshi(sbh, 0, 0) & SBTMH_DMA64) == SBTMH_DMA64); ++ slowminfreq = sb_slowclk_freq(si, FALSE); ++ fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) + (slowminfreq - 1)) / slowminfreq; + -+#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); ++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); ++} ++/* 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); + -+ /* init dma reg pointer */ -+ if (di->dma64) { -+ ASSERT(ntxd <= D64MAXDD); -+ ASSERT(nrxd <= D64MAXDD); -+ di->d64txregs = (dma64regs_t *)dmaregstx; -+ di->d64rxregs = (dma64regs_t *)dmaregsrx; ++ switch (BUSTYPE(si->sb.bustype)) { + -+ 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; -+ } + ++ case PCMCIA_BUS: ++ return (0); + -+ /* make a private copy of our callers name */ -+ strncpy(di->name, name, MAXNAMEL); -+ di->name[MAXNAMEL-1] = '\0'; + -+ di->osh = osh; -+ di->sbh = sbh; ++ case PCI_BUS: + -+ /* save tunables */ -+ di->ntxd = ntxd; -+ di->nrxd = nrxd; -+ di->rxbufsize = rxbufsize; -+ di->nrxpost = nrxpost; -+ di->rxoffset = rxoffset; ++ /* pcie core doesn't have any mapping to control the xtal pu */ ++ if (PCIE(si)) ++ return -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 (ugly_hack != NULL) { -+ di->ddoffsetlow = ugly_hack->ddoffset; -+ di->dataoffsetlow = ugly_hack->dataoffset; -+ di->ddoffsethigh = 0; -+ di->dataoffsethigh = 0; -+ } else 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; ++ 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)); ++ ++ /* ++ * 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); ++ ++ 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 { -+ di->ddoffsetlow = SB_PCI_DMA; -+ di->ddoffsethigh = 0; ++ 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->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 ++ ++ default: ++ return (-1); + } + -+ di->addrext = ((ugly_hack == NULL) ? dma_isaddrext(di) : 0); ++ return (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)); ++int sb_pwrctl_xtal(sb_t *sbh, uint what, bool on) ++{ ++return sb_clkctl_xtal(sbh,what,on); ++} + -+ /* 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); -+ } ++/* 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) ++{ ++ sb_info_t *si; ++ uint origidx; ++ chipcregs_t *cc; ++ uint32 scc; ++ bool forcefastclk=FALSE; ++ uint intr_val = 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); -+ } ++ si = SB_INFO(sbh); + -+ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ -+ if (ntxd) { -+ if (!dma_alloc(di, DMA_TX)) -+ goto fail; -+ } ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (si->sb.ccrev < 6) ++ return (FALSE); + -+ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ -+ if (nrxd) { -+ if (!dma_alloc(di, DMA_RX)) -+ goto fail; -+ } ++ /* chipcommon cores rev10 are a whole new ball game */ ++ if (si->sb.ccrev >= 10) ++ return (FALSE); + -+ 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; -+ } ++ INTR_OFF(si, intr_val); + -+ return ((void*)di); ++ origidx = si->curidx; + -+fail: -+ dma_detach((void*)di); -+ return (NULL); -+} ++ cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0); ++ ASSERT(cc != 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); -+ } -+} ++ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) ++ goto done; + -+/* may be called with core in reset */ -+void -+dma_detach(dma_info_t *di) -+{ -+ if (di == NULL) -+ return; ++ 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); + -+ DMA_TRACE(("%s: dma_detach\n", di->name)); ++ SET_REG(&cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); ++ break; + -+ /* shouldn't be here if descriptors are unreclaimed */ -+ ASSERT(di->txin == di->txout); -+ ASSERT(di->rxin == di->rxout); ++ 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); + -+ /* 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)); ++ /* for dynamic control, we have to release our xtal_pu "force on" */ ++ if (scc & SCC_XC) ++ sb_clkctl_xtal(&si->sb, XTAL, OFF); ++ break; + -+ /* 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*))); ++ default: ++ ASSERT(0); ++ } + -+ /* free our private info structure */ -+ MFREE(di->osh, (void*)di, sizeof (dma_info_t)); ++ /* Is the h/w forcing the use of the fast clk */ ++ forcefastclk = (bool)((R_REG(&cc->slow_clk_ctl) & SCC_IP) == SCC_IP); ++ ++done: ++ sb_setcoreidx(sbh, origidx); ++ INTR_RESTORE(si, intr_val); ++ return (forcefastclk); +} + -+/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ -+static bool -+dma_isaddrext(dma_info_t *di) ++bool sb_pwrctl_clk(sb_t *sbh, uint mode) +{ -+ 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); -+ } ++return sb_clkctl_clk(sbh, mode); +} -+ ++/* register driver interrupt disabling and restoring callback functions */ +void -+dma_txreset(dma_info_t *di) ++sb_register_intr_callback(sb_t *sbh, void *intrsoff_fn, void *intrsrestore_fn, void *intrsenabled_fn, void *intr_arg) +{ -+ DMA_TRACE(("%s: dma_txreset\n", di->name)); ++ sb_info_t *si; + -+ if (DMA64_ENAB(di)) -+ dma64_txreset(di); -+ else -+ dma32_txreset(di); ++ 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 -+dma_rxreset(dma_info_t *di) ++sb_corepciid(sb_t *sbh, uint16 *pcivendor, uint16 *pcidevice, ++ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif) +{ -+ DMA_TRACE(("%s: dma_rxreset\n", di->name)); ++ 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); + -+ if (DMA64_ENAB(di)) -+ dma64_rxreset(di); -+ else -+ dma32_rxreset(di); -+} ++ chip = BCMINIT(sb_chip)(sbh); ++ chippkg = BCMINIT(sb_chippkg)(sbh); + -+/* 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; ++ progif = 0; + -+ 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)); ++ /* Known vendor translations */ ++ switch (vendor) { ++ case SB_VEND_BCM: ++ vendor = VENDOR_BROADCOM; ++ break; ++ } ++ ++ /* 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; + } + } ++ break; ++ ++ default: ++ class = subclass = progif = 0xff; ++ break; + } ++ ++ *pcivendor = (uint16)vendor; ++ *pcidevice = (uint16)core; ++ *pciclass = class; ++ *pcisubclass = subclass; ++ *pciprogif = progif; +} + -+/* 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; + -+ 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; + -+ *ctrl |= (ae << CTRL_AE_SHIFT); -+ W_SM(&ddring[outidx].addr, BUS_SWAP32((pa & ~PCI32ADDR_HIGH) + offset)); -+ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*ctrl)); -+ } -+} + -+/* 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) ++/* use the mdio interface to write to mdio slaves */ ++static int ++sb_pcie_mdiowrite(sb_info_t *si, uint physmedia, uint regaddr, uint val) +{ -+ uint32 bufaddr_low = pa + di->dataoffsetlow; -+ uint32 bufaddr_high = 0 + di->dataoffsethigh; ++ uint mdiodata; ++ uint i = 0; ++ sbpcieregs_t *pcieregs; + -+ uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; ++ pcieregs = (sbpcieregs_t*) sb_setcoreidx(&si->sb, si->sb.buscoreidx); ++ ASSERT (pcieregs); + -+ 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)); -+} ++ /* enable mdio access to SERDES */ ++ W_REG((&pcieregs->mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); + -+void -+dma_txinit(dma_info_t *di) -+{ -+ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ mdiodata = MDIODATA_START | MDIODATA_WRITE | ++ (physmedia << MDIODATA_DEVADDR_SHF) | ++ (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA | val; + -+ di->txin = di->txout = 0; -+ di->txavail = di->ntxd - 1; ++ W_REG((&pcieregs->mdiodata), mdiodata); + -+ /* 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); -+ } -+} ++ PR28829_DELAY(); + -+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)); ++ /* 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; ++ } ++ OSL_DELAY(1000); ++ i++; + } -+} -+ -+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); -+} + -+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); -+} ++ SB_ERROR(("sb_pcie_mdiowrite: timed out\n")); ++ /* Disable mdio access to SERDES */ ++ W_REG((&pcieregs->mdiocontrol), 0); ++ ASSERT(0); ++ return 1; + -+bool -+dma_txsuspendedidle(dma_info_t *di) -+{ -+ if (DMA64_ENAB(di)) -+ return dma64_txsuspendedidle(di); -+ else -+ return dma32_txsuspendedidle(di); +} + -+bool -+dma_txsuspended(dma_info_t *di) ++/* indirect way to read pcie config regs*/ ++uint ++sb_pcie_readreg(void *sb, void* arg1, uint offset) +{ -+ 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; ++ sb_t *sbh; ++ uint retval = 0xFFFFFFFF; ++ sbpcieregs_t *pcieregs; ++ uint addrtype; + -+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); -+} ++ sbh = (sb_t *)sb; ++ si = SB_INFO(sbh); ++ ASSERT (PCIE(si)); + -+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); -+} ++ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); ++ ASSERT (pcieregs); + -+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); ++ 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; +} + -+void -+dma_rxinit(dma_info_t *di) ++/* indirect way to write pcie config/mdio/pciecore regs*/ ++uint ++sb_pcie_writereg(sb_t *sbh, void *arg1, uint offset, uint val) +{ -+ DMA_TRACE(("%s: dma_rxinit\n", di->name)); -+ -+ di->rxin = di->rxout = 0; ++ sb_info_t *si; ++ sbpcieregs_t *pcieregs; ++ uint addrtype; + -+ /* 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); -+ } -+} ++ si = SB_INFO(sbh); ++ ASSERT (PCIE(si)); + -+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)); -+} ++ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); ++ ASSERT (pcieregs); + -+bool -+dma_rxenabled(dma_info_t *di) -+{ -+ uint32 rc; ++ addrtype = (uint)((uintptr)arg1); + -+ 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)); ++ 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; +} + + -+/* !! tx entry routine */ ++/* Build device path. Support SB, PCI, and JTAG for now. */ +int -+dma_txfast(dma_info_t *di, void *p0, uint32 coreflags) ++sb_devpath(sb_t *sbh, char *path, int size) +{ -+ if (DMA64_ENAB(di)) { -+ return dma64_txfast(di, p0, coreflags); -+ } else { -+ return dma32_txfast(di, p0, coreflags); ++ 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; + } ++ ++ return 0; +} + -+/* !! 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) ++/* Fix chip's configuration. The current core may be changed upon return */ ++static int ++sb_pci_fixcfg(sb_info_t *si) +{ -+ 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; -+ } ++ uint origidx, pciidx; ++ sbpciregs_t *pciregs; ++ sbpcieregs_t *pcieregs; ++ uint16 val16, *reg16; ++ char name[SB_DEVPATH_BUFSZ+16], *value; ++ char devpath[SB_DEVPATH_BUFSZ]; + -+ len = ltoh16(*(uint16*)(PKTDATA(di->osh, p))); -+ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); ++ ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS); + -+ /* 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; -+ } ++ /* Fix PCI(e) SROM shadow area */ ++ /* save the current index */ ++ origidx = sb_coreidx(&si->sb); + -+ /* set actual length */ -+ PKTSETLEN(di->osh, p, (di->rxoffset + len)); ++ /* 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); ++ } + -+ break; ++ /* 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; ++ } + } + -+ return (p); ++ return 0; +} + -+/* post receive buffers */ -+void -+dma_rxfill(dma_info_t *di) -+{ -+ void *p; -+ uint rxin, rxout; -+ uint32 ctrl; -+ uint n; -+ uint i; -+ uint32 pa; -+ uint rxbufsize; +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 $ ++# + -+ /* -+ * Determine how many receive buffers we're lacking -+ * from the full complement, allocate, initialize, -+ * and post them, then update the chip rx lastdscr. -+ */ ++cat < ++#include ++EOF + -+ rxin = di->rxin; -+ rxout = di->rxout; -+ rxbufsize = di->rxbufsize; ++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 $ + -+ n = di->nrxpost - NRXDACTIVE(rxin, rxout); ++EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER + -+ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); ++O_TARGET := wl.o + -+ 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; -+ } ++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 + -+ /* Do a cached write instead of uncached write since DMA_MAP -+ * will flush the cache. */ -+ *(uint32*)(PKTDATA(di->osh, p)) = 0; ++obj-m := $(O_TARGET) + -+ pa = (uint32) DMA_MAP(di->osh, PKTDATA(di->osh, p), rxbufsize, DMA_RX, p); -+ ASSERT(ISALIGNED(pa, 4)); ++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$ ++ */ + -+ /* save the free packet pointer */ -+ ASSERT(di->rxp[rxout] == NULL); -+ di->rxp[rxout] = p; ++#include ++#ifdef BCMDRIVER ++#include ++#include ++#include ++#else ++#include ++#include ++#endif ++#include "pktq.h" ++#include ++#include ++#include + -+ if (DMA64_ENAB(di)) { -+ /* prep the descriptor control value */ -+ if (rxout == (di->nrxd - 1)) -+ ctrl = CTRL_EOT; ++#ifdef BCMDRIVER ++/* copy a pkt buffer chain into a buffer */ ++uint ++pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; + -+ 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 (len < 0) ++ len = 4096; /* "infinite" */ + -+ rxout = NEXTRXD(rxout); ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); + } + -+ di->rxout = rxout; ++ if (!p) ++ return 0; + -+ /* 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)); ++ /* 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; + } ++ ++ return ret; +} + -+void -+dma_txreclaim(dma_info_t *di, bool forceall) ++/* return total length of buffer chain */ ++uint ++pkttotlen(osl_t *osh, void *p) +{ -+ void *p; -+ -+ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); ++ uint total; + -+ while ((p = dma_getnexttxp(di, forceall))) -+ PKTFREE(di->osh, p, TRUE); ++ total = 0; ++ for (; p; p = PKTNEXT(osh, p)) ++ total += PKTLEN(osh, p); ++ return (total); +} + -+/* -+ * 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) ++void ++pktq_init(struct pktq *q, uint maxlen, const uint8 prio_map[]) +{ -+ if (DMA64_ENAB(di)) { -+ return dma64_getnexttxp(di, forceall); -+ } else { -+ return dma32_getnexttxp(di, forceall); ++ 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; +} -+ -+/* like getnexttxp but no reclaim */ -+void* -+dma_peeknexttxp(dma_info_t *di) ++ ++ ++/* should always check pktq_full before calling pktenq */ ++void ++pktenq(struct pktq *q, void *p, bool lifo) +{ -+ uint end, i; ++ void *next, *prev; + -+ 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); ++ /* allow 10 pkts slack */ ++ ASSERT(q->len < (q->maxlen + 10)); ++ ++ /* Queueing chains not allowed */ ++ ASSERT(PKTLINK(p) == NULL); ++ ++ /* Queue is empty */ ++ if (q->tail == NULL) { ++ ASSERT(q->head == NULL); ++ q->head = q->tail = p; + } + -+ for (i = di->txin; i != end; i = NEXTTXD(i)) -+ if (di->txp[i]) -+ return (di->txp[i]); ++ /* 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; ++ } ++ } + -+ return (NULL); -+} ++ /* Insert by priority */ ++ else { ++ /* legal priorities 0-7 */ ++ ASSERT(PKTPRIO(p) <= MAXPRIO); + -+/* -+ * 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); ++ 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; ++ } + } ++ ++ /* List invariants after insertion */ ++ ASSERT(q->head); ++ ASSERT(PKTLINK(q->tail) == NULL); ++ ++ q->len++; +} + -+void -+dma_rxreclaim(dma_info_t *di) ++/* dequeue packet at head */ ++void* ++pktdeq(struct pktq *q) +{ + void *p; + -+ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); ++ 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); ++ } + -+ while ((p = dma_getnextrxp(di, TRUE))) -+ PKTFREE(di->osh, p, FALSE); ++ return (p); +} + -+void * -+dma_getnextrxp(dma_info_t *di, bool forceall) ++/* dequeue packet at tail */ ++void* ++pktdeqtail(struct pktq *q) +{ -+ if (DMA64_ENAB(di)) { -+ return dma64_getnextrxp(di, forceall); -+ } else { -+ return dma32_getnextrxp(di, forceall); ++ void *p; ++ void *next, *prev; ++ ++ 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); + } -+} + -+uintptr -+dma_getvar(dma_info_t *di, char *name) -+{ -+ if (!strcmp(name, "&txavail")) -+ return ((uintptr) &di->txavail); -+ else { -+ ASSERT(0); ++ /* start walk at head */ ++ prev = NULL; ++ next = q->head; ++ ++ /* Walk the queue to find prev of q->tail */ ++ for (; next; prev = next, next = PKTLINK(next)) { ++ if (next == q->tail) ++ break; + } -+ return (0); -+} + -+void -+dma_txblock(dma_info_t *di) -+{ -+ di->txavail = 0; -+} ++ ASSERT(prev); + -+void -+dma_txunblock(dma_info_t *di) -+{ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+} ++ PKTSETLINK(prev, NULL); ++ q->tail = prev; ++ q->len--; ++ p = next; + -+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); ++ return (p); +} ++#endif + -+void -+dma_txpioloopback(dma32regs_t *regs) -+{ -+ OR_REG(®s->control, XC_LE); -+} + +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$ ++ */ + ++#include ++#include ++#include ++#include ++#include ++#include ++#include + ++struct dma_info; /* forward declaration */ ++#define di_t struct dma_info + -+/*** 32 bits DMA non-inline functions ***/ -+static bool -+dma32_alloc(dma_info_t *di, uint direction) -+{ -+ uint size; -+ uint ddlen; -+ void *va; ++#include "sbhnddma.h" ++#include "hnddma.h" + -+ ddlen = sizeof (dma32dd_t); ++/* debug/trace */ ++#define DMA_ERROR(args) ++#define DMA_TRACE(args) + -+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++/* default dma message level (if input msg_level pointer is null in dma_attach()) */ ++static uint dma_msg_level = ++ 0; + -+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, D32RINGALIGN)) -+ size += D32RINGALIGN; ++#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 */ + -+ 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; -+ } ++ 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 */ + -+ 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)); -+ } ++ 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 */ + -+ return TRUE; -+} ++ /* 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; + -+static void -+dma32_txreset(dma_info_t *di) -+{ -+ uint32 status; ++#ifdef BCMDMA64 ++#define DMA64_ENAB(di) ((di)->dma64) ++#else ++#define DMA64_ENAB(di) (0) ++#endif + -+ /* 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); ++/* 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) + -+ W_REG(&di->d32txregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED, -+ 10000); ++/* macros to convert between byte offsets and indexes */ ++#define B2I(bytes, type) ((bytes) / sizeof(type)) ++#define I2B(index, type) ((index) * sizeof(type)) + -+ if (status != XS_XS_DISABLED) { -+ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); -+ } ++#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ ++#define PCI32ADDR_HIGH_SHIFT 30 + -+ /* wait for the last transaction to complete */ -+ OSL_DELAY(300); -+} + -+static void -+dma32_rxreset(dma_info_t *di) -+{ -+ uint32 status; ++/* prototypes */ ++static bool dma_isaddrext(dma_info_t *di); ++static bool dma_alloc(dma_info_t *di, uint direction); + -+ W_REG(&di->d32rxregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED, -+ 10000); ++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); + -+ if (status != RS_RS_DISABLED) { -+ DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name)); -+ } -+} ++/* 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 + -+static bool -+dma32_txsuspendedidle(dma_info_t *di) -+{ -+ if (!(R_REG(&di->d32txregs->control) & XC_SE)) -+ return 0; ++/* 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 */ + -+ if ((R_REG(&di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) -+ return 0; -+ -+ OSL_DELAY(2); -+ return ((R_REG(&di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); -+} ++ /* 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; + -+/* -+ * 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* ++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) +{ -+ void *p, *next; -+ uchar *data; -+ uint len; -+ uint txout; -+ uint32 ctrl; -+ uint32 pa; -+ -+ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ 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; + -+ txout = di->txout; -+ ctrl = 0; ++ /* check arguments */ ++ ASSERT(ISPOWEROF2(ntxd)); ++ ASSERT(ISPOWEROF2(nrxd)); ++ if (nrxd == 0) ++ ASSERT(dmaregsrx == NULL); ++ if (ntxd == 0) ++ ASSERT(dmaregstx == NULL); + -+ /* -+ * 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); ++ ASSERT(ntxd <= D32MAXDD); ++ ASSERT(nrxd <= D32MAXDD); ++ di->d32txregs = (dma32regs_t *)dmaregstx; ++ di->d32rxregs = (dma32regs_t *)dmaregsrx; + -+ /* return nonzero if out of tx descriptors */ -+ if (NEXTTXD(txout) == di->txin) -+ goto outoftxd; ++ /* make a private copy of our callers name */ ++ strncpy(di->name, name, MAXNAMEL); ++ di->name[MAXNAMEL-1] = '\0'; + -+ if (len == 0) -+ continue; ++ di->osh = osh; ++ di->sbh = NULL; + -+ /* get physical address of buffer start */ -+ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); ++ /* save tunables */ ++ di->ntxd = ntxd; ++ di->nrxd = nrxd; ++ di->rxbufsize = rxbufsize; ++ di->nrxpost = nrxpost; ++ di->rxoffset = rxoffset; + -+ /* build the descriptor control value */ -+ ctrl = len & CTRL_BC_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)); + -+ ctrl |= coreflags; -+ -+ if (p == p0) -+ ctrl |= CTRL_SOF; -+ if (next == NULL) -+ ctrl |= (CTRL_IOC | CTRL_EOF); -+ if (txout == (di->ntxd - 1)) -+ ctrl |= CTRL_EOT; ++ /* 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); ++ } + -+ if (DMA64_ENAB(di)) { -+ dma64_dd_upd(di, di->txd64, pa, txout, &ctrl, len); -+ } else { -+ dma32_dd_upd(di, di->txd32, pa, txout, &ctrl); ++ /* 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); ++ } + -+ ASSERT(di->txp[txout] == NULL); ++ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ ++ if (ntxd) { ++ if (!dma_alloc(di, DMA_TX)) ++ goto fail; ++ } + -+ txout = NEXTTXD(txout); ++ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ ++ if (nrxd) { ++ if (!dma_alloc(di, DMA_RX)) ++ goto fail; + } + -+ /* 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)); ++ 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; ++ } + -+ /* save the packet */ -+ di->txp[PREVTXD(txout)] = p0; ++ return ((void*)di); + -+ /* bump the tx descriptor index */ -+ di->txout = txout; ++fail: ++ dma_detach((void*)di); ++ return (NULL); ++} + -+ /* kick the chip */ ++ ++static bool ++dma_alloc(dma_info_t *di, uint direction) ++{ + if (DMA64_ENAB(di)) { -+ W_REG(&di->d64txregs->ptr, I2B(txout, dma64dd_t)); ++ return dma64_alloc(di, direction); + } else { -+ W_REG(&di->d32txregs->ptr, I2B(txout, dma32dd_t)); ++ return dma32_alloc(di, direction); + } -+ -+ /* tx flow control */ -+ di->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->txavail = 0; -+ di->hnddma.txnobuf++; -+ return (-1); +} + -+static void* -+dma32_getnexttxp(dma_info_t *di, bool forceall) ++/* may be called with core in reset */ ++void ++dma_detach(dma_info_t *di) +{ -+ 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); -+ -+ 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]); ++ if (di == NULL) ++ return; + -+ W_SM(&di->txd32[i].addr, 0xdeadbeef); -+ txp = di->txp[i]; -+ di->txp[i] = NULL; -+ } ++ DMA_TRACE(("%s: dma_detach\n", di->name)); + -+ di->txin = i; ++ /* shouldn't be here if descriptors are unreclaimed */ ++ ASSERT(di->txin == di->txout); ++ ASSERT(di->rxin == di->rxout); + -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ /* 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)); + -+ return (txp); ++ /* 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*))); + -+bogus: -+/* -+ DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", -+ start, end, di->txout, forceall)); -+*/ -+ return (NULL); ++ /* free our private info structure */ ++ MFREE(di->osh, (void*)di, sizeof (dma_info_t)); +} + -+static void * -+dma32_getnextrxp(dma_info_t *di, bool forceall) ++/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ ++static bool ++dma_isaddrext(dma_info_t *di) +{ -+ uint i; -+ void *rxp; -+ -+ /* if forcing, dma engine must be disabled */ -+ ASSERT(!forceall || !dma_rxenabled(di)); -+ -+ i = di->rxin; -+ -+ /* return if no packets posted */ -+ if (i == di->rxout) -+ return (NULL); ++ uint32 w; + -+ /* ignore curr if forceall */ -+ if (!forceall && (i == B2I(R_REG(&di->d32rxregs->status) & RS_CD_MASK, dma32dd_t))) -+ return (NULL); ++ 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); ++ } ++} + -+ /* get the packet pointer that corresponds to the rx descriptor */ -+ rxp = di->rxp[i]; -+ ASSERT(rxp); -+ di->rxp[i] = NULL; ++void ++dma_txreset(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txreset\n", di->name)); + -+ /* 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 (DMA64_ENAB(di)) ++ dma64_txreset(di); ++ else ++ dma32_txreset(di); ++} + -+ di->rxin = NEXTRXD(i); ++void ++dma_rxreset(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxreset\n", di->name)); + -+ return (rxp); ++ if (DMA64_ENAB(di)) ++ dma64_rxreset(di); ++ else ++ dma32_rxreset(di); +} + ++/* initialize descriptor table base address */ +static void -+dma32_txrotate(di_t *di) ++dma_ddtable_init(dma_info_t *di, uint direction, ulong pa) +{ -+ 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; ++ 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)); ++ } ++ } + } ++} + -+ first = di->txin; -+ last = PREVTXD(di->txout); -+ -+ /* move entries starting at last and moving backwards to first */ -+ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { -+ new = TXD(old + rot); -+ -+ /* -+ * 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)); ++/* 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; + -+ /* zap the old tx dma descriptor address field */ -+ W_SM(&di->txd32[old].addr, 0xdeadbeef); ++ 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; + -+ /* move the corresponding txp[] entry */ -+ ASSERT(di->txp[new] == NULL); -+ di->txp[new] = di->txp[old]; -+ di->txp[old] = NULL; ++ *ctrl |= (ae << CTRL_AE_SHIFT); ++ W_SM(&ddring[outidx].addr, BUS_SWAP32((pa & ~PCI32ADDR_HIGH) + offset)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*ctrl)); + } -+ -+ /* update txin and txout */ -+ di->txin = ad; -+ di->txout = TXD(di->txout + rot); -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ /* kick the chip */ -+ W_REG(&di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); +} + -+/*** 64 bits DMA non-inline functions ***/ -+ -+#ifdef BCMDMA64 -+ -+static bool -+dma64_alloc(dma_info_t *di, uint direction) ++/* 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) +{ -+ uint size; -+ uint ddlen; -+ uint32 alignbytes; -+ void *va; -+ -+ ddlen = sizeof (dma64dd_t); ++ uint32 bufaddr_low = pa + di->dataoffsetlow; ++ uint32 bufaddr_high = 0 + di->dataoffsethigh; + -+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; + -+ alignbytes = di->dma64align; ++ 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)); ++} + -+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, alignbytes)) -+ size += alignbytes; ++void ++dma_txinit(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); + ++ di->txin = di->txout = 0; ++ di->txavail = di->ntxd - 1; + -+ 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; -+ } ++ /* 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); ++ } ++} + -+ 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)); ++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 { -+ 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)); ++ xc = R_REG(&di->d32txregs->control); ++ return ((xc != 0xffffffff) && (xc & XC_XE)); + } ++} + -+ return TRUE; ++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); +} + -+static void -+dma64_txreset(dma_info_t *di) ++void ++dma_txresume(dma_info_t *di) +{ -+ uint32 status; ++ 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); ++} + -+ /* 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); ++bool ++dma_txsuspendedidle(dma_info_t *di) ++{ ++ if (DMA64_ENAB(di)) ++ return dma64_txsuspendedidle(di); ++ else ++ return dma32_txsuspendedidle(di); ++} + -+ W_REG(&di->d64txregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED, -+ 10000); ++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); ++} + -+ if (status != D64_XS0_XS_DISABLED) { -+ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); -+ } ++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); ++} + -+ /* wait for the last transaction to complete */ -+ OSL_DELAY(300); ++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); ++} ++ ++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); +} + -+static void -+dma64_rxreset(dma_info_t *di) ++void ++dma_rxinit(dma_info_t *di) +{ -+ uint32 status; ++ DMA_TRACE(("%s: dma_rxinit\n", di->name)); + -+ W_REG(&di->d64rxregs->control, 0); -+ SPINWAIT((status = (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED, -+ 10000); ++ di->rxin = di->rxout = 0; + -+ if (status != D64_RS0_RS_DISABLED) { -+ DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name)); ++ /* 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); + } +} + -+static bool -+dma64_txsuspendedidle(dma_info_t *di) ++void ++dma_rxenable(dma_info_t *di) +{ -+ -+ 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; -+ -+ return 0; ++ 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)); +} + -+/* -+ * 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) ++bool ++dma_rxenabled(dma_info_t *di) +{ -+ void *p, *next; -+ uchar *data; -+ uint len; -+ uint txout; -+ uint32 flags; -+ uint32 pa; -+ -+ DMA_TRACE(("%s: dma_txfast\n", di->name)); -+ -+ txout = di->txout; -+ flags = 0; -+ -+ /* -+ * 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); -+ -+ /* return nonzero if out of tx descriptors */ -+ if (NEXTTXD(txout) == di->txin) -+ goto outoftxd; -+ -+ if (len == 0) -+ continue; -+ -+ /* get physical address of buffer start */ -+ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); -+ -+ 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); ++ uint32 rc; + -+ txout = NEXTTXD(txout); ++ 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)); + } ++} + -+ /* 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; -+ -+ /* bump the tx descriptor index */ -+ di->txout = txout; -+ -+ /* kick the chip */ -+ W_REG(&di->d64txregs->ptr, I2B(txout, dma64dd_t)); -+ -+ /* tx flow control */ -+ di->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->txavail = 0; -+ di->hnddma.txnobuf++; -+ return (-1); ++/* !! 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); ++ } +} + -+static void* -+dma64_getnexttxp(dma_info_t *di, bool forceall) ++/* !! 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) +{ -+ uint start, end, i; -+ void *txp; -+ -+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); -+ -+ txp = NULL; ++ void *p; ++ uint len; ++ int skiplen = 0; + -+ start = di->txin; -+ if (forceall) -+ end = di->txout; -+ else -+ end = B2I(R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK, dma64dd_t); ++ 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; ++ } + -+ if ((start == 0) && (end > di->txout)) -+ goto bogus; ++ len = ltoh16(*(uint16*)(PKTDATA(di->osh, p))); ++ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); + -+ 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]); ++ /* 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; ++ } + -+ W_SM(&di->txd64[i].addrlow, 0xdeadbeef); -+ W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); ++ /* set actual length */ ++ PKTSETLEN(di->osh, p, (di->rxoffset + len)); + -+ txp = di->txp[i]; -+ di->txp[i] = NULL; ++ break; + } + -+ di->txin = i; -+ -+ /* tx flow control */ -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 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); ++ return (p); +} + -+static void * -+dma64_getnextrxp(dma_info_t *di, bool forceall) ++/* post receive buffers */ ++void ++dma_rxfill(dma_info_t *di) +{ ++ void *p; ++ uint rxin, rxout; ++ uint32 ctrl; ++ uint n; + uint i; -+ void *rxp; ++ uint32 pa; ++ uint rxbufsize; + -+ /* if forcing, dma engine must be disabled */ -+ ASSERT(!forceall || !dma_rxenabled(di)); ++ /* ++ * Determine how many receive buffers we're lacking ++ * from the full complement, allocate, initialize, ++ * and post them, then update the chip rx lastdscr. ++ */ + -+ i = di->rxin; ++ rxin = di->rxin; ++ rxout = di->rxout; ++ rxbufsize = di->rxbufsize; + -+ /* return if no packets posted */ -+ if (i == di->rxout) -+ return (NULL); ++ n = di->nrxpost - NRXDACTIVE(rxin, rxout); + -+ /* ignore curr if forceall */ -+ if (!forceall && (i == B2I(R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK, dma64dd_t))) -+ return (NULL); ++ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); + -+ /* get the packet pointer that corresponds to the rx descriptor */ -+ rxp = di->rxp[i]; -+ ASSERT(rxp); -+ di->rxp[i] = NULL; ++ 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; ++ } + -+ /* 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); ++ /* Do a cached write instead of uncached write since DMA_MAP ++ * will flush the cache. */ ++ *(uint32*)(PKTDATA(di->osh, p)) = 0; ++ ++ pa = (uint32) DMA_MAP(di->osh, PKTDATA(di->osh, p), rxbufsize, DMA_RX, p); ++ ASSERT(ISALIGNED(pa, 4)); ++ ++ /* save the free packet pointer */ ++ ASSERT(di->rxp[rxout] == NULL); ++ di->rxp[rxout] = p; ++ ++ if (DMA64_ENAB(di)) { ++ /* prep the descriptor control value */ ++ if (rxout == (di->nrxd - 1)) ++ ctrl = CTRL_EOT; + -+ W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); -+ W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); ++ 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); ++ } + -+ di->rxin = NEXTRXD(i); ++ rxout = NEXTRXD(rxout); ++ } + -+ return (rxp); ++ di->rxout = rxout; ++ ++ /* 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)); ++ } +} + -+static void -+dma64_txrotate(di_t *di) ++void ++dma_txreclaim(dma_info_t *di, bool forceall) +{ -+ uint ad; -+ uint nactive; -+ uint rot; -+ uint old, new; -+ uint32 w; -+ uint first, last; ++ void *p; + -+ ASSERT(dma_txsuspendedidle(di)); ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); + -+ nactive = dma_txactive(di); -+ ad = B2I((R_REG(&di->d64txregs->status1) & D64_XS1_AD_MASK), dma64dd_t); -+ rot = TXD(ad - di->txin); ++ while ((p = dma_getnexttxp(di, forceall))) ++ PKTFREE(di->osh, p, TRUE); ++} + -+ ASSERT(rot < di->ntxd); ++/* ++ * 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) ++{ ++ uint end, i; + -+ /* 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; ++ 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); + } + -+ first = di->txin; -+ last = PREVTXD(di->txout); ++ for (i = di->txin; i != end; i = NEXTTXD(i)) ++ if (di->txp[i]) ++ return (di->txp[i]); + -+ /* move entries starting at last and moving backwards to first */ -+ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { -+ new = TXD(old + rot); ++ return (NULL); ++} + -+ /* -+ * 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); ++/* ++ * 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); ++ } ++} + -+ w = R_SM(&di->txd64[old].ctrl2); -+ W_SM(&di->txd64[new].ctrl2, w); ++void ++dma_rxreclaim(dma_info_t *di) ++{ ++ void *p; + -+ W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); -+ W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); ++ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); + -+ /* zap the old tx dma descriptor address field */ -+ W_SM(&di->txd64[old].addrlow, 0xdeadbeef); -+ W_SM(&di->txd64[old].addrhigh, 0xdeadbeef); ++ while ((p = dma_getnextrxp(di, TRUE))) ++ PKTFREE(di->osh, p, FALSE); ++} + -+ /* move the corresponding txp[] entry */ -+ ASSERT(di->txp[new] == NULL); -+ di->txp[new] = di->txp[old]; -+ di->txp[old] = NULL; ++void * ++dma_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ if (DMA64_ENAB(di)) { ++ return dma64_getnextrxp(di, forceall); ++ } else { ++ return dma32_getnextrxp(di, forceall); + } -+ -+ /* update txin and txout */ -+ di->txin = ad; -+ di->txout = TXD(di->txout + rot); -+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; -+ -+ /* kick the chip */ -+ W_REG(&di->d64txregs->ptr, I2B(di->txout, dma64dd_t)); +} + -+#endif -+ -diff -Nur linux-2.4.32/drivers/net/hnd/linux_osl.c linux-2.4.32-brcm/drivers/net/hnd/linux_osl.c ---- linux-2.4.32/drivers/net/hnd/linux_osl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/hnd/linux_osl.c 2005-12-16 23:39:11.292858500 +0100 -@@ -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$ -+ */ ++uintptr ++dma_getvar(dma_info_t *di, char *name) ++{ ++ if (!strcmp(name, "&txavail")) ++ return ((uintptr) &di->txavail); ++ else { ++ ASSERT(0); ++ } ++ return (0); ++} + -+#define LINUX_OSL ++void ++dma_txblock(dma_info_t *di) ++{ ++ di->txavail = 0; ++} + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef mips -+#include -+#endif -+#include ++void ++dma_txunblock(dma_info_t *di) ++{ ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++} + -+#define PCI_CFG_RETRY 10 ++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); ++} + -+#define OS_HANDLE_MAGIC 0x1234abcd -+#define BCM_MEM_FILENAME_LEN 24 ++void ++dma_txpioloopback(dma32regs_t *regs) ++{ ++ OR_REG(®s->control, XC_LE); ++} + -+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) ++/*** 32 bits DMA non-inline functions ***/ ++static bool ++dma32_alloc(dma_info_t *di, uint direction) +{ -+ int abs_bcmerror; -+ int array_size = ARRAYSIZE(linuxbcmerrormap); -+ -+ abs_bcmerror = ABS(bcmerror); ++ uint size; ++ uint ddlen; ++ void *va; + -+ if (bcmerror > 0) -+ abs_bcmerror = 0; ++ ddlen = sizeof (dma32dd_t); + -+ else if (abs_bcmerror >= array_size) -+ abs_bcmerror = BCME_ERROR; ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); + -+ return linuxbcmerrormap[abs_bcmerror]; ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, D32RINGALIGN)) ++ size += D32RINGALIGN; ++ ++ ++ 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; ++ } ++ ++ 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)); ++ } ++ ++ return TRUE; +} + -+osl_t * -+osl_attach(void *pdev) ++static void ++dma32_txreset(dma_info_t *di) +{ -+ osl_t *osh; ++ uint32 status; + -+ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); -+ ASSERT(osh); ++ /* 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); + -+ /* -+ * 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)); ++ W_REG(&di->d32txregs->control, 0); ++ SPINWAIT((status = (R_REG(&di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED, ++ 10000); + -+ osh->magic = OS_HANDLE_MAGIC; -+ osh->malloced = 0; -+ osh->failed = 0; -+ osh->dbgmem_list = NULL; -+ osh->pdev = pdev; ++ if (status != XS_XS_DISABLED) { ++ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); ++ } + -+ return osh; ++ /* wait for the last transaction to complete */ ++ OSL_DELAY(300); +} + -+void -+osl_detach(osl_t *osh) ++static void ++dma32_rxreset(dma_info_t *di) +{ -+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC)); -+ kfree(osh); ++ uint32 status; ++ ++ 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)); ++ } +} + -+void* -+osl_pktget(osl_t *osh, uint len, bool send) ++static bool ++dma32_txsuspendedidle(dma_info_t *di) +{ -+ struct sk_buff *skb; ++ if (!(R_REG(&di->d32txregs->control) & XC_SE)) ++ return 0; ++ ++ if ((R_REG(&di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) ++ return 0; + -+ if ((skb = dev_alloc_skb(len)) == NULL) -+ return (NULL); ++ OSL_DELAY(2); ++ return ((R_REG(&di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); ++} + -+ skb_put(skb, len); ++/* ++ * 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; + -+ /* ensure the cookie field is cleared */ -+ PKTSETCOOKIE(skb, NULL); ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); + -+ return ((void*) skb); -+} ++ txout = di->txout; ++ ctrl = 0; + -+void -+osl_pktfree(void *p) -+{ -+ struct sk_buff *skb, *nskb; ++ /* ++ * 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); + -+ skb = (struct sk_buff*) p; ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; + -+ /* 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); ++ if (len == 0) ++ continue; ++ ++ /* get physical address of buffer start */ ++ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); ++ ++ /* build the descriptor control value */ ++ ctrl = len & CTRL_BC_MASK; ++ ++ ctrl |= coreflags; ++ ++ if (p == p0) ++ ctrl |= CTRL_SOF; ++ if (next == NULL) ++ ctrl |= (CTRL_IOC | CTRL_EOF); ++ if (txout == (di->ntxd - 1)) ++ ctrl |= CTRL_EOT; ++ ++ if (DMA64_ENAB(di)) { ++ dma64_dd_upd(di, di->txd64, pa, txout, &ctrl, len); + } else { -+ /* can free immediately (even in_irq()) if destructor does not exist */ -+ dev_kfree_skb(skb); ++ dma32_dd_upd(di, di->txd32, pa, txout, &ctrl); + } -+ skb = nskb; ++ ++ ASSERT(di->txp[txout] == NULL); ++ ++ txout = NEXTTXD(txout); + } -+} + -+uint32 -+osl_pci_read_config(osl_t *osh, uint offset, uint size) -+{ -+ uint val; -+ uint retry=PCI_CFG_RETRY; ++ /* 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)); + -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; + -+ /* only 4byte access supported */ -+ ASSERT(size == 4); ++ /* bump the tx descriptor index */ ++ di->txout = txout; + -+ do { -+ pci_read_config_dword(osh->pdev, offset, &val); -+ if (val != 0xffffffff) -+ break; -+ } while (retry--); ++ /* 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)); ++ } + ++ /* tx flow control */ ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+ return (val); ++ return (0); ++ ++ 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); +} + -+void -+osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) ++static void* ++dma32_getnexttxp(dma_info_t *di, bool forceall) +{ -+ uint retry=PCI_CFG_RETRY; ++ uint start, end, i; ++ void *txp; + -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); + -+ /* only 4byte access supported */ -+ ASSERT(size == 4); ++ txp = NULL; + -+ 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--); ++ start = di->txin; ++ if (forceall) ++ end = di->txout; ++ else ++ end = B2I(R_REG(&di->d32txregs->status) & XS_CD_MASK, dma32dd_t); + -+} ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; + -+/* 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); ++ 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]); + -+ return ((struct pci_dev *)osh->pdev)->bus->number; -+} ++ W_SM(&di->txd32[i].addr, 0xdeadbeef); ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ } + -+/* return slot # for the pci device pointed by osh->pdev */ -+uint -+osl_pci_slot(osl_t *osh) -+{ -+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ di->txin = i; + -+ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); -+} ++ /* tx flow control */ ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+static void -+osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) -+{ -+} ++ return (txp); + -+void -+osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) -+{ -+ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); ++bogus: ++/* ++ DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", ++ start, end, di->txout, forceall)); ++*/ ++ return (NULL); +} + -+void -+osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) ++static void * ++dma32_getnextrxp(dma_info_t *di, bool forceall) +{ -+ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); -+} ++ uint i; ++ void *rxp; + ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma_rxenabled(di)); + -+#ifdef BCMDBG_MEM ++ i = di->rxin; + -+void* -+osl_debug_malloc(osl_t *osh, uint size, int line, char* file) -+{ -+ bcm_mem_link_t *p; -+ char* basename; ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); + -+ ASSERT(size); -+ -+ if ((p = (bcm_mem_link_t*)osl_malloc(osh, sizeof(bcm_mem_link_t) + size)) == NULL) ++ /* ignore curr if forceall */ ++ if (!forceall && (i == B2I(R_REG(&di->d32rxregs->status) & RS_CD_MASK, dma32dd_t))) + 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'; ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; + -+ /* link this block */ -+ p->prev = NULL; -+ p->next = osh->dbgmem_list; -+ if (p->next) -+ p->next->prev = p; -+ osh->dbgmem_list = p; ++ /* 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); + -+ return p + 1; ++ di->rxin = NEXTRXD(i); ++ ++ return (rxp); +} + -+void -+osl_debug_mfree(osl_t *osh, void *addr, uint size, int line, char* file) ++static void ++dma32_txrotate(di_t *di) +{ -+ bcm_mem_link_t *p = (bcm_mem_link_t *)((int8*)addr - sizeof(bcm_mem_link_t)); -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ uint ad; ++ uint nactive; ++ uint rot; ++ uint old, new; ++ uint32 w; ++ uint first, last; + -+ 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); ++ 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; + } + -+ 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; ++ first = di->txin; ++ last = PREVTXD(di->txout); ++ ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); ++ ++ /* ++ * 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)); ++ ++ /* 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; + } + -+ /* 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; ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+ osl_mfree(osh, p, size + sizeof(bcm_mem_link_t)); ++ /* kick the chip */ ++ W_REG(&di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); +} + -+char* -+osl_debug_memdump(osl_t *osh, char *buf, uint sz) ++/*** 64 bits DMA non-inline functions ***/ ++ ++#ifdef BCMDMA64 ++ ++static bool ++dma64_alloc(dma_info_t *di, uint direction) +{ -+ bcm_mem_link_t *p; -+ char *obuf; -+ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ obuf = buf; ++ uint size; ++ uint ddlen; ++ uint32 alignbytes; ++ void *va; + -+ 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); ++ ddlen = sizeof (dma64dd_t); + -+ return (obuf); -+} ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); + -+#endif /* BCMDBG_MEM */ ++ alignbytes = di->dma64align; + -+void* -+osl_malloc(osl_t *osh, uint size) -+{ -+ void *addr; -+ -+ /* only ASSERT if osh is defined */ -+ if (osh) -+ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, alignbytes)) ++ size += alignbytes; + -+ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { -+ if(osh) -+ osh->failed++; -+ return (NULL); -+ } -+ 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; ++ 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; ++ } ++ ++ 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)); + } -+ kfree(addr); -+} + -+uint -+osl_malloced(osl_t *osh) -+{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ return (osh->malloced); ++ return TRUE; +} + -+uint osl_malloc_failed(osl_t *osh) ++static void ++dma64_txreset(dma_info_t *di) +{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); -+ return (osh->failed); -+} ++ 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); + -+void* -+osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap) -+{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ if (status != D64_XS0_XS_DISABLED) { ++ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); ++ } + -+ return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); ++ /* wait for the last transaction to complete */ ++ OSL_DELAY(300); +} + -+void -+osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) ++static void ++dma64_rxreset(dma_info_t *di) +{ -+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ uint32 status; + -+ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); -+} ++ W_REG(&di->d64rxregs->control, 0); ++ SPINWAIT((status = (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED, ++ 10000); + -+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)); ++ if (status != D64_RS0_RS_DISABLED) { ++ DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name)); ++ } +} + -+void -+osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) ++static bool ++dma64_txsuspendedidle(dma_info_t *di) +{ -+ int dir; ++ ++ if (!(R_REG(&di->d64txregs->control) & D64_XC_SE)) ++ return 0; + -+ 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); ++ if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_IDLE) ++ return 1; ++ ++ return 0; +} + -+#if defined(BINOSL) -+void -+osl_assert(char *exp, char *file, int line) ++/* ++ * 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) +{ -+ char tempbuf[255]; ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint txout; ++ uint32 flags; ++ uint32 pa; + -+ sprintf(tempbuf, "assertion \"%s\" failed: file \"%s\", line %d\n", exp, file, line); -+ panic(tempbuf); -+} -+#endif /* BCMDBG || BINOSL */ ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); + -+void -+osl_delay(uint usec) -+{ -+ uint d; ++ txout = di->txout; ++ flags = 0; + -+ while (usec > 0) { -+ d = MIN(usec, 1000); -+ udelay(d); -+ usec -= 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); + -+/* -+ * BINOSL selects the slightly slower function-call-based binary compatible osl. -+ */ -+#ifdef BINOSL ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; + -+int -+osl_printf(const char *format, ...) -+{ -+ va_list args; -+ char buf[1024]; -+ int len; ++ if (len == 0) ++ continue; + -+ /* sprintf into a local buffer because there *is* no "vprintk()".. */ -+ va_start(args, format); -+ len = vsprintf(buf, format, args); -+ va_end(args); ++ /* get physical address of buffer start */ ++ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); + -+ if (len > sizeof (buf)) { -+ printk("osl_printf: buffer overrun\n"); -+ 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); ++ ++ txout = NEXTTXD(txout); + } + -+ return (printk(buf)); -+} ++ /* 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)); + -+int -+osl_sprintf(char *buf, const char *format, ...) -+{ -+ va_list args; -+ int rc; ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; + -+ va_start(args, format); -+ rc = vsprintf(buf, format, args); -+ va_end(args); -+ return (rc); -+} ++ /* bump the tx descriptor index */ ++ di->txout = txout; + -+int -+osl_strcmp(const char *s1, const char *s2) -+{ -+ return (strcmp(s1, s2)); -+} ++ /* kick the chip */ ++ W_REG(&di->d64txregs->ptr, I2B(txout, dma64dd_t)); + -+int -+osl_strncmp(const char *s1, const char *s2, uint n) -+{ -+ return (strncmp(s1, s2, n)); -+} ++ /* tx flow control */ ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+int -+osl_strlen(const char *s) -+{ -+ return (strlen(s)); -+} ++ return (0); + -+char* -+osl_strcpy(char *d, const char *s) -+{ -+ return (strcpy(d, s)); ++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); +} + -+char* -+osl_strncpy(char *d, const char *s, uint n) ++static void* ++dma64_getnexttxp(dma_info_t *di, bool forceall) +{ -+ return (strncpy(d, s, n)); -+} ++ uint start, end, i; ++ void *txp; + -+void -+bcopy(const void *src, void *dst, int len) -+{ -+ memcpy(dst, src, len); -+} ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); + -+int -+bcmp(const void *b1, const void *b2, int len) -+{ -+ return (memcmp(b1, b2, len)); -+} ++ txp = NULL; + -+void -+bzero(void *b, int len) -+{ -+ memset(b, '\0', len); -+} ++ start = di->txin; ++ if (forceall) ++ end = di->txout; ++ else ++ end = B2I(R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK, dma64dd_t); + -+uint32 -+osl_readl(volatile uint32 *r) -+{ -+ return (readl(r)); -+} ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; + -+uint16 -+osl_readw(volatile uint16 *r) -+{ -+ return (readw(r)); -+} ++ 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]); + -+uint8 -+osl_readb(volatile uint8 *r) -+{ -+ return (readb(r)); -+} ++ W_SM(&di->txd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); + -+void -+osl_writel(uint32 v, volatile uint32 *r) -+{ -+ writel(v, r); -+} ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ } + -+void -+osl_writew(uint16 v, volatile uint16 *r) -+{ -+ writew(v, r); -+} ++ di->txin = i; + -+void -+osl_writeb(uint8 v, volatile uint8 *r) -+{ -+ writeb(v, r); ++ /* tx flow control */ ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 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); +} + -+void * -+osl_uncached(void *va) ++static void * ++dma64_getnextrxp(dma_info_t *di, bool forceall) +{ -+#ifdef mips -+ return ((void*)KSEG1ADDR(va)); -+#else -+ return ((void*)va); -+#endif -+} ++ uint i; ++ void *rxp; + -+uint -+osl_getcycles(void) -+{ -+ uint cycles; ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma_rxenabled(di)); + -+#if defined(mips) -+ cycles = read_c0_count() * 2; -+#elif defined(__i386__) -+ rdtscl(cycles); -+#else -+ cycles = 0; -+#endif -+ return cycles; -+} ++ i = di->rxin; + -+void * -+osl_reg_map(uint32 pa, uint size) -+{ -+ return (ioremap_nocache((unsigned long)pa, (unsigned long)size)); -+} ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); + -+void -+osl_reg_unmap(void *va) -+{ -+ iounmap(va); -+} ++ /* ignore curr if forceall */ ++ if (!forceall && (i == B2I(R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK, dma64dd_t))) ++ return (NULL); + -+int -+osl_busprobe(uint32 *val, uint32 addr) -+{ -+#ifdef mips -+ return get_dbe(*val, (uint32*)addr); -+#else -+ *val = readl(addr); -+ return 0; -+#endif -+} ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; + -+uchar* -+osl_pktdata(osl_t *osh, void *skb) -+{ -+ return (((struct sk_buff*)skb)->data); -+} ++ /* 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); + -+uint -+osl_pktlen(osl_t *osh, void *skb) -+{ -+ return (((struct sk_buff*)skb)->len); -+} ++ W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); + -+uint -+osl_pktheadroom(osl_t *osh, void *skb) -+{ -+ return (uint) skb_headroom((struct sk_buff *) skb); -+} ++ di->rxin = NEXTRXD(i); + -+uint -+osl_pkttailroom(osl_t *osh, void *skb) -+{ -+ return (uint) skb_tailroom((struct sk_buff *) skb); ++ return (rxp); +} + -+void* -+osl_pktnext(osl_t *osh, void *skb) ++static void ++dma64_txrotate(di_t *di) +{ -+ return (((struct sk_buff*)skb)->next); -+} ++ uint ad; ++ uint nactive; ++ uint rot; ++ uint old, new; ++ uint32 w; ++ uint first, last; + -+void -+osl_pktsetnext(void *skb, void *x) -+{ -+ ((struct sk_buff*)skb)->next = (struct sk_buff*)x; -+} ++ ASSERT(dma_txsuspendedidle(di)); + -+void -+osl_pktsetlen(osl_t *osh, void *skb, uint len) -+{ -+ __skb_trim((struct sk_buff*)skb, len); -+} ++ nactive = dma_txactive(di); ++ ad = B2I((R_REG(&di->d64txregs->status1) & D64_XS1_AD_MASK), dma64dd_t); ++ rot = TXD(ad - di->txin); + -+uchar* -+osl_pktpush(osl_t *osh, void *skb, int bytes) -+{ -+ return (skb_push((struct sk_buff*)skb, bytes)); -+} ++ ASSERT(rot < di->ntxd); + -+uchar* -+osl_pktpull(osl_t *osh, void *skb, int bytes) -+{ -+ return (skb_pull((struct sk_buff*)skb, bytes)); -+} ++ /* 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; ++ } + -+void* -+osl_pktdup(osl_t *osh, void *skb) -+{ -+ return (skb_clone((struct sk_buff*)skb, GFP_ATOMIC)); -+} ++ first = di->txin; ++ last = PREVTXD(di->txout); + -+void* -+osl_pktcookie(void *skb) -+{ -+ return ((void*)((struct sk_buff*)skb)->csum); -+} ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); + -+void -+osl_pktsetcookie(void *skb, void *x) -+{ -+ ((struct sk_buff*)skb)->csum = (uint)x; -+} ++ /* ++ * 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); + -+void* -+osl_pktlink(void *skb) -+{ -+ return (((struct sk_buff*)skb)->prev); -+} ++ w = R_SM(&di->txd64[old].ctrl2); ++ W_SM(&di->txd64[new].ctrl2, w); + -+void -+osl_pktsetlink(void *skb, void *x) -+{ -+ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x; -+} ++ W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); ++ W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); + -+uint -+osl_pktprio(void *skb) -+{ -+ return (((struct sk_buff*)skb)->priority); -+} ++ /* zap the old tx dma descriptor address field */ ++ W_SM(&di->txd64[old].addrlow, 0xdeadbeef); ++ W_SM(&di->txd64[old].addrhigh, 0xdeadbeef); + -+void -+osl_pktsetprio(void *skb, uint x) -+{ -+ ((struct sk_buff*)skb)->priority = x; ++ /* move the corresponding txp[] entry */ ++ ASSERT(di->txp[new] == NULL); ++ di->txp[new] = di->txp[old]; ++ di->txp[old] = NULL; ++ } ++ ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ /* kick the chip */ ++ W_REG(&di->d64txregs->ptr, I2B(di->txout, dma64dd_t)); +} + ++#endif + -+#endif /* BINOSL */ -diff -Nur linux-2.4.32/drivers/net/hnd/Makefile linux-2.4.32-brcm/drivers/net/hnd/Makefile ---- linux-2.4.32/drivers/net/hnd/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/hnd/Makefile 2005-12-16 23:39:11.284858000 +0100 -@@ -0,0 +1,19 @@ -+# -+# Makefile for the BCM47xx specific kernel interface routines -+# under Linux. -+# +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$ ++ */ + -+EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER ++#ifndef _hnddma_h_ ++#define _hnddma_h_ + -+O_TARGET := hnd.o ++/* 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; ++ ++#ifndef di_t ++#define di_t void ++#endif ++ ++#ifndef osl_t ++#define osl_t void ++#endif + -+HND_OBJS := bcmutils.o hnddma.o linux_osl.o sbutils.o bcmsrom.o ++/* 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); + -+export-objs := shared_ksyms.o -+obj-y := shared_ksyms.o $(HND_OBJS) -+obj-m := $(O_TARGET) ++extern void dma_rxpiomode(dma32regs_t *); ++extern void dma_txpioloopback(dma32regs_t *); + -+include $(TOPDIR)/Rules.make + -+shared_ksyms.c: shared_ksyms.sh $(HND_OBJS) -+ sh -e $< $(HND_OBJS) > $@ -diff -Nur linux-2.4.32/drivers/net/hnd/sbutils.c linux-2.4.32-brcm/drivers/net/hnd/sbutils.c ---- linux-2.4.32/drivers/net/hnd/sbutils.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/hnd/sbutils.c 2005-12-16 23:39:11.316860000 +0100 -@@ -0,0 +1,2837 @@ ++#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 @@ +/* -+ * Misc utility routines for accessing chip-specific features -+ * of the SiliconBackplane-based Broadcom chips. ++ * Misc useful os-independent macros and functions. + * + * Copyright 2005, Broadcom Corporation + * All Rights Reserved. @@ -14928,2933 +17486,2736 @@ diff -Nur linux-2.4.32/drivers/net/hnd/sbutils.c linux-2.4.32-brcm/drivers/net/h + * $Id$ + */ + -+#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 { -+ -+ struct sb_pub sb; /* back plane public state(must be first field of sb_info */ -+ -+ void *osh; /* osl os handle */ -+ void *sdh; /* bcmsdh handle */ -+ -+ void *curmap; /* current regs va */ -+ void *regs[SB_MAXCORES]; /* other regs va */ -+ -+ uint curidx; /* current core index */ -+ uint dev_coreid; /* the core provides driver functions */ -+ -+ bool memseg; /* flag to toggle MEM_SEG register */ -+ -+ uint gpioidx; /* gpio control core index */ -+ uint gpioid; /* gpio control coretype */ -+ -+ uint numcores; /* # discovered cores */ -+ uint coreid[SB_MAXCORES]; /* id of each core */ -+ -+ 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 */ -+ -+} sb_info_t; -+ -+/* 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); -+ -+/* 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); -+ -+/* delay needed between the mdio control/ mdiodata register data access */ -+#define PR28829_DELAY() OSL_DELAY(10) -+ -+ -+/* global variable to indicate reservation/release of gpio's*/ -+static uint32 sb_gpioreservation = 0; ++#ifndef _pktq_h_ ++#define _pktq_h_ + -+#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 ++/*** driver-only section ***/ ++#ifdef BCMDRIVER + -+#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)) ++/* 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 + -+/* sonicsrev */ -+#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT) -+#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT) ++#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)) + -+#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))) ++/* 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); + ++#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 @@ +/* -+ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/ -+ * after core switching to avoid invalid register accesss inside ISR. ++ * 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$ + */ -+#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); } -+ -+/* 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 */ -+ -+#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ -+#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ -+ -+#define MIN_DUMPBUFLEN 32 /* debug */ -+ -+/* different register spaces to access thr'u pcie indirect access*/ -+#define PCIE_CONFIGREGS 1 -+#define PCIE_PCIEREGS 2 + -+/* GPIO Based LED powersave defines */ -+#define DEFAULT_GPIO_ONTIME 10 -+#define DEFAULT_GPIO_OFFTIME 90 ++#ifndef _sbhnddma_h_ ++#define _sbhnddma_h_ + -+#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) ++ ++/* 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; + -+static uint32 -+sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr) -+{ -+ uint8 tmp; -+ uint32 val, intr_val = 0; ++/* a pair of pio channels(tx and rx) */ ++typedef volatile struct { ++ pio2regs_t tx; ++ pio2regs_t rx; ++} pio2regp_t; + ++/* 4byte-wide pio register set per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 fifocontrol; ++ uint32 fifodata; ++} pio4regs_t; + -+ /* -+ * 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*/ -+ } ++/* a pair of pio channels(tx and rx) */ ++typedef volatile struct { ++ pio4regs_t tx; ++ pio4regs_t rx; ++} pio4regp_t; + -+ val = R_REG(sbr); + -+ if(si->memseg) { -+ tmp = 0; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); -+ INTR_RESTORE(si, intr_val); -+ } + -+ return (val); -+} ++/* 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 void -+sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v) -+{ -+ uint8 tmp; -+ volatile uint32 dummy; -+ uint32 intr_val = 0; + ++/*** 32 bits addressing ***/ + -+ /* -+ * 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*/ -+ } ++/* 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 (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); ++typedef volatile struct { ++ dma32regs_t xmt; /* dma tx channel */ ++ dma32regs_t rcv; /* dma rx channel */ ++} dma32regp_t; + -+ if(si->memseg) { -+ tmp = 0; -+ OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1); -+ INTR_RESTORE(si, intr_val); -+ } -+} ++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; + +/* -+ * 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 ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. + */ -+sb_t * -+BCMINITFN(sb_attach)(uint devid, osl_t *osh, void *regs, -+ uint bustype, void *sdh, char **vars, int *varsz) -+{ -+ sb_info_t *si; ++typedef volatile struct { ++ uint32 ctrl; /* misc control bits & bufcount */ ++ uint32 addr; /* data buffer address */ ++} dma32dd_t; + -+ /* 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); -+ } ++/* ++ * 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 (BCMINIT(sb_doattach)(si, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { -+ MFREE(osh, si, sizeof (sb_info_t)); -+ return (NULL); -+ } -+ return (sb_t *)si; -+} ++/* 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 + -+/* 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) ++/* transmit descriptor table pointer */ ++#define XP_LD_MASK 0xfff /* last valid descriptor */ + -+/* global kernel resource */ -+static sb_info_t ksi; ++/* 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 + -+/* generic kernel variant of sb_attach() */ -+sb_t * -+BCMINITFN(sb_kattach)() -+{ -+ uint32 *regs; ++/* 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 + -+ if (ksi.curmap == NULL) { -+ uint32 cid; ++/* receive descriptor table pointer */ ++#define RP_LD_MASK 0xfff /* last valid descriptor */ + -+ 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; ++/* 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 + -+ 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); -+ } ++/* 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 */ + -+ if (BCMINIT(sb_doattach)(&ksi, BCM4710_DEVICE_ID, NULL, (void*)regs, -+ SB_BUS, NULL, NULL, NULL) == NULL) { -+ return NULL; -+ } -+ } ++/* 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 */ + -+ return (sb_t *)&ksi; -+} -+#endif ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define CTRL_CORE_MASK 0x0ff00000 + -+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) -+{ -+ uint origidx; -+ chipcregs_t *cc; -+ sbconfig_t *sb; -+ uint32 w; ++/*** 64 bits addressing ***/ + -+ ASSERT(GOODREGS(regs)); ++/* 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; + -+ bzero((uchar*)si, sizeof (sb_info_t)); ++typedef volatile struct { ++ dma64regs_t tx; /* dma64 tx channel */ ++ dma64regs_t rx; /* dma64 rx channel */ ++} dma64regp_t; + -+ si->sb.buscoreidx = si->gpioidx = BADIDX; ++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; + -+ si->osh = osh; -+ si->curmap = regs; -+ si->sdh = sdh; ++/* ++ * 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; + -+ /* 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; -+ } ++/* ++ * 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)) + -+ 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; -+ } ++/* 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 + -+ /* need to set memseg flag for CF card first before any sb registers access */ -+ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) -+ si->memseg = TRUE; ++/* transmit descriptor table pointer */ ++#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ ++ ++/* 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 */ + -+ /* 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); ++#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 (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); -+ } ++/* 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 + -+ /* initialize current core index value */ -+ si->curidx = _sb_coreidx(si); ++/* receive descriptor table pointer */ ++#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ + -+ if (si->curidx == BADIDX) { -+ SB_ERROR(("sb_doattach: bad core index\n")); -+ return NULL; -+ } ++/* 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 */ + -+ /* get sonics backplane revision */ -+ sb = REGS2SB(si->curmap); -+ si->sb.sonicsrev = (R_SBREG(si, &(sb)->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT; ++#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 */ + -+ /* keep and reuse the initial register mapping */ -+ origidx = si->curidx; -+ if (BUSTYPE(si->sb.bustype) == SB_BUS) -+ si->regs[origidx] = regs; ++/* 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 */ + -+ /* 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; ++/* 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 */ + -+ /* 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; ++/* 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 + -+ /* 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; -+ } -+ } ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define D64_CTRL_CORE_MASK 0x0ff00000 + -+ /* get chipcommon rev */ -+ si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV; + -+ /* 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); ++#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 $ + -+ /* return to original core */ -+ sb_setcoreidx(&si->sb, origidx); ++EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER + -+ /* sanity checks */ -+ ASSERT(si->sb.chip); ++O_TARGET := wl.o + -+ /* scan for cores */ -+ BCMINIT(sb_scan)(si); ++obj-y := wl_apsta.o ++obj-y += compat.o hnddma.o + -+ /* 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; -+ } ++obj-m := $(O_TARGET) + -+ if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) { -+ w = getintvar(*vars, "regwindowsz"); -+ si->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE; -+ } ++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$ ++ */ + -+ /* gpio control core is required */ -+ if (!GOODIDX(si->gpioidx)) { -+ SB_ERROR(("sb_doattach: gpio control core not found\n")); -+ return NULL; -+ } ++#include ++#ifdef BCMDRIVER ++#include ++#include ++#include ++#else ++#include ++#include ++#endif ++#include "pktq.h" ++#include ++#include ++#include + -+ /* 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; ++#ifdef BCMDRIVER ++/* copy a pkt buffer chain into a buffer */ ++uint ++pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; + -+ case PCMCIA_BUS: -+ case SDIO_BUS: -+ si->sb.boardvendor = getintvar(*vars, "manfid"); -+ si->sb.boardtype = getintvar(*vars, "prodid"); -+ break; ++ if (len < 0) ++ len = 4096; /* "infinite" */ + -+ case SB_BUS: -+ case JTAG_BUS: -+ si->sb.boardvendor = VENDOR_BROADCOM; -+ if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0) -+ si->sb.boardtype = 0xffff; -+ break; ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); + } + -+ if (si->sb.boardtype == 0) { -+ SB_ERROR(("sb_doattach: unknown board type\n")); -+ ASSERT(si->sb.boardtype); -+ } ++ if (!p) ++ return 0; + -+ /* 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); ++ /* 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; + } + -+ -+ return (si); ++ return ret; +} + ++/* return total length of buffer chain */ +uint -+sb_coreid(sb_t *sbh) ++pkttotlen(osl_t *osh, void *p) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++ uint total; + -+ return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT); ++ total = 0; ++ for (; p; p = PKTNEXT(osh, p)) ++ total += PKTLEN(osh, p); ++ return (total); +} + -+uint -+sb_coreidx(sb_t *sbh) ++/* ++ * 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) +{ -+ sb_info_t *si; ++ struct pktq_prec *q; + -+ si = SB_INFO(sbh); -+ return (si->curidx); ++ 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++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; ++ ++ pq->len++; ++ ++ return p; +} + -+/* return current index of core */ -+static uint -+_sb_coreidx(sb_info_t *si) ++void * ++pktq_penq_head(struct pktq *pq, int prec, void *p) +{ -+ sbconfig_t *sb; -+ uint32 sbaddr = 0; -+ -+ ASSERT(si); ++ struct pktq_prec *q; + -+ switch (BUSTYPE(si->sb.bustype)) { -+ case SB_BUS: -+ sb = REGS2SB(si->curmap); -+ sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0)); -+ break; ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ + -+ case PCI_BUS: -+ sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32)); -+ break; ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); + -+ case PCMCIA_BUS: { -+ uint8 tmp = 0; ++ q = &pq->q[prec]; + -+ 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; -+ } ++ if (q->head) ++ PKTSETLINK(p, q->head); ++ else ++ q->tail = p; + -+#ifdef BCMJTAG -+ case JTAG_BUS: -+ sbaddr = (uint32)si->curmap; -+ break; -+#endif /* BCMJTAG */ ++ q->head = p; ++ q->len++; + -+ default: -+ ASSERT(0); -+ } ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; + -+ if (!GOODCOREADDR(sbaddr)) -+ return BADIDX; ++ pq->len++; + -+ return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE); ++ return p; +} + -+uint -+sb_corevendor(sb_t *sbh) ++void * ++pktq_pdeq(struct pktq *pq, int prec) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; ++ struct pktq_prec *q; ++ void *p; + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++ ASSERT(prec >= 0 && prec < pq->num_prec); + -+ return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT); -+} ++ q = &pq->q[prec]; + -+uint -+sb_corerev(sb_t *sbh) -+{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ uint sbidh; ++ if ((p = q->head) == NULL) ++ return NULL; + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); -+ sbidh = R_SBREG(si, &(sb)->sbidhigh); ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; + -+ return (SBCOREREV(sbidh)); ++ q->len--; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; +} + +void * -+sb_osh(sb_t *sbh) ++pktq_pdeq_tail(struct pktq *pq, int prec) +{ -+ sb_info_t *si; ++ struct pktq_prec *q; ++ void *p, *prev; + -+ si = SB_INFO(sbh); -+ return si->osh; -+} ++ ASSERT(prec >= 0 && prec < pq->num_prec); + -+#define SBTML_ALLOW (SBTML_PE | SBTML_FGC | SBTML_FL_MASK) ++ q = &pq->q[prec]; + -+/* 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; ++ if ((p = q->head) == NULL) ++ return NULL; + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; + -+ ASSERT((val & ~mask) == 0); -+ ASSERT((mask & ~SBTML_ALLOW) == 0); ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; + -+ /* mask and set */ -+ if (mask || val) { -+ w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val; -+ W_SBREG(si, &sb->sbtmstatelow, w); -+ } ++ q->tail = prev; ++ q->len--; + -+ /* return the new value */ -+ return (R_SBREG(si, &sb->sbtmstatelow) & SBTML_ALLOW); ++ pq->len--; ++ ++ return p; +} + -+/* set/clear sbtmstatehigh core-specific flags */ -+uint32 -+sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val) ++void ++pktq_init(struct pktq *pq, int num_prec, int max) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ uint32 w; ++ int prec; + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++ ASSERT(num_prec >= 0 && num_prec <= PKTQ_MAX_PREC); + -+ ASSERT((val & ~mask) == 0); -+ ASSERT((mask & ~SBTMH_FL_MASK) == 0); ++ bzero(pq, sizeof (*pq)); + -+ /* mask and set */ -+ if (mask || val) { -+ w = (R_SBREG(si, &sb->sbtmstatehigh) & ~mask) | val; -+ W_SBREG(si, &sb->sbtmstatehigh, w); -+ } ++ pq->num_prec = (uint16)num_prec; + -+ /* return the new value */ -+ return (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_FL_MASK); ++ pq->max = (uint16)max; ++ ++ for (prec = 0; prec < num_prec; prec++) ++ pq->q[prec].max = pq->max; +} + -+/* caller needs to take care of core-specific bist hazards */ -+int -+sb_corebist(sb_t *sbh, uint coreid, uint coreunit) ++void * ++pktq_deq(struct pktq *pq, int *prec_out) +{ -+ uint32 sblo; -+ uint coreidx; -+ sb_info_t *si; -+ int result = 0; ++ struct pktq_prec *q; ++ void *p; ++ int prec; + -+ si = SB_INFO(sbh); ++ if (pq->len == 0) ++ return NULL; + -+ 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; ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; + -+ sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), ~0, sblo); -+ } ++ q = &pq->q[prec]; + -+ return result; -+} ++ if ((p = q->head) == NULL) ++ return NULL; + -+bool -+sb_iscoreup(sb_t *sbh) -+{ -+ sb_info_t *si; -+ sbconfig_t *sb; ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; + -+ si = SB_INFO(sbh); -+ sb = REGS2SB(si->curmap); ++ q->len--; + -+ return ((R_SBREG(si, &(sb)->sbtmstatelow) & (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK); ++ if (prec_out) ++ *prec_out = prec; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; +} + -+/* -+ * 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) ++void * ++pktq_deq_tail(struct pktq *pq, int *prec_out) +{ -+ uint origidx; -+ uint32 *r; -+ uint w; -+ uint intr_val = 0; ++ struct pktq_prec *q; ++ void *p, *prev; ++ int prec; + -+ ASSERT(GOODIDX(coreidx)); -+ ASSERT(regoff < SB_CORE_SIZE); -+ ASSERT((val & ~mask) == 0); ++ if (pq->len == 0) ++ return NULL; + -+ INTR_OFF(si, intr_val); ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; + -+ /* save current core index */ -+ origidx = sb_coreidx(&si->sb); ++ q = &pq->q[prec]; + -+ /* switch core */ -+ r = (uint32*) ((uchar*) sb_setcoreidx(&si->sb, coreidx) + regoff); ++ if ((p = q->head) == NULL) ++ return NULL; + -+ /* 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); -+ } -+ } ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; + -+ /* readback */ -+ if (regoff >= SBCONFIGOFF) -+ w = R_SBREG(si, r); ++ if (prev) ++ PKTSETLINK(prev, NULL); + else -+ w = R_REG(r); ++ q->head = NULL; + -+ /* restore core index */ -+ if (origidx != coreidx) -+ sb_setcoreidx(&si->sb, origidx); ++ q->tail = prev; ++ q->len--; + -+ INTR_RESTORE(si, intr_val); -+ return (w); -+} ++ if (prec_out) ++ *prec_out = prec; + -+#define DWORD_ALIGN(x) (x & ~(0x03)) -+#define BYTE_POS(x) (x & 0x3) -+#define WORD_POS(x) (x & 0x1) ++ pq->len--; + -+#define BYTE_SHIFT(x) (8 * BYTE_POS(x)) -+#define WORD_SHIFT(x) (16 * WORD_POS(x)) ++ PKTSETLINK(p, NULL); + -+#define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF) -+#define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF) ++ return p; ++} + -+#define read_pci_cfg_byte(a) \ -+ (BYTE_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xff) ++void * ++pktq_peek(struct pktq *pq, int *prec_out) ++{ ++ void *p; ++ int prec; + -+#define read_pci_cfg_write(a) \ -+ (WORD_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xffff) ++ 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 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) ++ return p; ++} ++ ++void * ++pktq_peek_tail(struct pktq *pq, int *prec_out) +{ -+ uint8 cap_id; -+ uint8 cap_ptr; -+ uint32 bufsize; -+ uint8 byte_val; ++ void *p; ++ int prec; + -+ if (BUSTYPE(si->sb.bustype) != PCI_BUS) -+ return FALSE; ++ if (pq->len == 0) ++ return NULL; + -+ /* check for Header type 0*/ -+ byte_val = read_pci_cfg_byte(PCI_CFG_HDR); -+ if ((byte_val & 0x7f) != PCI_HEADER_NORMAL) -+ return FALSE; ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; + -+ /* check if the capability pointer field exists */ -+ byte_val = read_pci_cfg_byte(PCI_CFG_STAT); -+ if (!(byte_val & PCI_CAPPTR_PRESENT)) -+ return FALSE; ++ if ((p = pq->q[prec].tail) == NULL) ++ return NULL; + -+ cap_ptr = read_pci_cfg_byte(PCI_CFG_CAPPTR); -+ /* check if the capability pointer is 0x00 */ -+ if (cap_ptr == 0x00) -+ return FALSE; ++ if (prec_out) ++ *prec_out = prec; + ++ return p; ++} + -+ /* loop thr'u the capability list and see if the pcie capabilty exists */ ++int ++pktq_mlen(struct pktq *pq, uint prec_bmp) ++{ ++ int prec, len; + -+ cap_id = read_pci_cfg_byte(cap_ptr); ++ len = 0; + -+ 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; -+} ++ for (prec = 0; prec <= pq->hi_prec; prec++) ++ if (prec_bmp & (1 << prec)) ++ len += pq->q[prec].len; + -+/* 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)); ++ return len; +} + -+/* scan the sb enumerated space to identify all cores */ -+static void -+BCMINITFN(sb_scan)(sb_info_t *si) ++void * ++pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) +{ -+ uint origidx; -+ uint i; -+ bool pci; -+ bool pcie; -+ uint pciidx; -+ uint pcieidx; -+ uint pcirev; -+ uint pcierev; ++ 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--; + -+ /* numcores should already be set */ -+ ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES)); ++ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) ++ if (prec-- == 0) ++ return NULL; + -+ /* save current core index */ -+ origidx = sb_coreidx(&si->sb); ++ q = &pq->q[prec]; + -+ si->sb.buscorerev = NOREV; -+ si->sb.buscoreidx = BADIDX; ++ if ((p = q->head) == NULL) ++ return NULL; + -+ si->gpioidx = BADIDX; ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; + -+ pci = pcie = FALSE; -+ pcirev = pcierev = NOREV; -+ pciidx = pcieidx = BADIDX; ++ q->len--; + -+ for (i = 0; i < si->numcores; i++) { -+ sb_setcoreidx(&si->sb, i); -+ si->coreid[i] = sb_coreid(&si->sb); ++ if (prec_out) ++ *prec_out = prec; + -+ 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; -+ } ++ pq->len--; + -+ /* -+ * 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); ++ PKTSETLINK(p, NULL); + -+ /* return to original core index */ -+ sb_setcoreidx(&si->sb, origidx); ++ return p; +} + -+/* may be called with core in reset */ -+void -+sb_detach(sb_t *sbh) -+{ -+ sb_info_t *si; -+ uint idx; ++#endif + -+ si = SB_INFO(sbh); + -+ if (si == NULL) -+ return; +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 @@ ++/* ++ * 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$ ++ */ + -+ 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; -+ } ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ if (si != &ksi) -+ MFREE(si->osh, si, sizeof (sb_info_t)); -+} ++struct dma_info; /* forward declaration */ ++#define di_t struct dma_info + -+/* 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); ++#include "sbhnddma.h" ++#include "hnddma.h" + -+ return (0); -+} ++/* debug/trace */ ++#define DMA_ERROR(args) ++#define DMA_TRACE(args) + -+/* convert chip number to number of i/o cores */ -+static uint -+BCMINITFN(sb_chip2numcores)(uint chip) -+{ -+ 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); ++/* default dma message level (if input msg_level pointer is null in dma_attach()) */ ++static uint dma_msg_level = ++ 0; + -+ SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip)); -+ ASSERT(0); -+ return (1); -+} ++#define MAXNAMEL 8 + -+/* 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; ++/* 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 */ + -+ found = 0; ++ 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 */ + -+ for (i = 0; i < si->numcores; i++) -+ if (si->coreid[i] == coreid) { -+ if (found == coreunit) -+ return (i); -+ found++; -+ } ++ 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 */ + -+ return (BADIDX); -+} ++ /* 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; + -+/* -+ * 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) -+{ -+ sb_info_t *si; -+ uint32 sbaddr; -+ uint8 tmp; ++#ifdef BCMDMA64 ++#define DMA64_ENAB(di) ((di)->dma64) ++#else ++#define DMA64_ENAB(di) (0) ++#endif + -+ 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) + -+ 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)); ++/* macros to convert between byte offsets and indexes */ ++#define B2I(bytes, type) ((bytes) / sizeof(type)) ++#define I2B(index, type) ((index) * sizeof(type)) + -+ sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE); ++#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ ++#define PCI32ADDR_HIGH_SHIFT 30 + -+ 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; + -+ case PCI_BUS: -+ /* point bar0 window */ -+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, 4, sbaddr); -+ break; ++/* prototypes */ ++static bool dma_isaddrext(dma_info_t *di); ++static bool dma_alloc(dma_info_t *di, uint direction); + -+ 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 */ -+ } ++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); + -+ si->curidx = coreidx; ++/* 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 + -+ return (si->curmap); -+} + -+/* -+ * 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) ++ ++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) +{ -+ sb_info_t *si; -+ uint idx; ++ dma_info_t *di; ++ uint size; + -+ si = SB_INFO(sbh); -+ idx = sb_findcoreidx(si, coreid, coreunit); -+ if (!GOODIDX(idx)) ++ /* allocate private info structure */ ++ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { + return (NULL); ++ } ++ bzero((char*)di, sizeof (dma_info_t)); + -+ return (sb_setcoreidx(sbh, idx)); -+} ++ di->msg_level = msg_level ? msg_level : &dma_msg_level; + -+/* return chip number */ -+uint -+BCMINITFN(sb_chip)(sb_t *sbh) -+{ -+ sb_info_t *si; ++ if (sbh != NULL) ++ di->dma64 = ((sb_coreflagshi(sbh, 0, 0) & SBTMH_DMA64) == SBTMH_DMA64); + -+ si = SB_INFO(sbh); -+ return (si->sb.chip); -+} ++#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); + -+/* return chip revision number */ -+uint -+BCMINITFN(sb_chiprev)(sb_t *sbh) -+{ -+ sb_info_t *si; + -+ si = SB_INFO(sbh); -+ return (si->sb.chiprev); -+} ++ /* init dma reg pointer */ ++ if (di->dma64) { ++ ASSERT(ntxd <= D64MAXDD); ++ ASSERT(nrxd <= D64MAXDD); ++ di->d64txregs = (dma64regs_t *)dmaregstx; ++ di->d64rxregs = (dma64regs_t *)dmaregsrx; + -+/* return chip common revision number */ -+uint -+BCMINITFN(sb_chipcrev)(sb_t *sbh) -+{ -+ sb_info_t *si; ++ 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; ++ } + -+ si = SB_INFO(sbh); -+ return (si->sb.ccrev); -+} + -+/* return chip package option */ -+uint -+BCMINITFN(sb_chippkg)(sb_t *sbh) -+{ -+ sb_info_t *si; ++ /* make a private copy of our callers name */ ++ strncpy(di->name, name, MAXNAMEL); ++ di->name[MAXNAMEL-1] = '\0'; ++ ++ di->osh = osh; ++ di->sbh = sbh; ++ ++ /* save tunables */ ++ di->ntxd = ntxd; ++ di->nrxd = nrxd; ++ di->rxbufsize = rxbufsize; ++ di->nrxpost = nrxpost; ++ di->rxoffset = rxoffset; ++ ++ /* ++ * 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 ++ } + -+ si = SB_INFO(sbh); -+ return (si->sb.chippkg); -+} ++ di->addrext = dma_isaddrext(di); + -+/* return PCI core rev. */ -+uint -+BCMINITFN(sb_pcirev)(sb_t *sbh) -+{ -+ sb_info_t *si; ++ 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)); + -+ si = SB_INFO(sbh); -+ return (si->sb.buscorerev); -+} ++ /* 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); ++ } + -+bool -+BCMINITFN(sb_war16165)(sb_t *sbh) -+{ -+ sb_info_t *si; ++ /* 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); ++ } + -+ si = SB_INFO(sbh); ++ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ ++ if (ntxd) { ++ if (!dma_alloc(di, DMA_TX)) ++ goto fail; ++ } + -+ return (PCI(si) && (si->sb.buscorerev <= 10)); -+} ++ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ ++ if (nrxd) { ++ if (!dma_alloc(di, DMA_RX)) ++ goto fail; ++ } + -+static void -+BCMINITFN(sb_war30841)(sb_info_t *si) -+{ -+ 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); -+} ++ 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 PCMCIA core rev. */ -+uint -+BCMINITFN(sb_pcmciarev)(sb_t *sbh) -+{ -+ sb_info_t *si; ++ return ((void*)di); + -+ si = SB_INFO(sbh); -+ return (si->sb.buscorerev); ++fail: ++ dma_detach((void*)di); ++ return (NULL); +} + -+/* return board vendor id */ -+uint -+BCMINITFN(sb_boardvendor)(sb_t *sbh) ++static bool ++dma_alloc(dma_info_t *di, uint direction) +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); -+ return (si->sb.boardvendor); ++ if (DMA64_ENAB(di)) { ++ return dma64_alloc(di, direction); ++ } else { ++ return dma32_alloc(di, direction); ++ } +} + -+/* return boardtype */ -+uint -+BCMINITFN(sb_boardtype)(sb_t *sbh) ++/* may be called with core in reset */ ++void ++dma_detach(dma_info_t *di) +{ -+ sb_info_t *si; -+ char *var; -+ -+ si = SB_INFO(sbh); ++ if (di == NULL) ++ return; + -+ if (BUSTYPE(si->sb.bustype) == SB_BUS && si->sb.boardtype == 0xffff) { -+ /* boardtype format is a hex string */ -+ si->sb.boardtype = getintvar(NULL, "boardtype"); ++ DMA_TRACE(("%s: dma_detach\n", di->name)); + -+ /* 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; -+ } -+ } ++ /* shouldn't be here if descriptors are unreclaimed */ ++ ASSERT(di->txin == di->txout); ++ ASSERT(di->rxin == di->rxout); + -+ return (si->sb.boardtype); -+} ++ /* 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)); + -+/* return bus type of sbh device */ -+uint -+sb_bus(sb_t *sbh) -+{ -+ sb_info_t *si; ++ /* 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*))); + -+ si = SB_INFO(sbh); -+ return (si->sb.bustype); ++ /* free our private info structure */ ++ MFREE(di->osh, (void*)di, sizeof (dma_info_t)); +} + -+/* return bus core type */ -+uint -+sb_buscoretype(sb_t *sbh) ++/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ ++static bool ++dma_isaddrext(dma_info_t *di) +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); ++ uint32 w; + -+ return (si->sb.buscoretype); ++ 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); ++ } +} + -+/* return bus core revision */ -+uint -+sb_buscorerev(sb_t *sbh) ++void ++dma_txreset(dma_info_t *di) +{ -+ sb_info_t *si; -+ si = SB_INFO(sbh); ++ DMA_TRACE(("%s: dma_txreset\n", di->name)); + -+ return (si->sb.buscorerev); ++ if (DMA64_ENAB(di)) ++ dma64_txreset(di); ++ else ++ dma32_txreset(di); +} + -+/* return list of found cores */ -+uint -+sb_corelist(sb_t *sbh, uint coreid[]) ++void ++dma_rxreset(dma_info_t *di) +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); ++ DMA_TRACE(("%s: dma_rxreset\n", di->name)); + -+ bcopy((uchar*)si->coreid, (uchar*)coreid, (si->numcores * sizeof (uint))); -+ return (si->numcores); ++ if (DMA64_ENAB(di)) ++ dma64_rxreset(di); ++ else ++ dma32_rxreset(di); +} + -+/* return current register mapping */ -+void * -+sb_coreregs(sb_t *sbh) ++/* initialize descriptor table base address */ ++static void ++dma_ddtable_init(dma_info_t *di, uint direction, ulong pa) +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); -+ ASSERT(GOODREGS(si->curmap)); -+ -+ return (si->curmap); ++ 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)); ++ } ++ } ++ } +} + -+ -+/* do buffered registers update */ -+void -+sb_commit(sb_t *sbh) ++/* 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) +{ -+ sb_info_t *si; -+ uint origidx; -+ uint intr_val = 0; -+ -+ si = SB_INFO(sbh); -+ -+ origidx = si->curidx; -+ ASSERT(GOODIDX(origidx)); ++ uint offset = di->dataoffsetlow; + -+ INTR_OFF(si, intr_val); ++ 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; + -+ /* 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); ++ *ctrl |= (ae << CTRL_AE_SHIFT); ++ W_SM(&ddring[outidx].addr, BUS_SWAP32((pa & ~PCI32ADDR_HIGH) + offset)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*ctrl)); ++ } ++} + -+ /* 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); ++/* 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) ++{ ++ uint32 bufaddr_low = pa + di->dataoffsetlow; ++ uint32 bufaddr_high = 0 + di->dataoffsethigh; + -+ /* do the buffer registers update */ -+ W_REG(&pciregs->bcastaddr, SB_COMMIT); -+ W_REG(&pciregs->bcastdata, 0x0); -+ } else -+ ASSERT(0); ++ uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; + -+ /* restore core index */ -+ sb_setcoreidx(sbh, origidx); -+ INTR_RESTORE(si, intr_val); ++ 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)); +} + -+/* reset and re-enable a core */ +void -+sb_core_reset(sb_t *sbh, uint32 bits) ++dma_txinit(dma_info_t *di) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ volatile uint32 dummy; -+ -+ si = SB_INFO(sbh); -+ ASSERT(GOODREGS(si->curmap)); -+ sb = REGS2SB(si->curmap); -+ -+ /* -+ * Must do the disable sequence first to work for arbitrary current core state. -+ */ -+ sb_core_disable(sbh, bits); -+ -+ /* -+ * Now do the initialization sequence. -+ */ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); + -+ /* 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); ++ di->txin = di->txout = 0; ++ di->txavail = di->ntxd - 1; + -+ 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)); ++ /* 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); + } -+ -+ /* 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); -+ -+ /* leave clock enabled */ -+ W_SBREG(si, &sb->sbtmstatelow, (SBTML_CLK | bits)); -+ dummy = R_SBREG(si, &sb->sbtmstatelow); -+ OSL_DELAY(1); +} + -+void -+sb_core_tofixup(sb_t *sbh) ++bool ++dma_txenabled(dma_info_t *di) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ -+ 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); ++ 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 { -+ 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); -+ } ++ xc = R_REG(&di->d32txregs->control); ++ return ((xc != 0xffffffff) && (xc & XC_XE)); + } -+ -+ sb_commit(sbh); +} + -+/* -+ * 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 ++dma_txsuspend(dma_info_t *di) +{ -+ sb_info_t *si; -+ uint origidx, idx; -+ uint intr_val = 0; -+ uint32 tmp, ret = 0xffffffff; -+ sbconfig_t *sb; -+ -+ si = SB_INFO(sbh); -+ -+ if ((to & ~TO_MASK) != 0) -+ return ret; ++ 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); ++} + -+ /* 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; ++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_OFF(si, intr_val); -+ origidx = sb_coreidx(sbh); ++bool ++dma_txsuspendedidle(dma_info_t *di) ++{ ++ if (DMA64_ENAB(di)) ++ return dma64_txsuspendedidle(di); ++ else ++ return dma32_txsuspendedidle(di); ++} + -+ sb = REGS2SB(sb_setcoreidx(sbh, idx)); ++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); ++} + -+ tmp = R_SBREG(si, &sb->sbimconfiglow); -+ ret = tmp & TO_MASK; -+ W_SBREG(si, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to); ++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); ++} + -+ sb_commit(sbh); -+ sb_setcoreidx(sbh, origidx); -+ INTR_RESTORE(si, intr_val); -+ return ret; ++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); +} + +void -+sb_core_disable(sb_t *sbh, uint32 bits) ++dma_fifoloopbackenable(dma_info_t *di) +{ -+ sb_info_t *si; -+ volatile uint32 dummy; -+ uint32 rej; -+ sbconfig_t *sb; -+ -+ si = SB_INFO(sbh); -+ -+ ASSERT(GOODREGS(si->curmap)); -+ sb = REGS2SB(si->curmap); -+ -+ /* if core is already in reset, just return */ -+ if (R_SBREG(si, &sb->sbtmstatelow) & SBTML_RESET) -+ return; -+ -+ /* reject value changed between sonics 2.2 and 2.3 */ -+ if (si->sb.sonicsrev == SONICS_2_2) -+ rej = (1 << SBTML_REJ_SHIFT); ++ DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name)); ++ if (DMA64_ENAB(di)) ++ OR_REG(&di->d64txregs->control, D64_XC_LE); + else -+ rej = (2 << SBTML_REJ_SHIFT); ++ OR_REG(&di->d32txregs->control, XC_LE); ++} + -+ /* if clocks are not enabled, put into reset and return */ -+ if ((R_SBREG(si, &sb->sbtmstatelow) & SBTML_CLK) == 0) -+ goto disable; ++void ++dma_rxinit(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxinit\n", di->name)); + -+ /* 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); ++ di->rxin = di->rxout = 0; + -+ 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); ++ /* 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); + } ++} + -+ /* 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); ++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)); ++} + -+ /* don't forget to clear the initiator reject bit */ -+ if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) -+ AND_SBREG(si, &sb->sbimstate, ~SBIM_RJ); ++bool ++dma_rxenabled(dma_info_t *di) ++{ ++ uint32 rc; + -+disable: -+ /* leave reset and reject asserted */ -+ W_SBREG(si, &sb->sbtmstatelow, (bits | rej | SBTML_RESET)); -+ OSL_DELAY(1); ++ 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)); ++ } +} + -+/* 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); + -+ /* instant NMI */ -+ switch (si->gpioid) { -+ case SB_CC: -+ sb_corereg(si, 0, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); -+ break; -+ case SB_EXTIF: -+ sb_corereg(si, si->gpioidx, OFFSETOF(extifregs_t, watchdog), ~0, ticks); -+ break; ++/* !! 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); + } +} + -+/* initialize the pcmcia core */ -+void -+sb_pcmcia_init(sb_t *sbh) ++/* !! 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) +{ -+ sb_info_t *si; -+ uint8 cor; ++ void *p; ++ uint len; ++ int skiplen = 0; + -+ si = SB_INFO(sbh); ++ 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; ++ } + -+ /* 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); ++ len = ltoh16(*(uint16*)(PKTDATA(di->osh, p))); ++ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); ++ ++ /* 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; ++ } ++ ++ /* set actual length */ ++ PKTSETLEN(di->osh, p, (di->rxoffset + len)); ++ ++ break; + } + ++ return (p); +} + -+ -+/* -+ * Configure the pci core for pci client (NIC) action -+ * coremask is the bitvec of cores by index to be enabled. -+ */ ++/* post receive buffers */ +void -+sb_pci_setup(sb_t *sbh, uint coremask) ++dma_rxfill(dma_info_t *di) +{ -+ sb_info_t *si; -+ sbconfig_t *sb; -+ sbpciregs_t *pciregs; -+ uint32 sbflag; -+ uint32 w; -+ uint idx; -+ int reg_val; ++ void *p; ++ uint rxin, rxout; ++ uint32 ctrl; ++ uint n; ++ uint i; ++ uint32 pa; ++ uint rxbufsize; + -+ si = SB_INFO(sbh); ++ /* ++ * Determine how many receive buffers we're lacking ++ * from the full complement, allocate, initialize, ++ * and post them, then update the chip rx lastdscr. ++ */ + -+ /* if not pci bus, we're done */ -+ if (BUSTYPE(si->sb.bustype) != PCI_BUS) -+ return; ++ rxin = di->rxin; ++ rxout = di->rxout; ++ rxbufsize = di->rxbufsize; + -+ ASSERT(PCI(si) || PCIE(si)); -+ ASSERT(si->sb.buscoreidx != BADIDX); ++ n = di->nrxpost - NRXDACTIVE(rxin, rxout); + -+ /* get current core index */ -+ idx = si->curidx; ++ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); + -+ /* we interrupt on this backplane flag number */ -+ ASSERT(GOODREGS(si->curmap)); -+ sb = REGS2SB(si->curmap); -+ sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK; ++ 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; ++ } + -+ /* switch over to pci core */ -+ pciregs = (sbpciregs_t*) sb_setcoreidx(sbh, si->sb.buscoreidx); -+ sb = REGS2SB(pciregs); ++ /* Do a cached write instead of uncached write since DMA_MAP ++ * will flush the cache. */ ++ *(uint32*)(PKTDATA(di->osh, p)) = 0; + -+ /* -+ * 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)); -+ } ++ pa = (uint32) DMA_MAP(di->osh, PKTDATA(di->osh, p), rxbufsize, DMA_RX, p); ++ ASSERT(ISALIGNED(pa, 4)); + -+ 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); -+ } -+ } ++ /* save the free packet pointer */ ++ ASSERT(di->rxp[rxout] == NULL); ++ di->rxp[rxout] = p; + -+ 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); ++ if (DMA64_ENAB(di)) { ++ /* prep the descriptor control value */ ++ if (rxout == (di->nrxd - 1)) ++ ctrl = CTRL_EOT; + -+ 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); ++ 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); ++ } + -+ BCMINIT(sb_war30841)(si); ++ rxout = NEXTRXD(rxout); + } + -+ /* switch back to previous core */ -+ sb_setcoreidx(sbh, idx); ++ di->rxout = rxout; ++ ++ /* 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)); ++ } +} + -+uint32 -+sb_base(uint32 admatch) ++void ++dma_txreclaim(dma_info_t *di, bool forceall) +{ -+ uint32 base; -+ uint type; ++ void *p; + -+ type = admatch & SBAM_TYPE_MASK; -+ ASSERT(type < 3); ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); + -+ base = 0; ++ while ((p = dma_getnexttxp(di, forceall))) ++ PKTFREE(di->osh, p, TRUE); ++} + -+ 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; ++/* ++ * 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); + } -+ -+ return (base); +} -+ -+uint32 -+sb_size(uint32 admatch) ++ ++/* like getnexttxp but no reclaim */ ++void* ++dma_peeknexttxp(dma_info_t *di) +{ -+ uint32 size; -+ uint type; ++ uint end, i; + -+ type = admatch & SBAM_TYPE_MASK; -+ ASSERT(type < 3); ++ 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); ++ } + -+ size = 0; ++ for (i = di->txin; i != end; i = NEXTTXD(i)) ++ if (di->txp[i]) ++ return (di->txp[i]); + -+ 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 (NULL); ++} + -+ return (size); ++/* ++ * 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 the core-type instantiation # of the current core */ -+uint -+sb_coreunit(sb_t *sbh) ++void ++dma_rxreclaim(dma_info_t *di) +{ -+ sb_info_t *si; -+ uint idx; -+ uint coreid; -+ uint coreunit; -+ uint i; ++ void *p; + -+ si = SB_INFO(sbh); -+ coreunit = 0; ++ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); + -+ idx = si->curidx; ++ while ((p = dma_getnextrxp(di, TRUE))) ++ PKTFREE(di->osh, p, FALSE); ++} + -+ ASSERT(GOODREGS(si->curmap)); -+ coreid = sb_coreid(sbh); ++void * ++dma_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ if (DMA64_ENAB(di)) { ++ return dma64_getnextrxp(di, forceall); ++ } else { ++ return dma32_getnextrxp(di, forceall); ++ } ++} + -+ /* count the cores of our type */ -+ for (i = 0; i < idx; i++) -+ if (si->coreid[i] == coreid) -+ coreunit++; ++uintptr ++dma_getvar(dma_info_t *di, char *name) ++{ ++ if (!strcmp(name, "&txavail")) ++ return ((uintptr) &di->txavail); ++ else { ++ ASSERT(0); ++ } ++ return (0); ++} + -+ return (coreunit); ++void ++dma_txblock(dma_info_t *di) ++{ ++ di->txavail = 0; +} + -+static INLINE uint32 -+factor6(uint32 x) ++void ++dma_txunblock(dma_info_t *di) +{ -+ 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; -+ } ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; +} + -+/* 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) ++uint ++dma_txactive(dma_info_t *di) +{ -+ uint32 n1, n2, clock, m1, m2, m3, mc; ++ return (NTXDACTIVE(di->txin, di->txout)); ++} ++ ++void ++dma_rxpiomode(dma32regs_t *regs) ++{ ++ W_REG(®s->control, RC_FM); ++} + -+ n1 = n & CN_N1_MASK; -+ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; ++void ++dma_txpioloopback(dma32regs_t *regs) ++{ ++ OR_REG(®s->control, XC_LE); ++} + -+ 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 (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); ++/*** 32 bits DMA non-inline functions ***/ ++static bool ++dma32_alloc(dma_info_t *di, uint direction) ++{ ++ uint size; ++ uint ddlen; ++ void *va; + -+ 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); ++ ddlen = sizeof (dma32dd_t); + -+ 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)); ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, D32RINGALIGN)) ++ size += D32RINGALIGN; + -+ if ((mc & CC_T2MC_M1BYP) == 0) -+ clock /= m1; -+ if ((mc & CC_T2MC_M2BYP) == 0) -+ clock /= m2; -+ if ((mc & CC_T2MC_M3BYP) == 0) -+ clock /= m3; + -+ return(clock); ++ 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; ++ } ++ ++ 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)); + } ++ ++ return TRUE; +} + -+/* returns the current speed the SB is running at */ -+uint32 -+sb_clock(sb_t *sbh) ++static void ++dma32_txreset(dma_info_t *di) +{ -+ sb_info_t *si; -+ extifregs_t *eir; -+ chipcregs_t *cc; -+ uint32 n, m; -+ uint idx; -+ uint32 pll_type, rate; -+ uint intr_val = 0; ++ uint32 status; + -+ si = SB_INFO(sbh); -+ idx = si->curidx; -+ pll_type = PLL_TYPE1; ++ /* 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); + -+ INTR_OFF(si, intr_val); ++ W_REG(&di->d32txregs->control, 0); ++ SPINWAIT((status = (R_REG(&di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED, ++ 10000); + -+ /* 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 { -+ INTR_RESTORE(si, intr_val); -+ return 0; ++ if (status != XS_XS_DISABLED) { ++ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); + } + -+ // 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); -+ if (pll_type == PLL_TYPE3) -+ rate = rate / 2; -+ } ++ /* wait for the last transaction to complete */ ++ OSL_DELAY(300); ++} + -+ /* switch back to previous core */ -+ sb_setcoreidx(sbh, idx); ++static void ++dma32_rxreset(dma_info_t *di) ++{ ++ uint32 status; + -+ INTR_RESTORE(si, intr_val); ++ W_REG(&di->d32rxregs->control, 0); ++ SPINWAIT((status = (R_REG(&di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED, ++ 10000); + -+ return rate; ++ if (status != RS_RS_DISABLED) { ++ DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name)); ++ } +} + -+/* change logical "focus" to the gpio core for optimized access */ -+void* -+sb_gpiosetcore(sb_t *sbh) ++static bool ++dma32_txsuspendedidle(dma_info_t *di) +{ -+ sb_info_t *si; -+ -+ si = SB_INFO(sbh); ++ if (!(R_REG(&di->d32txregs->control) & XC_SE)) ++ return 0; ++ ++ if ((R_REG(&di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) ++ return 0; + -+ return (sb_setcoreidx(sbh, si->gpioidx)); ++ OSL_DELAY(2); ++ return ((R_REG(&di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); +} + -+/* mask&set gpiocontrol bits */ -+uint32 -+sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) ++/* ++ * 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) +{ -+ sb_info_t *si; -+ uint regoff; ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint txout; ++ uint32 ctrl; ++ uint32 pa; + -+ si = SB_INFO(sbh); -+ regoff = 0; ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ txout = di->txout; ++ ctrl = 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; -+ } ++ /* ++ * 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); + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpiocontrol); -+ break; ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; + -+ case SB_PCI: -+ regoff = OFFSETOF(sbpciregs_t, gpiocontrol); -+ break; ++ if (len == 0) ++ continue; + -+ case SB_EXTIF: -+ return (0); -+ } ++ /* get physical address of buffer start */ ++ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); + -+ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); -+} ++ /* build the descriptor control value */ ++ ctrl = len & CTRL_BC_MASK; + -+/* mask&set gpio output enable bits */ -+uint32 -+sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) -+{ -+ sb_info_t *si; -+ uint regoff; ++ ctrl |= coreflags; ++ ++ if (p == p0) ++ ctrl |= CTRL_SOF; ++ if (next == NULL) ++ ctrl |= (CTRL_IOC | CTRL_EOF); ++ if (txout == (di->ntxd - 1)) ++ ctrl |= CTRL_EOT; + -+ si = SB_INFO(sbh); -+ regoff = 0; ++ if (DMA64_ENAB(di)) { ++ dma64_dd_upd(di, di->txd64, pa, txout, &ctrl, len); ++ } else { ++ dma32_dd_upd(di, di->txd32, pa, txout, &ctrl); ++ } + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ ASSERT(di->txp[txout] == NULL); + -+ /* 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; ++ txout = NEXTTXD(txout); + } + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpioouten); -+ break; ++ /* 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)); + -+ case SB_PCI: -+ regoff = OFFSETOF(sbpciregs_t, gpioouten); -+ break; ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; + -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpio[0].outen); -+ break; ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* 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)); + } + -+ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); ++ /* tx flow control */ ++ di->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->txavail = 0; ++ di->hnddma.txnobuf++; ++ return (-1); +} + -+/* mask&set gpio output bits */ -+uint32 -+sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) ++static void* ++dma32_getnexttxp(dma_info_t *di, bool forceall) +{ -+ sb_info_t *si; -+ uint regoff; ++ 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); + -+ si = SB_INFO(sbh); -+ regoff = 0; ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ 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]); + -+ /* 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; ++ W_SM(&di->txd32[i].addr, 0xdeadbeef); ++ txp = di->txp[i]; ++ di->txp[i] = NULL; + } + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpioout); -+ break; ++ di->txin = i; + -+ case SB_PCI: -+ regoff = OFFSETOF(sbpciregs_t, gpioout); -+ break; ++ /* tx flow control */ ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpio[0].out); -+ break; -+ } ++ return (txp); + -+ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); ++bogus: ++/* ++ DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", ++ start, end, di->txout, forceall)); ++*/ ++ return (NULL); +} + -+/* reserve one gpio */ -+uint32 -+sb_gpioreserve(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) ++static void * ++dma32_getnextrxp(dma_info_t *di, bool forceall) +{ -+ sb_info_t *si; ++ uint i; ++ void *rxp; + -+ si = SB_INFO(sbh); ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma_rxenabled(di)); + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ i = di->rxin; + -+ /* 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; -+ } ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); + -+ /* already reserved */ -+ if (sb_gpioreservation & gpio_bitmask) -+ return -1; -+ /* set reservation */ -+ sb_gpioreservation |= gpio_bitmask; ++ /* ignore curr if forceall */ ++ if (!forceall && (i == B2I(R_REG(&di->d32rxregs->status) & RS_CD_MASK, dma32dd_t))) ++ return (NULL); + -+ return sb_gpioreservation; -+} ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; + -+/* release one gpio */ -+/* -+ * releasing the gpio doesn't change the current value on the GPIO last write value -+ * persists till some one overwrites it -+*/ ++ /* 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); + -+uint32 -+sb_gpiorelease(sb_t *sbh, uint32 gpio_bitmask, uint8 priority) -+{ -+ sb_info_t *si; ++ di->rxin = NEXTRXD(i); + -+ si = SB_INFO(sbh); ++ return (rxp); ++} + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++static void ++dma32_txrotate(di_t *di) ++{ ++ uint ad; ++ uint nactive; ++ uint rot; ++ uint old, new; ++ uint32 w; ++ uint first, last; + -+ /* 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; ++ ASSERT(dma_txsuspendedidle(di)); + -+ /* clear reservation */ -+ sb_gpioreservation &= ~gpio_bitmask; ++ nactive = dma_txactive(di); ++ ad = B2I(((R_REG(&di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t); ++ rot = TXD(ad - di->txin); + -+ return sb_gpioreservation; -+} ++ ASSERT(rot < di->ntxd); + -+/* return the current gpioin register value */ -+uint32 -+sb_gpioin(sb_t *sbh) -+{ -+ sb_info_t *si; -+ uint regoff; ++ /* 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; ++ } + -+ si = SB_INFO(sbh); -+ regoff = 0; ++ first = di->txin; ++ last = PREVTXD(di->txout); + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpioin); -+ break; ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); + -+ case SB_PCI: -+ regoff = OFFSETOF(sbpciregs_t, gpioin); -+ break; ++ /* ++ * 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)); + -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpioin); -+ break; ++ /* 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; + } + -+ return (sb_corereg(si, si->gpioidx, regoff, 0, 0)); ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ /* kick the chip */ ++ W_REG(&di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); +} + -+/* mask&set gpio interrupt polarity bits */ -+uint32 -+sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority) -+{ -+ sb_info_t *si; -+ uint regoff; ++/*** 64 bits DMA non-inline functions ***/ + -+ si = SB_INFO(sbh); -+ regoff = 0; ++#ifdef BCMDMA64 + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++static bool ++dma64_alloc(dma_info_t *di, uint direction) ++{ ++ uint size; ++ uint ddlen; ++ uint32 alignbytes; ++ void *va; + -+ /* 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; -+ } ++ ddlen = sizeof (dma64dd_t); + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpiointpolarity); -+ break; ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); + -+ case SB_PCI: -+ /* pci gpio implementation does not support interrupt polarity */ -+ ASSERT(0); -+ break; ++ alignbytes = di->dma64align; + -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpiointpolarity); -+ break; -+ } ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, alignbytes)) ++ size += alignbytes; + -+ 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; ++ 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; ++ } + -+ si = SB_INFO(sbh); -+ regoff = 0; ++ 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)); ++ } + -+ priority = GPIO_DRV_PRIORITY; /* compatibility hack */ ++ return TRUE; ++} + -+ /* 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; -+ } ++static void ++dma64_txreset(dma_info_t *di) ++{ ++ uint32 status; + -+ switch (si->gpioid) { -+ case SB_CC: -+ regoff = OFFSETOF(chipcregs_t, gpiointmask); -+ break; ++ /* 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); + -+ case SB_PCI: -+ /* pci gpio implementation does not support interrupt mask */ -+ ASSERT(0); -+ break; ++ W_REG(&di->d64txregs->control, 0); ++ SPINWAIT((status = (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED, ++ 10000); + -+ case SB_EXTIF: -+ regoff = OFFSETOF(extifregs_t, gpiointmask); -+ break; ++ if (status != D64_XS0_XS_DISABLED) { ++ DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name)); + } + -+ return (sb_corereg(si, si->gpioidx, regoff, mask, val)); ++ /* wait for the last transaction to complete */ ++ OSL_DELAY(300); +} + -+/* assign the gpio to an led */ -+uint32 -+sb_gpioled(sb_t *sbh, uint32 mask, uint32 val) ++static void ++dma64_rxreset(dma_info_t *di) +{ -+ sb_info_t *si; ++ uint32 status; + -+ si = SB_INFO(sbh); -+ if (si->sb.ccrev < 16) -+ return -1; ++ W_REG(&di->d64rxregs->control, 0); ++ SPINWAIT((status = (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED, ++ 10000); + -+ /* gpio led powersave reg */ -+ return(sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); ++ if (status != D64_RS0_RS_DISABLED) { ++ DMA_ERROR(("%s: dma_rxreset: dma cannot be stopped\n", di->name)); ++ } +} + -+/* mask&set gpio timer val */ -+uint32 -+sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 gpiotimerval) ++static bool ++dma64_txsuspendedidle(dma_info_t *di) +{ -+ sb_info_t *si; -+ si = SB_INFO(sbh); + -+ if (si->sb.ccrev < 16) -+ return -1; ++ 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; + -+ return(sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); ++ return 0; +} + -+ -+/* return the slow clock source - LPO, XTAL, or PCI */ -+static uint -+sb_slowclk_src(sb_info_t *si) ++/* ++ * 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) +{ -+ chipcregs_t *cc; ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint txout; ++ uint32 flags; ++ uint32 pa; + ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); + -+ ASSERT(sb_coreid(&si->sb) == SB_CC); ++ txout = di->txout; ++ flags = 0; + -+ 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); -+} ++ /* ++ * 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); + -+/* return the ILP (slowclock) min or max frequency */ -+static uint -+sb_slowclk_freq(sb_info_t *si, bool max) -+{ -+ chipcregs_t *cc; -+ uint32 slowclk; -+ uint div; ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; + ++ if (len == 0) ++ continue; + -+ ASSERT(sb_coreid(&si->sb) == SB_CC); ++ /* get physical address of buffer start */ ++ pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); + -+ cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); ++ 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; + -+ /* shouldn't be here unless we've established the chip has dynamic clk control */ -+ ASSERT(R_REG(&cc->capabilities) & CAP_PWR_CTL); ++ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); + -+ 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)); ++ ASSERT(di->txp[txout] == NULL); ++ ++ txout = NEXTTXD(txout); + } -+ return (0); -+} + -+static void -+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 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)); + -+ pll_delay = PLL_DELAY; ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; + -+ /* 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; ++ /* bump the tx descriptor index */ ++ di->txout = txout; + -+ /* Starting with 4318 it is ILP that is used for the delays */ -+ slowmaxfreq = sb_slowclk_freq(si, (si->sb.ccrev >= 10) ? FALSE : TRUE); ++ /* kick the chip */ ++ W_REG(&di->d64txregs->ptr, I2B(txout, dma64dd_t)); + -+ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; -+ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; ++ /* tx flow control */ ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+ cc = (chipcregs_t *)chipcregs; -+ W_REG(&cc->pll_on_delay, pll_on_delay); -+ W_REG(&cc->fref_sel_delay, fref_sel_delay); ++ return (0); ++ ++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); +} + -+int -+sb_pwrctl_slowclk(void *sbh, bool set, uint *div) ++static void* ++dma64_getnexttxp(dma_info_t *di, bool forceall) +{ -+ sb_info_t *si; -+ uint origidx; -+ chipcregs_t *cc; -+ uint intr_val = 0; -+ uint err = 0; -+ -+ si = SB_INFO(sbh); ++ uint start, end, i; ++ void *txp; + -+ /* chipcommon cores prior to rev6 don't support slowclkcontrol */ -+ if (si->sb.ccrev < 6) -+ return 1; ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); + -+ /* chipcommon cores rev10 are a whole new ball game */ -+ if (si->sb.ccrev >= 10) -+ return 1; ++ txp = NULL; + -+ 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; ++ start = di->txin; ++ if (forceall) ++ end = di->txout; ++ else ++ end = B2I(R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK, dma64dd_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->txd64[i].addrlow)) - di->dataoffsetlow), ++ (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) & D64_CTRL2_BC_MASK), DMA_TX, di->txp[i]); ++ ++ W_SM(&di->txd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); ++ ++ txp = di->txp[i]; ++ di->txp[i] = NULL; + } + -+ 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); ++ di->txin = i; ++ ++ /* tx flow control */ ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+done: -+ sb_setcoreidx(sbh, origidx); -+ INTR_RESTORE(si, intr_val); -+ return err; ++ 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); +} + -+/* initialize power control delay registers */ -+void sb_clkctl_init(sb_t *sbh) ++static void * ++dma64_getnextrxp(dma_info_t *di, bool forceall) +{ -+ sb_info_t *si; -+ uint origidx; -+ chipcregs_t *cc; ++ uint i; ++ void *rxp; + -+ si = SB_INFO(sbh); ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma_rxenabled(di)); + -+ origidx = si->curidx; ++ i = di->rxin; + -+ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) -+ return; ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); + -+ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) -+ goto done; ++ /* ignore curr if forceall */ ++ if (!forceall && (i == B2I(R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK, dma64dd_t))) ++ return (NULL); + -+ /* 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)); ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; + -+ /* 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); ++ /* 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); + -+done: -+ sb_setcoreidx(sbh, origidx); -+} -+void sb_pwrctl_init(sb_t *sbh) -+{ -+sb_clkctl_init(sbh); ++ W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); ++ ++ di->rxin = NEXTRXD(i); ++ ++ return (rxp); +} -+/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */ -+uint16 -+sb_clkctl_fast_pwrup_delay(sb_t *sbh) ++ ++static void ++dma64_txrotate(di_t *di) +{ -+ sb_info_t *si; -+ uint origidx; -+ chipcregs_t *cc; -+ uint slowminfreq; -+ uint16 fpdelay; -+ uint intr_val = 0; ++ uint ad; ++ uint nactive; ++ uint rot; ++ uint old, new; ++ uint32 w; ++ uint first, last; + -+ si = SB_INFO(sbh); -+ fpdelay = 0; -+ origidx = si->curidx; ++ ASSERT(dma_txsuspendedidle(di)); + -+ INTR_OFF(si, intr_val); ++ nactive = dma_txactive(di); ++ ad = B2I((R_REG(&di->d64txregs->status1) & D64_XS1_AD_MASK), dma64dd_t); ++ rot = TXD(ad - di->txin); + -+ if ((cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0)) == NULL) -+ goto done; ++ ASSERT(rot < di->ntxd); + -+ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) -+ goto done; ++ /* 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; ++ } + -+ slowminfreq = sb_slowclk_freq(si, FALSE); -+ fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) + (slowminfreq - 1)) / slowminfreq; ++ first = di->txin; ++ last = PREVTXD(di->txout); + -+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); -+} -+/* 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; ++ /* 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->txd64[old].ctrl1) & ~D64_CTRL1_EOT; ++ if (new == (di->ntxd - 1)) ++ w |= D64_CTRL1_EOT; ++ W_SM(&di->txd64[new].ctrl1, w); + -+ switch (BUSTYPE(si->sb.bustype)) { ++ w = R_SM(&di->txd64[old].ctrl2); ++ W_SM(&di->txd64[new].ctrl2, w); + ++ W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); ++ W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); + -+ case PCMCIA_BUS: -+ return (0); ++ /* zap the old tx dma descriptor address field */ ++ W_SM(&di->txd64[old].addrlow, 0xdeadbeef); ++ W_SM(&di->txd64[old].addrhigh, 0xdeadbeef); + ++ /* move the corresponding txp[] entry */ ++ ASSERT(di->txp[new] == NULL); ++ di->txp[new] = di->txp[old]; ++ di->txp[old] = NULL; ++ } + -+ case PCI_BUS: ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + -+ /* pcie core doesn't have any mapping to control the xtal pu */ -+ if (PCIE(si)) -+ return -1; ++ /* kick the chip */ ++ W_REG(&di->d64txregs->ptr, I2B(di->txout, dma64dd_t)); ++} + -+ 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)); ++#endif + -+ /* -+ * 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); +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$ ++ */ + -+ if (what & XTAL) -+ outen |= PCI_CFG_GPIO_XTAL; -+ if (what & PLL) -+ outen |= PCI_CFG_GPIO_PLL; ++#ifndef _hnddma_h_ ++#define _hnddma_h_ + -+ 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); -+ } ++/* 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; + -+ /* 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); -+ } ++#ifndef di_t ++#define di_t void ++#endif + -+ default: -+ return (-1); -+ } ++#ifndef osl_t ++#define osl_t void ++#endif + -+ return (0); -+} ++/* externs */ ++extern 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); ++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); + -+int sb_pwrctl_xtal(sb_t *sbh, uint what, bool on) -+{ -+return sb_clkctl_xtal(sbh,what,on); -+} ++extern void dma_rxpiomode(dma32regs_t *); ++extern void dma_txpioloopback(dma32regs_t *); + -+/* 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) -+{ -+ sb_info_t *si; -+ uint origidx; -+ chipcregs_t *cc; -+ uint32 scc; -+ bool forcefastclk=FALSE; -+ uint intr_val = 0; + -+ si = SB_INFO(sbh); ++#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$ ++ */ + -+ /* chipcommon cores prior to rev6 don't support dynamic clock control */ -+ if (si->sb.ccrev < 6) -+ return (FALSE); ++#ifndef _pktq_h_ ++#define _pktq_h_ + -+ /* chipcommon cores rev10 are a whole new ball game */ -+ if (si->sb.ccrev >= 10) -+ return (FALSE); ++/*** driver-only section ***/ ++#ifdef BCMDRIVER + -+ INTR_OFF(si, intr_val); ++/* 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 *); + -+ origidx = si->curidx; ++#define pktenq(pq, p) pktq_penq((pq), 0, (p)) /* legacy */ ++#define pktdeq(pq) pktq_pdeq((pq), 0) /* legacy */ + -+ cc = (chipcregs_t*) sb_setcore(sbh, SB_CC, 0); -+ ASSERT(cc != NULL); ++/* osl multi-precedence packet queue */ + -+ if (!(R_REG(&cc->capabilities) & CAP_PWR_CTL)) -+ goto done; ++#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 */ ++}; + -+ 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); ++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 */ ++}; + -+ SET_REG(&cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); -+ break; ++/* operations on a specific precedence in packet queue */ + -+ 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); ++#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) + -+ /* for dynamic control, we have to release our xtal_pu "force on" */ -+ if (scc & SCC_XC) -+ sb_clkctl_xtal(&si->sb, XTAL, OFF); -+ break; ++#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) ++#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) + -+ default: -+ ASSERT(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); + -+ /* Is the h/w forcing the use of the fast clk */ -+ forcefastclk = (bool)((R_REG(&cc->slow_clk_ctl) & SCC_IP) == SCC_IP); ++/* operations on packet queue as a whole */ + -+done: -+ sb_setcoreidx(sbh, origidx); -+ INTR_RESTORE(si, intr_val); -+ return (forcefastclk); -+} ++extern void pktq_init(struct pktq *pq, int num_prec, int max); + -+bool sb_pwrctl_clk(sb_t *sbh, uint mode) -+{ -+return sb_clkctl_clk(sbh, mode); -+} -+/* 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) -+{ -+ sb_info_t *si; ++#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) + -+ 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]; -+} ++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 int pktq_mlen(struct pktq *pq, uint prec_bmp); ++extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); + -+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); ++#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) + -+ chip = BCMINIT(sb_chip)(sbh); -+ chippkg = BCMINIT(sb_chippkg)(sbh); ++#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$ ++ */ + -+ progif = 0; -+ -+ /* Known vendor translations */ -+ switch (vendor) { -+ case SB_VEND_BCM: -+ vendor = VENDOR_BROADCOM; -+ break; -+ } ++#ifndef _sbhnddma_h_ ++#define _sbhnddma_h_ + -+ /* 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; -+ } -+ } -+ break; ++ ++/* 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; + -+ default: -+ class = subclass = progif = 0xff; -+ break; -+ } ++/* a pair of pio channels(tx and rx) */ ++typedef volatile struct { ++ pio2regs_t tx; ++ pio2regs_t rx; ++} pio2regp_t; + -+ *pcivendor = (uint16)vendor; -+ *pcidevice = (uint16)core; -+ *pciclass = class; -+ *pcisubclass = subclass; -+ *pciprogif = progif; -+} ++/* 4byte-wide pio register set per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 fifocontrol; ++ uint32 fifodata; ++} pio4regs_t; + ++/* a pair of pio channels(tx and rx) */ ++typedef volatile struct { ++ pio4regs_t tx; ++ pio4regs_t rx; ++} pio4regp_t; + + + -+/* 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; ++/* 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 ++ */ + -+ pcieregs = (sbpcieregs_t*) sb_setcoreidx(&si->sb, si->sb.buscoreidx); -+ ASSERT (pcieregs); + -+ /* enable mdio access to SERDES */ -+ W_REG((&pcieregs->mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); ++/*** 32 bits addressing ***/ + -+ mdiodata = MDIODATA_START | MDIODATA_WRITE | -+ (physmedia << MDIODATA_DEVADDR_SHF) | -+ (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA | val; ++/* 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; + -+ W_REG((&pcieregs->mdiodata), mdiodata); ++typedef volatile struct { ++ dma32regs_t xmt; /* dma tx channel */ ++ dma32regs_t rcv; /* dma rx channel */ ++} dma32regp_t; + -+ PR28829_DELAY(); ++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; + -+ /* 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; -+ } -+ OSL_DELAY(1000); -+ i++; -+ } ++/* ++ * 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; + -+ SB_ERROR(("sb_pcie_mdiowrite: timed out\n")); -+ /* Disable mdio access to SERDES */ -+ W_REG((&pcieregs->mdiocontrol), 0); -+ ASSERT(0); -+ return 1; ++/* ++ * 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)) + -+} ++/* 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 + -+/* indirect way to read pcie config regs*/ -+uint -+sb_pcie_readreg(void *sb, void* arg1, uint offset) -+{ -+ sb_info_t *si; -+ sb_t *sbh; -+ uint retval = 0xFFFFFFFF; -+ sbpcieregs_t *pcieregs; -+ uint addrtype; ++/* transmit descriptor table pointer */ ++#define XP_LD_MASK 0xfff /* last valid descriptor */ + -+ sbh = (sb_t *)sb; -+ si = SB_INFO(sbh); -+ ASSERT (PCIE(si)); ++/* 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 + -+ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); -+ ASSERT (pcieregs); ++/* 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 + -+ 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; -+} ++/* receive descriptor table pointer */ ++#define RP_LD_MASK 0xfff /* last valid descriptor */ + -+/* 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; ++/* 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 + -+ si = SB_INFO(sbh); -+ ASSERT (PCIE(si)); ++/* 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 */ + -+ pcieregs = (sbpcieregs_t *)sb_setcore(sbh, SB_PCIE, 0); -+ ASSERT (pcieregs); ++/* 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 */ + -+ addrtype = (uint)((uintptr)arg1); ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define CTRL_CORE_MASK 0x0ff00000 + -+ 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; -+} ++/*** 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; + -+/* 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); -+ -+ 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; -+ } ++typedef volatile struct { ++ dma64regs_t tx; /* dma64 tx channel */ ++ dma64regs_t rx; /* dma64 rx channel */ ++} dma64regp_t; + -+ 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 */ ++} dma64diag_t; + -+/* Fix chip's configuration. The current core may be changed upon return */ -+static int -+sb_pci_fixcfg(sb_info_t *si) -+{ -+ uint origidx, pciidx; -+ sbpciregs_t *pciregs; -+ sbpcieregs_t *pcieregs; -+ uint16 val16, *reg16; -+ char name[SB_DEVPATH_BUFSZ+16], *value; -+ char devpath[SB_DEVPATH_BUFSZ]; ++/* ++ * 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; + -+ ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS); ++/* ++ * 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)) + -+ /* Fix PCI(e) SROM shadow area */ -+ /* save the current index */ -+ origidx = sb_coreidx(&si->sb); ++/* 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 + -+ /* 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); -+ } ++/* transmit descriptor table pointer */ ++#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ + -+ /* 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; -+ } -+ } ++/* 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 */ + -+ return 0; -+} ++#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 */ + -diff -Nur linux-2.4.32/drivers/net/hnd/shared_ksyms.sh linux-2.4.32-brcm/drivers/net/hnd/shared_ksyms.sh ---- linux-2.4.32/drivers/net/hnd/shared_ksyms.sh 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/hnd/shared_ksyms.sh 2005-12-16 23:39:11.316860000 +0100 -@@ -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 $ -+# ++/* 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 + -+cat < -+#include -+EOF ++/* receive descriptor table pointer */ ++#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ + -+for file in $* ; do -+ ${NM} $file | sed -ne 's/[0-9A-Fa-f]* [DT] \([^ ]*\)/extern void \1; EXPORT_SYMBOL(\1);/p' -+done -diff -Nur linux-2.4.32/drivers/net/Makefile linux-2.4.32-brcm/drivers/net/Makefile ---- linux-2.4.32/drivers/net/Makefile 2005-01-19 15:09:56.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/Makefile 2005-12-16 23:39:11.284858000 +0100 -@@ -3,6 +3,8 @@ - # Makefile for the Linux network (ethercard) device drivers. - # - -+EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include ++/* 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 */ + - obj-y := - obj-m := - obj-n := -@@ -39,6 +41,8 @@ - obj-$(CONFIG_ISDN) += slhc.o - endif - -+subdir-$(CONFIG_HND) += hnd -+subdir-$(CONFIG_WL) += wl - subdir-$(CONFIG_NET_PCMCIA) += pcmcia - subdir-$(CONFIG_NET_WIRELESS) += wireless - subdir-$(CONFIG_TULIP) += tulip -@@ -69,6 +74,13 @@ - obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o - obj-$(CONFIG_SUNGEM) += sungem.o - -+ifeq ($(CONFIG_HND),y) -+ obj-y += hnd/hnd.o -+endif -+ifeq ($(CONFIG_WL),y) -+ obj-y += wl/wl.o -+endif ++#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 */ + - obj-$(CONFIG_MACE) += mace.o - obj-$(CONFIG_BMAC) += bmac.o - obj-$(CONFIG_GMAC) += gmac.o -diff -Nur linux-2.4.32/drivers/net/wireless/Config.in linux-2.4.32-brcm/drivers/net/wireless/Config.in ---- linux-2.4.32/drivers/net/wireless/Config.in 2004-11-17 12:54:21.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/wireless/Config.in 2005-12-16 23:39:11.364863000 +0100 -@@ -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 -Nur linux-2.4.32/drivers/net/wl/Makefile linux-2.4.32-brcm/drivers/net/wl/Makefile ---- linux-2.4.32/drivers/net/wl/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/net/wl/Makefile 2005-12-16 23:39:11.364863000 +0100 -@@ -0,0 +1,26 @@ -+# -+# 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 $ ++/* 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 */ + -+EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include ++/* 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 */ + -+O_TARGET := wl.o ++/* 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 + -+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 ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define D64_CTRL_CORE_MASK 0x0ff00000 + -+obj-m := $(O_TARGET) + -+include $(TOPDIR)/Rules.make -diff -Nur linux-2.4.32/drivers/parport/Config.in linux-2.4.32-brcm/drivers/parport/Config.in ---- linux-2.4.32/drivers/parport/Config.in 2004-02-18 14:36:31.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/parport/Config.in 2005-12-16 23:39:11.364863000 +0100 ++#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 @@ -17863,9 +20224,9 @@ diff -Nur linux-2.4.32/drivers/parport/Config.in linux-2.4.32-brcm/drivers/parpo if [ "$CONFIG_PARPORT_PC" != "n" -a "$CONFIG_SERIAL" != "n" ]; then if [ "$CONFIG_SERIAL" = "m" ]; then define_tristate CONFIG_PARPORT_PC_CML1 m -diff -Nur linux-2.4.32/drivers/parport/Makefile linux-2.4.32-brcm/drivers/parport/Makefile ---- linux-2.4.32/drivers/parport/Makefile 2004-08-08 01:26:05.000000000 +0200 -+++ linux-2.4.32-brcm/drivers/parport/Makefile 2005-12-16 23:39:11.364863000 +0100 +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 @@ -17874,9 +20235,9 @@ diff -Nur linux-2.4.32/drivers/parport/Makefile linux-2.4.32-brcm/drivers/parpor obj-$(CONFIG_PARPORT_PC_PCMCIA) += parport_cs.o obj-$(CONFIG_PARPORT_AMIGA) += parport_amiga.o obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o -diff -Nur linux-2.4.32/drivers/parport/parport_splink.c linux-2.4.32-brcm/drivers/parport/parport_splink.c ---- linux-2.4.32/drivers/parport/parport_splink.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/parport/parport_splink.c 2005-12-16 23:39:11.364863000 +0100 +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 + * @@ -18223,9 +20584,32 @@ diff -Nur linux-2.4.32/drivers/parport/parport_splink.c linux-2.4.32-brcm/driver +module_init(parport_splink_init) +module_exit(parport_splink_cleanup) + -diff -Nur linux-2.4.32/drivers/pcmcia/bcm4710_generic.c linux-2.4.32-brcm/drivers/pcmcia/bcm4710_generic.c ---- linux-2.4.32/drivers/pcmcia/bcm4710_generic.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/pcmcia/bcm4710_generic.c 2005-12-16 23:39:11.368863250 +0100 +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 @@ +/* + * @@ -19139,9 +21523,9 @@ diff -Nur linux-2.4.32/drivers/pcmcia/bcm4710_generic.c linux-2.4.32-brcm/driver + + +#endif /* defined(CONFIG_PROC_FS) */ -diff -Nur linux-2.4.32/drivers/pcmcia/bcm4710_pcmcia.c linux-2.4.32-brcm/drivers/pcmcia/bcm4710_pcmcia.c ---- linux-2.4.32/drivers/pcmcia/bcm4710_pcmcia.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/pcmcia/bcm4710_pcmcia.c 2005-12-16 23:39:11.368863250 +0100 +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. @@ -19409,9 +21793,9 @@ diff -Nur linux-2.4.32/drivers/pcmcia/bcm4710_pcmcia.c linux-2.4.32-brcm/drivers + bcm4710_pcmcia_configure_socket +}; + -diff -Nur linux-2.4.32/drivers/pcmcia/bcm4710pcmcia.h linux-2.4.32-brcm/drivers/pcmcia/bcm4710pcmcia.h ---- linux-2.4.32/drivers/pcmcia/bcm4710pcmcia.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/pcmcia/bcm4710pcmcia.h 2005-12-16 23:39:11.368863250 +0100 +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 @@ +/* + * @@ -19531,32 +21915,9 @@ diff -Nur linux-2.4.32/drivers/pcmcia/bcm4710pcmcia.h linux-2.4.32-brcm/drivers/ +extern struct pcmcia_low_level bcm4710_pcmcia_ops; + +#endif /* !defined(_BCM4710PCMCIA_H) */ -diff -Nur linux-2.4.32/drivers/pcmcia/Makefile linux-2.4.32-brcm/drivers/pcmcia/Makefile ---- linux-2.4.32/drivers/pcmcia/Makefile 2004-02-18 14:36:31.000000000 +0100 -+++ linux-2.4.32-brcm/drivers/pcmcia/Makefile 2005-12-16 23:39:11.364863000 +0100 -@@ -65,6 +65,10 @@ - au1000_ss-objs-$(CONFIG_PCMCIA_DB1X00) += au1000_db1x00.o - au1000_ss-objs-$(CONFIG_PCMCIA_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 -@@ -102,5 +106,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 -Nur linux-2.4.32/include/asm-mips/bootinfo.h linux-2.4.32-brcm/include/asm-mips/bootinfo.h ---- linux-2.4.32/include/asm-mips/bootinfo.h 2004-02-18 14:36:32.000000000 +0100 -+++ linux-2.4.32-brcm/include/asm-mips/bootinfo.h 2005-12-16 23:39:11.400865250 +0100 +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 @@ -37,6 +37,7 @@ #define MACH_GROUP_HP_LJ 20 /* Hewlett Packard LaserJet */ #define MACH_GROUP_LASAT 21 @@ -19565,7 +21926,7 @@ diff -Nur linux-2.4.32/include/asm-mips/bootinfo.h linux-2.4.32-brcm/include/asm /* * Valid machtype values for group unknown (low order halfword of mips_machtype) -@@ -194,6 +195,15 @@ +@@ -197,6 +198,15 @@ #define MACH_TANBAC_TB0229 7 /* TANBAC TB0229 (VR4131DIMM) */ /* @@ -19581,9 +21942,9 @@ diff -Nur linux-2.4.32/include/asm-mips/bootinfo.h linux-2.4.32-brcm/include/asm * Valid machtype for group TITAN */ #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */ -diff -Nur linux-2.4.32/include/asm-mips/cpu.h linux-2.4.32-brcm/include/asm-mips/cpu.h ---- linux-2.4.32/include/asm-mips/cpu.h 2005-01-19 15:10:11.000000000 +0100 -+++ linux-2.4.32-brcm/include/asm-mips/cpu.h 2005-12-16 23:39:11.412866000 +0100 +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 @@ -22,6 +22,11 @@ spec. */ @@ -19632,10 +21993,10 @@ diff -Nur linux-2.4.32/include/asm-mips/cpu.h linux-2.4.32-brcm/include/asm-mips /* * ISA Level encodings -diff -Nur linux-2.4.32/include/asm-mips/r4kcache.h linux-2.4.32-brcm/include/asm-mips/r4kcache.h ---- linux-2.4.32/include/asm-mips/r4kcache.h 2004-02-18 14:36:32.000000000 +0100 -+++ linux-2.4.32-brcm/include/asm-mips/r4kcache.h 2005-12-16 23:39:11.416866250 +0100 -@@ -567,4 +567,17 @@ +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 +@@ -658,4 +658,17 @@ cache128_unroll32(addr|ws,Index_Writeback_Inv_SD); } @@ -19653,9 +22014,9 @@ diff -Nur linux-2.4.32/include/asm-mips/r4kcache.h linux-2.4.32-brcm/include/asm +} + #endif /* __ASM_R4KCACHE_H */ -diff -Nur linux-2.4.32/include/asm-mips/serial.h linux-2.4.32-brcm/include/asm-mips/serial.h ---- linux-2.4.32/include/asm-mips/serial.h 2005-01-19 15:10:12.000000000 +0100 -+++ linux-2.4.32-brcm/include/asm-mips/serial.h 2005-12-16 23:39:11.428867000 +0100 +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 @@ -223,6 +223,13 @@ #define TXX927_SERIAL_PORT_DEFNS #endif @@ -19678,10 +22039,10 @@ diff -Nur linux-2.4.32/include/asm-mips/serial.h linux-2.4.32-brcm/include/asm-m COBALT_SERIAL_PORT_DEFNS \ DDB5477_SERIAL_PORT_DEFNS \ EV96100_SERIAL_PORT_DEFNS \ -diff -Nur linux-2.4.32/init/do_mounts.c linux-2.4.32-brcm/init/do_mounts.c ---- linux-2.4.32/init/do_mounts.c 2003-11-28 19:26:21.000000000 +0100 -+++ linux-2.4.32-brcm/init/do_mounts.c 2005-12-16 23:39:11.504871750 +0100 -@@ -253,7 +253,13 @@ +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 +@@ -254,7 +254,13 @@ { "ftlb", 0x2c08 }, { "ftlc", 0x2c10 }, { "ftld", 0x2c18 },