/****************************************************************************** * ae531x_RxQueueCreate - create a circular queue of Rx descriptors */ int ae531x_RxQueueCreate(ae531x_MAC_t *MACInfo, AE531X_QUEUE *q, char *pMem, int count) { int i; VIRT_ADDR descAddr; ARRIVE(); ae531x_QueueInit(q, pMem, count); q->reapDescAddr = NULL; /* Initialize Rx buffer descriptors */ for (i=0, descAddr=q->firstDescAddr; i<count; i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) { void *swptr; char *rxBuffer; int rxBufferSize; swptr = ae531x_rxbuf_alloc(MACInfo, &rxBuffer, &rxBufferSize); if (swptr == NULL) { AE531X_PRINT(AE531X_DEBUG_RESET, ("eth%d RX queue: ae531x_rxbuf_alloc failed\n", MACInfo->unit)); ae531x_QueueDestroy(q); return -1; } AE531X_DESC_SWPTR_SET(descAddr, swptr); AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma); AE531X_DESC_CTRLEN_SET(descAddr, rxBufferSize); AE531X_DESC_BUFPTR_SET(descAddr, virt_to_bus(rxBuffer)); AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0); } /* for each desc */ /* Make the queue circular */ AE531X_DESC_CTRLEN_SET(q->lastDescAddr, DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr)); AE531X_PRINT(AE531X_DEBUG_RESET, ("eth%d Rxbuf begin = %x, end = %x\n", MACInfo->unit, (UINT32)q->firstDescAddr, (UINT32)q->lastDescAddr)); LEAVE(); return 0; }
/****************************************************************************** * ae531x_TxQueueCreate - create a circular queue of descriptors for Transmit */ static int ae531x_TxQueueCreate(ae531x_MAC_t *MACInfo, AE531X_QUEUE *q, char *pMem, int count) { int i; VIRT_ADDR descAddr; ARRIVE(); ae531x_QueueInit(q, pMem, count); q->reapDescAddr = q->lastDescAddr; /* Initialize Tx buffer descriptors. */ for (i=0, descAddr=q->firstDescAddr; i<count; i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) { /* Update the size, BUFPTR, and SWPTR fields */ AE531X_DESC_STATUS_SET(descAddr, 0); AE531X_DESC_CTRLEN_SET(descAddr, 0); AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0); AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0); AE531X_DESC_SWPTR_SET(descAddr, (void *)0); } /* for each desc */ /* Make the queue circular */ AE531X_DESC_CTRLEN_SET(q->lastDescAddr, DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr)); AE531X_PRINT(AE531X_DEBUG_RESET, ("eth%d Txbuf begin = %x, end = %x\n", MACInfo->unit, (UINT32)q->firstDescAddr, (UINT32)q->lastDescAddr)); LEAVE(); return 0; }
static int ae531x_send(struct eth_device *dev, volatile void *packet, int length) { ae531x_priv_data_t *ae531x_priv; ae531x_MAC_t *MACInfo; UINT32 ctrlen; VIRT_ADDR txDesc; ae531xTxBuf_t *TxBuf; unsigned char *TxBufData, *TxBufDataStart; int i; volatile UINT32 regval; ae531x_priv = (ae531x_priv_data_t *)dev->priv; MACInfo = (ae531x_MAC_t *)&ae531x_priv->MACInfo; /* Check if this port is up, else toss packet */ if (!MACInfo->port_is_up) { goto dropFrame; } if (ae531x_IsInResetMode(MACInfo)) { goto dropFrame; } ae531x_TxReap(MACInfo); txDesc = MACInfo->txQueue.curDescAddr; if (txDesc == MACInfo->txQueue.reapDescAddr) { goto dropFrame; } AE531X_CONSUME_DESC((&MACInfo->txQueue)); ae531xTxAvail--; /* Allocate a transmit data buffer */ ae531x_txbuf_alloc(MACInfo, &TxBuf); AE531X_DESC_SWPTR_SET(txDesc, TxBuf); TxBufDataStart = TxBufData = TxBuf->data; if (length< 60) { length= 60; } memcpy(TxBufData, packet, length); TxBufData += length; /* Update the descriptor */ AE531X_DESC_BUFPTR_SET(txDesc, virt_to_bus(TxBufDataStart)); ctrlen = AE531X_DESC_CTRLEN_GET(txDesc); ctrlen = (ctrlen & (DescEndOfRing)) | DescTxFirst | DescTxLast | DescTxIntEnable; ctrlen |= ((length << DescSize1Shift) & DescSize1Mask); AE531X_DESC_CTRLEN_SET(txDesc, ctrlen); AE531X_DESC_STATUS_SET(txDesc, DescOwnByDma); /* Alert DMA engine to resume Tx */ ae531x_WriteDmaReg(MACInfo, DmaTxPollDemand, 0); sysWbFlush(); dropFrame: return length; }