-+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;
-+
-+ /* clear tx descriptor ring */
-+ BZERO_SM((void*)di->txd, (di->ntxd * sizeof (dmadd_t)));
-+
-+ W_REG(&di->regs->xmtcontrol, XC_XE);
-+ W_REG(&di->regs->xmtaddr, (di->txdpa + di->ddoffset));
-+}
-+
-+bool
-+dma_txenabled(dma_info_t *di)
-+{
-+ uint32 xc;
-+
-+ /* If the chip is dead, it is not enabled :-) */
-+ xc = R_REG(&di->regs->xmtcontrol);
-+ return ((xc != 0xffffffff) && (xc & XC_XE));
-+}
-+
-+void
-+dma_txsuspend(dma_info_t *di)
-+{
-+ DMA_TRACE(("%s: dma_txsuspend\n", di->name));
-+ OR_REG(&di->regs->xmtcontrol, XC_SE);
-+}
-+
-+void
-+dma_txresume(dma_info_t *di)
-+{
-+ DMA_TRACE(("%s: dma_txresume\n", di->name));
-+ AND_REG(&di->regs->xmtcontrol, ~XC_SE);
-+}
-+
-+bool
-+dma_txsuspended(dma_info_t *di)
-+{
-+ uint32 xc;
-+ uint32 xs;
-+
-+ xc = R_REG(&di->regs->xmtcontrol);
-+ if (xc & XC_SE) {
-+ xs = R_REG(&di->regs->xmtstatus);
-+ return ((xs & XS_XS_MASK) == XS_XS_IDLE);
-+ }
-+ return 0;
-+}
-+
-+bool
-+dma_txstopped(dma_info_t *di)
-+{
-+ return ((R_REG(&di->regs->xmtstatus) & XS_XS_MASK) == XS_XS_STOPPED);
-+}
-+
-+bool
-+dma_rxstopped(dma_info_t *di)
-+{
-+ return ((R_REG(&di->regs->rcvstatus) & RS_RS_MASK) == RS_RS_STOPPED);
-+}
-+
-+void
-+dma_fifoloopbackenable(dma_info_t *di)
-+{
-+ DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name));
-+ OR_REG(&di->regs->xmtcontrol, XC_LE);
-+}
-+
-+void
-+dma_rxinit(dma_info_t *di)
-+{
-+ DMA_TRACE(("%s: dma_rxinit\n", di->name));
-+
-+ di->rxin = di->rxout = 0;
-+
-+ /* clear rx descriptor ring */
-+ BZERO_SM((void*)di->rxd, (di->nrxd * sizeof (dmadd_t)));
-+
-+ dma_rxenable(di);
-+ W_REG(&di->regs->rcvaddr, (di->rxdpa + di->ddoffset));
-+}
-+
-+void
-+dma_rxenable(dma_info_t *di)
-+{
-+ DMA_TRACE(("%s: dma_rxenable\n", di->name));
-+ W_REG(&di->regs->rcvcontrol, ((di->rxoffset << RC_RO_SHIFT) | RC_RE));
-+}
-+
-+bool
-+dma_rxenabled(dma_info_t *di)
-+{
-+ uint32 rc;
-+
-+ rc = R_REG(&di->regs->rcvcontrol);
-+ return ((rc != 0xffffffff) && (rc & RC_RE));
-+}
-+
-+/*
-+ * The BCM47XX family supports full 32bit dma engine buffer addressing so
-+ * dma buffers can cross 4 Kbyte page boundaries.
-+ */
-+int
-+dma_txfast(dma_info_t *di, void *p0, uint32 coreflags)
-+{
-+ void *p, *next;
-+ uchar *data;
-+ uint len;
-+ uint txout;
-+ uint32 ctrl;
-+ uint32 pa;
-+
-+ DMA_TRACE(("%s: dma_txfast\n", di->name));
-+
-+ txout = di->txout;
-+ ctrl = 0;
-+
-+ /*
-+ * Walk the chain of packet buffers
-+ * allocating and initializing transmit descriptor entries.
-+ */
-+ for (p = p0; p; p = next) {
-+ data = PKTDATA(di->drv, p);
-+ len = PKTLEN(di->drv, p);
-+ next = PKTNEXT(di->drv, 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->dev, 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;
-+
-+ /* init the tx descriptor */
-+ W_SM(&di->txd[txout].ctrl, BUS_SWAP32(ctrl));
-+ W_SM(&di->txd[txout].addr, BUS_SWAP32(pa + di->dataoffset));
-+
-+ ASSERT(di->txp[txout] == NULL);
-+
-+ txout = NEXTTXD(txout);
-+ }
-+
-+ /* if last txd eof not set, fix it */
-+ if (!(ctrl & CTRL_EOF))
-+ W_SM(&di->txd[PREVTXD(txout)].ctrl, BUS_SWAP32(ctrl | CTRL_IOC | CTRL_EOF));
-+
-+ /* save the packet */
-+ di->txp[PREVTXD(txout)] = p0;
-+
-+ /* bump the tx descriptor index */
-+ di->txout = txout;
-+
-+ /* kick the chip */
-+ W_REG(&di->regs->xmtptr, I2B(txout));
-+
-+ /* 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->drv, p0, TRUE);
-+ di->txavail = 0;
-+ di->hnddma.txnobuf++;
-+ return (-1);
-+}
-+
-+#define PAGESZ 4096
-+#define PAGEBASE(x) ((uint)(x) & ~4095)
-+
-+/*
-+ * Just like above except go through the extra effort of splitting
-+ * buffers that cross 4Kbyte boundaries into multiple tx descriptors.
-+ */
-+int
-+dma_tx(dma_info_t *di, void *p0, uint32 coreflags)
-+{
-+ void *p, *next;
-+ uchar *data;
-+ uint plen, len;
-+ uchar *page, *start, *end;
-+ uint txout;
-+ uint32 ctrl;
-+ uint32 pa;
-+
-+ DMA_TRACE(("%s: dma_tx\n", di->name));
-+
-+ txout = di->txout;
-+ ctrl = 0;
-+
-+ /*
-+ * Walk the chain of packet buffers
-+ * splitting those that cross 4 Kbyte boundaries
-+ * allocating and initializing transmit descriptor entries.
-+ */
-+ for (p = p0; p; p = next) {
-+ data = PKTDATA(di->drv, p);
-+ plen = PKTLEN(di->drv, p);
-+ next = PKTNEXT(di->drv, p);
-+
-+ if (plen == 0)
-+ continue;
-+
-+ for (page = (uchar*)PAGEBASE(data);
-+ page <= (uchar*)PAGEBASE(data + plen - 1);
-+ page += PAGESZ) {
-+
-+ /* return nonzero if out of tx descriptors */
-+ if (NEXTTXD(txout) == di->txin)
-+ goto outoftxd;
-+
-+ start = (page == (uchar*)PAGEBASE(data))? data: page;
-+ end = (page == (uchar*)PAGEBASE(data + plen))?
-+ (data + plen): (page + PAGESZ);
-+ len = end - start;
-+
-+ /* build the descriptor control value */
-+ ctrl = len & CTRL_BC_MASK;
-+
-+ ctrl |= coreflags;
-+
-+ if ((p == p0) && (start == data))
-+ ctrl |= CTRL_SOF;
-+ if ((next == NULL) && (end == (data + plen)))
-+ ctrl |= (CTRL_IOC | CTRL_EOF);
-+ if (txout == (di->ntxd - 1))
-+ ctrl |= CTRL_EOT;
-+
-+ /* get physical address of buffer start */
-+ pa = (uint32) DMA_MAP(di->dev, start, len, DMA_TX, p);
-+
-+ /* init the tx descriptor */
-+ W_SM(&di->txd[txout].ctrl, BUS_SWAP32(ctrl));
-+ W_SM(&di->txd[txout].addr, BUS_SWAP32(pa + di->dataoffset));
-+
-+ ASSERT(di->txp[txout] == NULL);
-+
-+ txout = NEXTTXD(txout);
-+ }
-+ }
-+
-+ /* if last txd eof not set, fix it */
-+ if (!(ctrl & CTRL_EOF))
-+ W_SM(&di->txd[PREVTXD(txout)].ctrl, BUS_SWAP32(ctrl | CTRL_IOC | CTRL_EOF));
-+
-+ /* save the packet */
-+ di->txp[PREVTXD(txout)] = p0;
-+
-+ /* bump the tx descriptor index */
-+ di->txout = txout;
-+
-+ /* kick the chip */
-+ W_REG(&di->regs->xmtptr, I2B(txout));
-+
-+ /* tx flow control */
-+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-+
-+ return (0);
-+
-+outoftxd:
-+ DMA_ERROR(("%s: dma_tx: out of txds\n", di->name));
-+ PKTFREE(di->drv, p0, TRUE);
-+ di->txavail = 0;
-+ di->hnddma.txnobuf++;
-+ return (-1);
-+}
-+
-+/* returns a pointer to the next frame received, or NULL if there are no more */
-+void*
-+dma_rx(dma_info_t *di)
-+{
-+ 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->drv, p, FALSE);
-+ continue;
-+ }
-+
-+ len = ltoh16(*(uint16*)(PKTDATA(di->drv, 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->drv, p, FALSE);
-+ di->hnddma.rxgiants++;
-+ continue;
-+ }
-+
-+ /* set actual length */
-+ PKTSETLEN(di->drv, p, (di->rxoffset + len));
-+
-+ break;
-+ }
-+
-+ return (p);
-+}
-+
-+/* post receive buffers */
-+void
-+dma_rxfill(dma_info_t *di)
-+{
-+ void *p;
-+ uint rxin, rxout;
-+ uint ctrl;
-+ uint n;
-+ uint i;
-+ uint32 pa;
-+ uint rxbufsize;
-+
-+ /*
-+ * Determine how many receive buffers we're lacking
-+ * from the full complement, allocate, initialize,
-+ * and post them, then update the chip rx lastdscr.
-+ */
-+
-+ rxin = di->rxin;
-+ rxout = di->rxout;
-+ rxbufsize = di->rxbufsize;
-+
-+ n = di->nrxpost - NRXDACTIVE(rxin, rxout);
-+
-+ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));
-+
-+ for (i = 0; i < n; i++) {
-+ if ((p = PKTGET(di->drv, rxbufsize, FALSE)) == NULL) {
-+ DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", di->name));
-+ di->hnddma.rxnobuf++;
-+ break;
-+ }
-+
-+ *(uint32*)(OSL_UNCACHED(PKTDATA(di->drv, p))) = 0;
-+
-+ pa = (uint32) DMA_MAP(di->dev, PKTDATA(di->drv, p), rxbufsize, DMA_RX, p);
-+ ASSERT(ISALIGNED(pa, 4));
-+
-+ /* save the free packet pointer */
-+ ASSERT(di->rxp[rxout] == NULL);
-+ di->rxp[rxout] = p;
-+
-+ /* prep the descriptor control value */
-+ ctrl = rxbufsize;
-+ if (rxout == (di->nrxd - 1))
-+ ctrl |= CTRL_EOT;
-+
-+ /* init the rx descriptor */
-+ W_SM(&di->rxd[rxout].ctrl, BUS_SWAP32(ctrl));
-+ W_SM(&di->rxd[rxout].addr, BUS_SWAP32(pa + di->dataoffset));
-+
-+ rxout = NEXTRXD(rxout);
-+ }
-+
-+ di->rxout = rxout;
-+
-+ /* update the chip lastdscr pointer */
-+ W_REG(&di->regs->rcvptr, I2B(rxout));
-+}
-+
-+void
-+dma_txreclaim(dma_info_t *di, bool forceall)
-+{
-+ void *p;
-+
-+ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : ""));
-+
-+ while ((p = dma_getnexttxp(di, forceall)))
-+ PKTFREE(di->drv, p, TRUE);
-+}
-+
-+/*
-+ * 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)
-+{
-+ 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->regs->xmtstatus) & XS_CD_MASK);
-+
-+ if ((start == 0) && (end > di->txout))
-+ goto bogus;
-+
-+ for (i = start; i != end && !txp; i = NEXTTXD(i)) {
-+ DMA_UNMAP(di->dev, (BUS_SWAP32(R_SM(&di->txd[i].addr)) - di->dataoffset),
-+ (BUS_SWAP32(R_SM(&di->txd[i].ctrl)) & CTRL_BC_MASK), DMA_TX, di->txp[i]);
-+ W_SM(&di->txd[i].addr, 0xdeadbeef);
-+ txp = di->txp[i];
-+ di->txp[i] = NULL;
-+ }
-+
-+ 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);
-+}
-+
-+void
-+dma_rxreclaim(dma_info_t *di)
-+{
-+ void *p;
-+
-+ DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
-+
-+ while ((p = dma_getnextrxp(di, TRUE)))
-+ PKTFREE(di->drv, p, FALSE);
-+}
-+
-+void *
-+dma_getnextrxp(dma_info_t *di, bool forceall)
-+{
-+ 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);
-+
-+ /* ignore curr if forceall */
-+ if (!forceall && (i == B2I(R_REG(&di->regs->rcvstatus) & RS_CD_MASK)))
-+ return (NULL);
-+
-+ /* get the packet pointer that corresponds to the rx descriptor */
-+ rxp = di->rxp[i];
-+ ASSERT(rxp);
-+ di->rxp[i] = NULL;
-+
-+ /* clear this packet from the descriptor ring */
-+ DMA_UNMAP(di->dev, (BUS_SWAP32(R_SM(&di->rxd[i].addr)) - di->dataoffset),
-+ di->rxbufsize, DMA_RX, rxp);
-+ W_SM(&di->rxd[i].addr, 0xdeadbeef);
-+
-+ di->rxin = NEXTRXD(i);
-+
-+ return (rxp);
-+}
-+
-+char*
-+dma_dumptx(dma_info_t *di, char *buf)
-+{
-+ buf += sprintf(buf, "txd 0x%lx txdpa 0x%lx txp 0x%lx txin %d txout %d txavail %d\n",
-+ (ulong)di->txd, di->txdpa, (ulong)di->txp, di->txin, di->txout, di->txavail);
-+ buf += sprintf(buf, "xmtcontrol 0x%x xmtaddr 0x%x xmtptr 0x%x xmtstatus 0x%x\n",
-+ R_REG(&di->regs->xmtcontrol),
-+ R_REG(&di->regs->xmtaddr),
-+ R_REG(&di->regs->xmtptr),
-+ R_REG(&di->regs->xmtstatus));
-+ return (buf);
-+}
-+
-+char*
-+dma_dumprx(dma_info_t *di, char *buf)
-+{
-+ buf += sprintf(buf, "rxd 0x%lx rxdpa 0x%lx rxp 0x%lx rxin %d rxout %d\n",
-+ (ulong)di->rxd, di->rxdpa, (ulong)di->rxp, di->rxin, di->rxout);
-+ buf += sprintf(buf, "rcvcontrol 0x%x rcvaddr 0x%x rcvptr 0x%x rcvstatus 0x%x\n",
-+ R_REG(&di->regs->rcvcontrol),
-+ R_REG(&di->regs->rcvaddr),
-+ R_REG(&di->regs->rcvptr),
-+ R_REG(&di->regs->rcvstatus));
-+ return (buf);
-+}
-+
-+char*
-+dma_dump(dma_info_t *di, char *buf)
-+{
-+ buf = dma_dumptx(di, buf);
-+ buf = dma_dumprx(di, buf);
-+ return (buf);
-+}
-+
-+uint
-+dma_getvar(dma_info_t *di, char *name)
-+{
-+ if (!strcmp(name, "&txavail"))
-+ return ((uint) &di->txavail);
-+ else {
-+ ASSERT(0);
-+ }
-+ return (0);
-+}
-+
-+void
-+dma_txblock(dma_info_t *di)
-+{
-+ di->txavail = 0;
-+}
-+
-+void
-+dma_txunblock(dma_info_t *di)
-+{
-+ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-+}
-+
-+uint
-+dma_txactive(dma_info_t *di)
-+{
-+ return (NTXDACTIVE(di->txin, di->txout));
-+}
-diff -Nur linux-2.6.12.5/arch/mips/bcm947xx/broadcom/linux_osl.c linux-2.6.12.5-brcm/arch/mips/bcm947xx/broadcom/linux_osl.c
---- linux-2.6.12.5/arch/mips/bcm947xx/broadcom/linux_osl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.12.5-brcm/arch/mips/bcm947xx/broadcom/linux_osl.c 2005-11-07 01:12:51.815809250 +0100
-@@ -0,0 +1,420 @@
-+/*
-+ * Linux OS Independent Layer
-+ *
-+ * Copyright 2001-2003, Broadcom Corporation
-+ * All Rights Reserved.
-+ *
-+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
-+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
-+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
-+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
-+ *
-+ * $Id: linux_osl.c,v 1.2 2005/02/28 13:34:25 jolt Exp $
-+ */
-+
-+#define LINUX_OSL
-+
-+#include <typedefs.h>
-+#include <bcmendian.h>
-+#include <linuxver.h>
-+#include <linux_osl.h>
-+#include <bcmutils.h>
-+#include <linux/delay.h>
-+#ifdef mips
-+#include <asm/paccess.h>
-+#endif
-+#include <pcicfg.h>
-+
-+#define PCI_CFG_RETRY 10
-+
-+void*
-+osl_pktget(void *drv, 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(void *loc, uint offset, uint size)
-+{
-+ struct pci_dev *pdev;
-+ uint val;
-+ uint retry=PCI_CFG_RETRY;
-+
-+ /* only 4byte access supported */
-+ ASSERT(size == 4);
-+
-+ pdev = (struct pci_dev*)loc;
-+ do {
-+ pci_read_config_dword(pdev, offset, &val);
-+ if (val != 0xffffffff)
-+ break;
-+ } while (retry--);
-+
-+
-+ return (val);
-+}
-+
-+void
-+osl_pci_write_config(void *loc, uint offset, uint size, uint val)
-+{
-+ struct pci_dev *pdev;
-+ uint retry=PCI_CFG_RETRY;
-+
-+ /* only 4byte access supported */
-+ ASSERT(size == 4);
-+
-+ pdev = (struct pci_dev*)loc;
-+
-+ do {
-+ pci_write_config_dword(pdev, offset, val);
-+ if (offset!=PCI_BAR0_WIN)
-+ break;
-+ if (osl_pci_read_config(loc,offset,size) == val)
-+ break;
-+ } while (retry--);
-+
-+}
-+
-+void
-+osl_pcmcia_read_attr(void *osh, uint offset, void *buf, int size)
-+{
-+ ASSERT(0);
-+}
-+
-+void
-+osl_pcmcia_write_attr(void *osh, uint offset, void *buf, int size)
-+{
-+ ASSERT(0);
-+}
-+
-+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);
-+}
-+
-+/*
-+ * 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(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);
-+}
-+
-+void*
-+osl_malloc(uint size)
-+{
-+ return (kmalloc(size, GFP_ATOMIC));
-+}
-+
-+void
-+osl_mfree(void *addr, uint size)
-+{
-+ kfree(addr);
-+}
-+
-+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
-+}
-+
-+void*
-+osl_dma_alloc_consistent(void *dev, uint size, ulong *pap)
-+{
-+ return (pci_alloc_consistent((struct pci_dev*)dev, size, (dma_addr_t*)pap));
-+}
-+
-+void
-+osl_dma_free_consistent(void *dev, void *va, uint size, ulong pa)
-+{
-+ pci_free_consistent((struct pci_dev*)dev, size, va, (dma_addr_t)pa);
-+}
-+
-+uint
-+osl_dma_map(void *dev, void *va, uint size, int direction)
-+{
-+ int dir;
-+
-+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
-+ return (pci_map_single(dev, va, size, dir));
-+}
-+
-+void
-+osl_dma_unmap(void *dev, uint pa, uint size, int direction)
-+{
-+ int dir;
-+
-+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
-+ pci_unmap_single(dev, (uint32)pa, size, dir);
-+}
-+
-+void
-+osl_delay(uint usec)
-+{
-+ udelay(usec);
-+}
-+
-+uchar*
-+osl_pktdata(void *drv, void *skb)
-+{
-+ return (((struct sk_buff*)skb)->data);
-+}
-+
-+uint
-+osl_pktlen(void *drv, void *skb)
-+{
-+ return (((struct sk_buff*)skb)->len);
-+}
-+
-+void*
-+osl_pktnext(void *drv, 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(void *drv, void *skb, uint len)
-+{
-+ __skb_trim((struct sk_buff*)skb, len);
-+}
-+
-+uchar*
-+osl_pktpush(void *drv, void *skb, int bytes)
-+{
-+ return (skb_push((struct sk_buff*)skb, bytes));
-+}
-+
-+uchar*
-+osl_pktpull(void *drv, void *skb, int bytes)
-+{
-+ return (skb_pull((struct sk_buff*)skb, bytes));
-+}
-+
-+void*
-+osl_pktdup(void *drv, 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;
-+}
-+
-+#endif
-diff -Nur linux-2.6.12.5/arch/mips/bcm947xx/broadcom/Makefile linux-2.6.12.5-brcm/arch/mips/bcm947xx/broadcom/Makefile
---- linux-2.6.12.5/arch/mips/bcm947xx/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.12.5-brcm/arch/mips/bcm947xx/broadcom/Makefile 2005-11-19 14:16:38.941631500 +0100
-@@ -0,0 +1,7 @@
-+#
-+# Makefile for the BCM47xx specific kernel interface routines
-+# under Linux.
-+#
-+
-+obj-y := sbutils.o linux_osl.o bcmsrom.o bcmutils.o sbmips.o sbpci.o hnddma.o
-+#obj-y := nvram.o nvram_linux.o
-diff -Nur linux-2.6.12.5/arch/mips/bcm947xx/broadcom/nvram.c linux-2.6.12.5-brcm/arch/mips/bcm947xx/broadcom/nvram.c
---- linux-2.6.12.5/arch/mips/bcm947xx/broadcom/nvram.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.12.5-brcm/arch/mips/bcm947xx/broadcom/nvram.c 2005-11-19 02:28:26.438059500 +0100
-@@ -0,0 +1,321 @@
-+/*
-+ * NVRAM variable manipulation (common)
-+ *
-+ * Copyright 2004, Broadcom Corporation
-+ * All Rights Reserved.
-+ *
-+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
-+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
-+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
-+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
-+ *
-+ * $Id$
-+ */
-+
-+#include <typedefs.h>
-+#include <osl.h>
-+#include <bcmendian.h>
-+#include <bcmnvram.h>
-+#include <bcmutils.h>
-+#include <sbsdram.h>
-+
-+extern struct nvram_tuple * BCMINIT(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value);
-+extern void BCMINIT(_nvram_free)(struct nvram_tuple *t);
-+extern int BCMINIT(_nvram_read)(void *buf);
-+
-+char * BCMINIT(_nvram_get)(const char *name);
-+int BCMINIT(_nvram_set)(const char *name, const char *value);
-+int BCMINIT(_nvram_unset)(const char *name);
-+int BCMINIT(_nvram_getall)(char *buf, int count);
-+int BCMINIT(_nvram_commit)(struct nvram_header *header);
-+int BCMINIT(_nvram_init)(void);
-+void BCMINIT(_nvram_exit)(void);
-+
-+static struct nvram_tuple * BCMINITDATA(nvram_hash)[257];
-+static struct nvram_tuple * nvram_dead;
-+
-+/* Free all tuples. Should be locked. */
-+static void
-+BCMINITFN(nvram_free)(void)
-+{
-+ uint i;
-+ struct nvram_tuple *t, *next;
-+
-+ /* Free hash table */
-+ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) {
-+ for (t = BCMINIT(nvram_hash)[i]; t; t = next) {
-+ next = t->next;
-+ BCMINIT(_nvram_free)(t);
-+ }
-+ BCMINIT(nvram_hash)[i] = NULL;
-+ }
-+
-+ /* Free dead table */
-+ for (t = nvram_dead; t; t = next) {
-+ next = t->next;
-+ BCMINIT(_nvram_free)(t);
-+ }
-+ nvram_dead = NULL;
-+
-+ /* Indicate to per-port code that all tuples have been freed */
-+ BCMINIT(_nvram_free)(NULL);
-+}
-+
-+/* String hash */
-+static INLINE uint
-+hash(const char *s)
-+{
-+ uint hash = 0;
-+
-+ while (*s)
-+ hash = 31 * hash + *s++;
-+
-+ return hash;
-+}
-+
-+/* (Re)initialize the hash table. Should be locked. */
-+static int
-+BCMINITFN(nvram_rehash)(struct nvram_header *header)
-+{
-+ char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq;
-+
-+ /* (Re)initialize hash table */
-+ BCMINIT(nvram_free)();
-+
-+ /* Parse and set "name=value\0 ... \0\0" */
-+ name = (char *) &header[1];
-+ end = (char *) header + NVRAM_SPACE - 2;
-+ end[0] = end[1] = '\0';
-+ for (; *name; name = value + strlen(value) + 1) {
-+ if (!(eq = strchr(name, '=')))
-+ break;
-+ *eq = '\0';
-+ value = eq + 1;
-+ BCMINIT(_nvram_set)(name, value);
-+ *eq = '=';
-+ }
-+
-+ /* Set special SDRAM parameters */
-+ if (!BCMINIT(_nvram_get)("sdram_init")) {
-+ sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16));
-+ BCMINIT(_nvram_set)("sdram_init", buf);
-+ }
-+ if (!BCMINIT(_nvram_get)("sdram_config")) {
-+ sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff));
-+ BCMINIT(_nvram_set)("sdram_config", buf);
-+ }
-+ if (!BCMINIT(_nvram_get)("sdram_refresh")) {
-+ sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff));
-+ BCMINIT(_nvram_set)("sdram_refresh", buf);
-+ }
-+ if (!BCMINIT(_nvram_get)("sdram_ncdl")) {
-+ sprintf(buf, "0x%08X", header->config_ncdl);
-+ BCMINIT(_nvram_set)("sdram_ncdl", buf);
-+ }
-+
-+ return 0;
-+}
-+
-+/* Get the value of an NVRAM variable. Should be locked. */
-+char *
-+BCMINITFN(_nvram_get)(const char *name)
-+{
-+ uint i;
-+ struct nvram_tuple *t;
-+ char *value;
-+
-+ if (!name)
-+ return NULL;
-+
-+ /* Hash the name */
-+ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash));
-+
-+ /* Find the associated tuple in the hash table */
-+ for (t = BCMINIT(nvram_hash)[i]; t && strcmp(t->name, name); t = t->next);
-+
-+ value = t ? t->value : NULL;
-+
-+ return value;
-+}
-+
-+/* Get the value of an NVRAM variable. Should be locked. */
-+int
-+BCMINITFN(_nvram_set)(const char *name, const char *value)
-+{
-+ uint i;
-+ struct nvram_tuple *t, *u, **prev;
-+
-+ /* Hash the name */
-+ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash));
-+
-+ /* Find the associated tuple in the hash table */
-+ for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev);
-+
-+ /* (Re)allocate tuple */
-+ if (!(u = BCMINIT(_nvram_realloc)(t, name, value)))
-+ return -12; /* -ENOMEM */
-+
-+ /* Value reallocated */
-+ if (t && t == u)
-+ return 0;
-+
-+ /* Move old tuple to the dead table */
-+ if (t) {
-+ *prev = t->next;
-+ t->next = nvram_dead;
-+ nvram_dead = t;
-+ }
-+
-+ /* Add new tuple to the hash table */
-+ u->next = BCMINIT(nvram_hash)[i];
-+ BCMINIT(nvram_hash)[i] = u;
-+
-+ return 0;
-+}
-+
-+/* Unset the value of an NVRAM variable. Should be locked. */
-+int
-+BCMINITFN(_nvram_unset)(const char *name)
-+{
-+ uint i;
-+ struct nvram_tuple *t, **prev;
-+
-+ if (!name)
-+ return 0;
-+
-+ /* Hash the name */
-+ i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash));
-+
-+ /* Find the associated tuple in the hash table */
-+ for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev);
-+
-+ /* Move it to the dead table */
-+ if (t) {
-+ *prev = t->next;
-+ t->next = nvram_dead;
-+ nvram_dead = t;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Get all NVRAM variables. Should be locked. */
-+int
-+BCMINITFN(_nvram_getall)(char *buf, int count)
-+{
-+ uint i;
-+ struct nvram_tuple *t;
-+ int len = 0;
-+
-+ bzero(buf, count);
-+
-+ /* Write name=value\0 ... \0\0 */
-+ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) {
-+ for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) {
-+ if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1))
-+ len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1;
-+ else
-+ break;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/* Regenerate NVRAM. Should be locked. */
-+int
-+BCMINITFN(_nvram_commit)(struct nvram_header *header)
-+{
-+ char *init, *config, *refresh, *ncdl;
-+ char *ptr, *end;
-+ int i;
-+ struct nvram_tuple *t;
-+ struct nvram_header tmp;
-+ uint8 crc;
-+
-+ /* Regenerate header */
-+ header->magic = NVRAM_MAGIC;
-+ header->crc_ver_init = (NVRAM_VERSION << 8);
-+ if (!(init = BCMINIT(_nvram_get)("sdram_init")) ||
-+ !(config = BCMINIT(_nvram_get)("sdram_config")) ||
-+ !(refresh = BCMINIT(_nvram_get)("sdram_refresh")) ||
-+ !(ncdl = BCMINIT(_nvram_get)("sdram_ncdl"))) {
-+ header->crc_ver_init |= SDRAM_INIT << 16;
-+ header->config_refresh = SDRAM_CONFIG;
-+ header->config_refresh |= SDRAM_REFRESH << 16;
-+ header->config_ncdl = 0;
-+ } else {
-+ header->crc_ver_init |= (bcm_strtoul(init, NULL, 0) & 0xffff) << 16;
-+ header->config_refresh = bcm_strtoul(config, NULL, 0) & 0xffff;
-+ header->config_refresh |= (bcm_strtoul(refresh, NULL, 0) & 0xffff) << 16;
-+ header->config_ncdl = bcm_strtoul(ncdl, NULL, 0);
-+ }
-+
-+ /* Clear data area */
-+ ptr = (char *) header + sizeof(struct nvram_header);
-+ bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header));
-+
-+ /* Leave space for a double NUL at the end */
-+ end = (char *) header + NVRAM_SPACE - 2;
-+
-+ /* Write out all tuples */
-+ for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) {
-+ for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) {
-+ if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end)
-+ break;
-+ ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1;
-+ }
-+ }
-+
-+ /* End with a double NUL */
-+ ptr += 2;
-+
-+ /* Set new length */
-+ header->len = ROUNDUP(ptr - (char *) header, 4);
-+
-+ /* Little-endian CRC8 over the last 11 bytes of the header */
-+ tmp.crc_ver_init = htol32(header->crc_ver_init);
-+ tmp.config_refresh = htol32(header->config_refresh);
-+ tmp.config_ncdl = htol32(header->config_ncdl);
-+ crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, CRC8_INIT_VALUE);
-+
-+ /* Continue CRC8 over data bytes */
-+ crc = hndcrc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc);
-+
-+ /* Set new CRC8 */
-+ header->crc_ver_init |= crc;
-+
-+ /* Reinitialize hash table */
-+ return BCMINIT(nvram_rehash)(header);
-+}
-+
-+/* Initialize hash table. Should be locked. */
-+int
-+BCMINITFN(_nvram_init)(void)
-+{
-+ struct nvram_header *header;
-+ int ret;
-+ void *osh;
-+
-+ /* get kernel osl handler */
-+ osh = osl_attach(NULL);
-+
-+ if (!(header = (struct nvram_header *) MALLOC(osh, NVRAM_SPACE))) {
-+ printf("nvram_init: out of memory, malloced %d bytes\n", MALLOCED(osh));
-+ return -12; /* -ENOMEM */
-+ }
-+
-+ if ((ret = BCMINIT(_nvram_read)(header)) == 0 &&
-+ header->magic == NVRAM_MAGIC)
-+ BCMINIT(nvram_rehash)(header);
-+
-+ MFREE(osh, header, NVRAM_SPACE);
-+ return ret;
-+}
-+
-+/* Free hash table. Should be locked. */
-+void
-+BCMINITFN(_nvram_exit)(void)
-+{
-+ BCMINIT(nvram_free)();
-+}
-diff -Nur linux-2.6.12.5/arch/mips/bcm947xx/broadcom/nvram_linux.c linux-2.6.12.5-brcm/arch/mips/bcm947xx/broadcom/nvram_linux.c
---- linux-2.6.12.5/arch/mips/bcm947xx/broadcom/nvram_linux.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.12.5-brcm/arch/mips/bcm947xx/broadcom/nvram_linux.c 2005-11-19 02:28:26.438059500 +0100
-@@ -0,0 +1,633 @@
-+/*
-+ * NVRAM variable manipulation (Linux kernel half)
-+ *
-+ * 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$
-+ */