aboutsummaryrefslogtreecommitdiffstats
path: root/package/linux/kernel-source/drivers/net/hnd/hnddma.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/linux/kernel-source/drivers/net/hnd/hnddma.c')
-rw-r--r--package/linux/kernel-source/drivers/net/hnd/hnddma.c841
1 files changed, 0 insertions, 841 deletions
diff --git a/package/linux/kernel-source/drivers/net/hnd/hnddma.c b/package/linux/kernel-source/drivers/net/hnd/hnddma.c
deleted file mode 100644
index ab87e4e2df..0000000000
--- a/package/linux/kernel-source/drivers/net/hnd/hnddma.c
+++ /dev/null
@@ -1,841 +0,0 @@
-/*
- * Generic Broadcom Home Networking Division (HND) DMA module.
- * This supports the following chips: BCM42xx, 44xx, 47xx .
- *
- * 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 <bcmutils.h>
-
-struct dma_info; /* forward declaration */
-#define di_t struct dma_info
-#include <hnddma.h>
-
-/* debug/trace */
-#define DMA_ERROR(args)
-#define DMA_TRACE(args)
-
-/* default dma message level(if input msg_level pointer is null in dma_attach()) */
-static uint dma_msg_level = 0;
-
-#define MAXNAMEL 8
-#define MAXDD (DMAMAXRINGSZ / sizeof (dmadd_t))
-
-/* 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 *drv; /* driver handle */
- void *dev; /* device handle */
- dmaregs_t *regs; /* dma engine registers */
-
- dmadd_t *txd; /* pointer to chip-specific tx descriptor ring */
- uint txin; /* index of next descriptor to reclaim */
- uint txout; /* index of next descriptor to post */
- uint txavail; /* # free tx descriptors */
- void *txp[MAXDD]; /* parallel array of pointers to packets */
- ulong txdpa; /* physical address of descriptor ring */
- uint txdalign; /* #bytes added to alloc'd mem to align txd */
-
- dmadd_t *rxd; /* pointer to chip-specific rx descriptor ring */
- uint rxin; /* index of next descriptor to reclaim */
- uint rxout; /* index of next descriptor to post */
- void *rxp[MAXDD]; /* parallel array of pointers to packets */
- ulong rxdpa; /* physical address of descriptor ring */
- uint rxdalign; /* #bytes added to alloc'd mem to align rxd */
-
- /* tunables */
- uint ntxd; /* # tx descriptors */
- uint nrxd; /* # rx descriptors */
- uint rxbufsize; /* rx buffer size in bytes */
- uint nrxpost; /* # rx buffers to keep posted */
- uint rxoffset; /* rxcontrol offset */
- uint ddoffset; /* add to get dma address of descriptor ring */
- uint dataoffset; /* add to get dma address of data buffer */
-} dma_info_t;
-
-/* descriptor bumping macros */
-#define TXD(x) ((x) & (di->ntxd - 1))
-#define RXD(x) ((x) & (di->nrxd - 1))
-#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)
-
-/* macros to convert between byte offsets and indexes */
-#define B2I(bytes) ((bytes) / sizeof (dmadd_t))
-#define I2B(index) ((index) * sizeof (dmadd_t))
-
-void*
-dma_attach(void *drv, void *dev, char *name, dmaregs_t *regs, uint ntxd, uint nrxd,
- uint rxbufsize, uint nrxpost, uint rxoffset, uint ddoffset, uint dataoffset, uint *msg_level)
-{
- dma_info_t *di;
- void *va;
-
- ASSERT(ntxd <= MAXDD);
- ASSERT(nrxd <= MAXDD);
-
- /* allocate private info structure */
- if ((di = MALLOC(sizeof (dma_info_t))) == NULL)
- return (NULL);
- bzero((char*)di, sizeof (dma_info_t));
-
- /* set message level */
- di->msg_level = msg_level ? msg_level : &dma_msg_level;
-
- DMA_TRACE(("%s: dma_attach: drv 0x%x dev 0x%x regs 0x%x ntxd %d nrxd %d rxbufsize %d nrxpost %d rxoffset %d ddoffset 0x%x dataoffset 0x%x\n", name, (uint)drv, (uint)dev, (uint)regs, ntxd, nrxd, rxbufsize, nrxpost, rxoffset, ddoffset, dataoffset));
-
- /* make a private copy of our callers name */
- strncpy(di->name, name, MAXNAMEL);
- di->name[MAXNAMEL-1] = '\0';
-
- di->drv = drv;
- di->dev = dev;
- di->regs = regs;
-
- /* allocate transmit descriptor ring */
- if (ntxd) {
- if ((va = DMA_ALLOC_CONSISTENT(dev, (DMAMAXRINGSZ + DMARINGALIGN), &di->txdpa)) == NULL)
- goto fail;
- di->txd = (dmadd_t*) ROUNDUP(va, DMARINGALIGN);
- di->txdalign = ((uint)di->txd - (uint)va);
- di->txdpa = di->txdpa + di->txdalign;
- ASSERT(ISALIGNED(di->txd, DMARINGALIGN));
- }
-
- /* allocate receive descriptor ring */
- if (nrxd) {
- if ((va = DMA_ALLOC_CONSISTENT(dev, (DMAMAXRINGSZ + DMARINGALIGN), &di->rxdpa)) == NULL)
- goto fail;
- di->rxd = (dmadd_t*) ROUNDUP(va, DMARINGALIGN);
- di->rxdalign = ((uint)di->rxd - (uint)va);
- di->rxdpa = di->rxdpa + di->rxdalign;
- ASSERT(ISALIGNED(di->rxd, DMARINGALIGN));
- }
-
- /* save tunables */
- di->ntxd = ntxd;
- di->nrxd = nrxd;
- di->rxbufsize = rxbufsize;
- di->nrxpost = nrxpost;
- di->rxoffset = rxoffset;
- di->ddoffset = ddoffset;
- di->dataoffset = dataoffset;
-
- return ((void*)di);
-
-fail:
- dma_detach((void*)di);
- return (NULL);
-}
-
-/* may be called with core in reset */
-void
-dma_detach(dma_info_t *di)
-{
- if (di == NULL)
- return;
-
- DMA_TRACE(("%s: dma_detach\n", di->name));
-
- /* shouldn't be here if descriptors are unreclaimed */
- ASSERT(di->txin == di->txout);
- ASSERT(di->rxin == di->rxout);
-
- /* free dma descriptor rings */
- if (di->txd)
- DMA_FREE_CONSISTENT(di->dev, (void *)((uint)di->txd - di->txdalign), (DMAMAXRINGSZ + DMARINGALIGN), di->txdpa);
- if (di->rxd)
- DMA_FREE_CONSISTENT(di->dev, (void *)((uint)di->rxd - di->rxdalign), (DMAMAXRINGSZ + DMARINGALIGN), di->rxdpa);
-
- /* free our private info structure */
- MFREE((void*)di, sizeof (dma_info_t));
-}
-
-
-void
-dma_txreset(dma_info_t *di)
-{
- uint32 status;
-
- DMA_TRACE(("%s: dma_txreset\n", di->name));
-
- /* suspend tx DMA first */
- W_REG(&di->regs->xmtcontrol, XC_SE);
- SPINWAIT((status = (R_REG(&di->regs->xmtstatus) & XS_XS_MASK)) != XS_XS_DISABLED &&
- status != XS_XS_IDLE &&
- status != XS_XS_STOPPED,
- 10000);
-
- W_REG(&di->regs->xmtcontrol, 0);
- SPINWAIT((status = (R_REG(&di->regs->xmtstatus) & XS_XS_MASK)) != XS_XS_DISABLED,
- 10000);
-
- if (status != XS_XS_DISABLED) {
- DMA_ERROR(("%s: dma_txreset: dma cannot be stopped\n", di->name));
- }
-
- /* wait for the last transaction to complete */
- OSL_DELAY(300);
-}
-
-void
-dma_rxreset(dma_info_t *di)
-{
- uint32 status;
-
- DMA_TRACE(("%s: dma_rxreset\n", di->name));
-
- W_REG(&di->regs->rcvcontrol, 0);
- SPINWAIT((status = (R_REG(&di->regs->rcvstatus) & 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
-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)
-{
- if (!(R_REG(&di->regs->xmtcontrol) & XC_SE))
- return 0;
-
- if ((R_REG(&di->regs->xmtstatus) & XS_XS_MASK) != XS_XS_IDLE)
- return 0;
-
- OSL_DELAY(2);
- return ((R_REG(&di->regs->xmtstatus) & XS_XS_MASK) == XS_XS_IDLE);
-}
-
-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);
-}
-
-/* like getnexttxp but no reclaim */
-void*
-dma_peeknexttxp(dma_info_t *di)
-{
- uint end, i;
-
- end = B2I(R_REG(&di->regs->xmtstatus) & XS_CD_MASK);
-
- for (i = di->txin; i != end; i = NEXTTXD(i))
- if (di->txp[i])
- return (di->txp[i]);
-
- 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));
-}
-
-/*
- * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin).
- */
-void
-dma_txrotate(di_t *di)
-{
- uint ad;
- uint nactive;
- uint rot;
- uint old, new;
- uint32 w;
- uint first, last;
-
- ASSERT(dma_txsuspended(di));
-
- nactive = dma_txactive(di);
- ad = B2I((R_REG(&di->regs->xmtstatus) & XS_AD_MASK) >> XS_AD_SHIFT);
- rot = TXD(ad - di->txin);
-
- ASSERT(rot < di->ntxd);
-
- /* full-ring case is a lot harder - don't worry about this */
- if (rot >= (di->ntxd - nactive)) {
- DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name));
- return;
- }
-
- first = di->txin;
- last = PREVTXD(di->txout);
-
- /* 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->txd[old].ctrl) & ~CTRL_EOT;
- if (new == (di->ntxd - 1))
- w |= CTRL_EOT;
- W_SM(&di->txd[new].ctrl, w);
- W_SM(&di->txd[new].addr, R_SM(&di->txd[old].addr));
-
- /* zap the old tx dma descriptor address field */
- W_SM(&di->txd[old].addr, 0xdeadbeef);
-
- /* 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->regs->xmtptr, I2B(di->txout));
-}