示例#1
0
/******************************************************************************
* ae531x_QueueDestroy -- Free all buffers and descriptors associated 
* with a queue.
*/
static void
ae531x_QueueDestroy(AE531X_QUEUE *q)
{
    int i;
    int count;
    VIRT_ADDR    descAddr;

    ARRIVE();

    count = q->count;

    for (i=0, descAddr=q->firstDescAddr;
         i<count;
         i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) {

        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);

#if 0 /* TBDXXX */
        ae531x_rxbuf_free(descAddr); /* Free OS-specific software pointer */
#endif
        AE531X_DESC_SWPTR_SET(descAddr, NULL);
    }

    LEAVE();
}
示例#2
0
/******************************************************************************
* 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;
}
示例#3
0
static void
ae531x_TxReap(ae531x_MAC_t *MACInfo)
{
    AE531X_QUEUE      *txq;
    VIRT_ADDR         txDesc;
    UINT32            cmdsts;
    int               reaped;
    ae531xTxBuf_t     *TxBuf;
    unsigned long     key;

    txq = &MACInfo->txQueue;
    reaped = 0;

    // XXXTODO: bug - won't be able to reap once run out of descriptors
    while (1) {
        txDesc = AE531X_QUEUE_ELE_NEXT_GET(txq, txq->reapDescAddr);
        if (txDesc == txq->curDescAddr) {
            break;
        }

        cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(txDesc));
        if (cmdsts & DescOwnByDma) {
            break;
        }


        TxBuf = (ae531xTxBuf_t *)AE531X_DESC_SWPTR_GET(txDesc);
        AE531X_PRINT(AE531X_DEBUG_TX_REAP, ("TXREAP: cur=%p  reap=%p  txDesc=%p TxBuf=%p\n",
                     txq->curDescAddr, txq->reapDescAddr, txDesc, TxBuf));
        key = TxBuf->key;

        /* Release transmit buffer associated with completed transmit */
        ae531x_txbuf_free(TxBuf);
        AE531X_DESC_SWPTR_SET(txDesc, (void *)0x1bad0dad);
        ae531xTxAvail++;

        txq->reapDescAddr = txDesc;
        reaped++;
    }

    if (reaped > 0) {
        AE531X_PRINT(AE531X_DEBUG_TX_REAP,
                 ("reaped=%d    TxAvail=%d\n", reaped, ae531xTxAvail));
    } else {
        aeUselessReap++;
    }
}
示例#4
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;
}
示例#5
0
static int ae531x_poll(struct eth_device *dev)
{
    ae531xRxBuf_t *rxBuf, *newRxBuf;
    char *rxBufData;
    int unused_length;
    VIRT_ADDR   rxDesc;
    int length;
    ae531x_MAC_t *MACInfo;
    unsigned int cmdsts;
    ae531x_priv_data_t *ae531x_priv;

    ae531x_priv = (ae531x_priv_data_t *)dev->priv;
    MACInfo = (ae531x_MAC_t *)&ae531x_priv->MACInfo;

    do {
        for(;;) {
            rxDesc = MACInfo->rxQueue.curDescAddr;
            cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(rxDesc));

            if (cmdsts & DescOwnByDma) {
                /* There's nothing left to process in the RX ring */
                goto rx_all_done;
            }

            AE531X_PRINT(AE531X_DEBUG_RX,
                  ("consume rxDesc %p with cmdsts=0x%x\n",
                   (void *)rxDesc, cmdsts));
   
            AE531X_CONSUME_DESC((&MACInfo->rxQueue));
    
            A_DATA_CACHE_INVAL(rxDesc, AE531X_DESC_SIZE);

            /*  Process a packet */
            length = AE531X_DESC_STATUS_RX_SIZE(cmdsts) - ETH_CRC_LEN;
            if ( (cmdsts & (DescRxFirst |DescRxLast | DescRxErrors)) ==
                           (DescRxFirst | DescRxLast) ) {
                /* Descriptor status indicates "NO errors" */

                rxBuf = AE531X_DESC_SWPTR_GET(rxDesc);
                /*
                 * Allocate a replacement buffer
                 * We want to get another buffer ready for Rx ASAP.
                 */
                newRxBuf = ae531x_rxbuf_alloc(MACInfo, &rxBufData, &unused_length);
                if(newRxBuf == NULL ) {
                    /*
                     * Give this descriptor back to the DMA engine,
                     * and drop the received packet.
                     */
                    AE531X_PRINT(AE531X_DEBUG_ERROR,
                              ("Can't allocate new rx buf\n"));
                } else {
		   //diag_printf("rxBufData=%p\n",rxBufData);
                    AE531X_DESC_BUFPTR_SET(rxDesc, virt_to_bus(rxBufData));
                    AE531X_DESC_SWPTR_SET(rxDesc, newRxBuf);
                }

                AE531X_DESC_STATUS_SET(rxDesc, DescOwnByDma);
                rxDesc = NULL; /* sanity -- cannot use rxDesc now */
                sysWbFlush();
    
                if (newRxBuf == NULL) {
                    goto no_rx_bufs;
                } else {
                    /* Sync data cache w.r.t. DMA */
                    A_DATA_CACHE_INVAL(rxBuf->data, length);
        
                    /* Send the data up the stack */
                    AE531X_PRINT(AE531X_DEBUG_RX,
                              ("Send data up stack: rxBuf=%p data=%p length=%d\n",
                               (void *)rxBuf, (void *)rxBuf->data, length));

                    {
                        unsigned long oldIntrState;

                        rxBuf->next = NULL;
                        intDisable(oldIntrState);
                        if (ae531xRxRecvdListHead) {
                            ae531xRxRecvdListTail->next = rxBuf;
                            ae531xRxRecvdListTail = rxBuf;
                        } else {
                            ae531xRxRecvdListHead = rxBuf;
                            ae531xRxRecvdListTail = rxBuf;
                        }
                        intEnable(oldIntrState);
                    }
                     NetReceive(rxBuf->data, length);
			    /* Free driver Rx buffer */
    			ae531x_rxbuf_free(rxBuf);
                }
            } else {
                AE531X_PRINT(AE531X_DEBUG_ERROR,
                          ("Bad receive.  rxDesc=%p  cmdsts=0x%8.8x\n",
                           (void *)rxDesc, cmdsts));
            }
        }
    } while (ae531x_ReadDmaReg(MACInfo, DmaStatus) & DmaIntRxCompleted);

rx_all_done:
    ae531x_SetDmaReg(MACInfo, DmaIntrEnb,
                     DmaIeRxCompleted | DmaIeRxNoBuffer);
    ae531x_WriteDmaReg(MACInfo, DmaRxPollDemand, 0);

no_rx_bufs:

    return;
}
示例#6
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;
}