Exemple #1
0
/******************************************************************************
*
* ae531x_MACAddressSet - Set the ethernet address
*
* Sets the ethernet address from the given address field
*
* RETURNS: void
*/
static void
ae531x_MACAddressSet(ae531x_MAC_t *MACInfo)
{
    unsigned int    data;
    UINT8 *macAddr;

    ARRIVE();
        
    macAddr = macAddrGet(MACInfo);

    /* set our MAC address  */
    data = (macAddr[5]<<8) | macAddr[4];
    ae531x_WriteMacReg(MACInfo, MacAddrHigh, data );

    data = (macAddr[3]<<24) | (macAddr[2]<<16) | (macAddr[1]<<8) | macAddr[0];
    ae531x_WriteMacReg(MACInfo, MacAddrLow, data );

    AE531X_PRINT(AE531X_DEBUG_RESET,
              ("eth%d Verify MAC address %8.8X %8.8X \n",
               MACInfo->unit,
               ae531x_ReadMacReg(MACInfo, MacAddrLow),
               ae531x_ReadMacReg(MACInfo, MacAddrHigh)));

    AE531X_PRINT(AE531X_DEBUG_RESET,
              ("  sb = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
               0xff&macAddr[0],
               0xff&macAddr[1],
               0xff&macAddr[2],
               0xff&macAddr[3],
               0xff&macAddr[4],
               0xff&macAddr[5]));
    LEAVE();
}
Exemple #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;
}
Exemple #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++;
    }
}
Exemple #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;
}
Exemple #5
0
/******************************************************************************
* ae531x_unitLinkGained -- Called from PHY layer to notify the MAC layer
* that there are 1 or more live links associated with a MAC.
*/
void
ae531x_unitLinkGained(int ethUnit)
{
    AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
             ("enet%d link up\n", ethUnit));
}
Exemple #6
0
/******************************************************************************
* ae531x_unitLinkLost -- Called from PHY layer to notify the MAC layer
* that there are no longer any live links associated with a MAC.
*/
void
ae531x_unitLinkLost(int ethUnit)
{
    AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,
             ("enet%d link down\n", ethUnit));
}
Exemple #7
0
/******************************************************************************
*
* ae531x_DmaReset - Reset DMA and TLI controllers
*
* RETURNS: N/A
*/
void
ae531x_DmaReset(ae531x_MAC_t *MACInfo)
{
    int           i;
    UINT32        descAddr;
    unsigned long oldIntrState;

    ARRIVE();

    /* Disable device interrupts prior to any errors during stop */
    intDisable(oldIntrState);

    /* Disable MAC rx and tx */
    ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));

    /* Reset dma controller */
    ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaResetOn);

    /* Delay 2 usec */
    sysUDelay(2);

    /* Flush the rx queue */
    descAddr = (UINT32)MACInfo->rxQueue.firstDescAddr;
    MACInfo->rxQueue.curDescAddr = MACInfo->rxQueue.firstDescAddr;
    for (i=0;
         i<(MACInfo->rxDescCount);
         i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
            AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);
    }

    /* Flush the tx queue */
    descAddr = (UINT32)MACInfo->txQueue.firstDescAddr;
    MACInfo->txQueue.curDescAddr = MACInfo->txQueue.firstDescAddr;
    MACInfo->txQueue.reapDescAddr = MACInfo->txQueue.lastDescAddr;
    for (i=0;
         i<(MACInfo->txDescCount);
         i++, descAddr += AE531X_QUEUE_ELE_SIZE) {
            AE531X_DESC_STATUS_SET (descAddr, 0);
    }

    /* Set init register values  */
    ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaBusModeInit);

    /* Install the first Tx and Rx queues on the device */
    ae531x_WriteDmaReg(MACInfo, DmaRxBaseAddr,
                      (UINT32)MACInfo->rxQueue.firstDescAddr);
    ae531x_WriteDmaReg(MACInfo, DmaTxBaseAddr,
                      (UINT32)MACInfo->txQueue.firstDescAddr);

    ae531x_WriteDmaReg(MACInfo, DmaControl, DmaStoreAndForward);

    ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);

    AE531X_PRINT(AE531X_DEBUG_RESET,
              ("eth%d: DMA RESET!\n", MACInfo->unit));

    /* Turn on device interrupts -- enable most errors */
    ae531x_DmaIntClear(MACInfo);    /* clear interrupt requests  */
    ae531x_DmaIntEnable(MACInfo);   /* enable interrupts */

    ae531x_EndResetMode(MACInfo);

    intEnable(oldIntrState);

    LEAVE();
}
Exemple #8
0
/******************************************************************************
* ae531x_AllocateQueues - Allocate receive and transmit queues
*/
int
ae531x_AllocateQueues(ae531x_MAC_t *MACInfo)
{
    size_t QMemSize;
    char *pTxBuf = NULL;
    char *pRxBuf = NULL;

    ARRIVE();

    QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->txDescCount;
    pTxBuf = MACInfo->pTxDescs;
    if (pTxBuf == NULL) {
        AE531X_PRINT(AE531X_DEBUG_RESET,
                  ("eth%d Failed to allocate TX queue\n", MACInfo->unit));
        goto AllocQFail;
    }

    if (ae531x_TxQueueCreate(MACInfo, &MACInfo->txQueue, pTxBuf,
                          MACInfo->txDescCount) < 0)
    {
        AE531X_PRINT(AE531X_DEBUG_RESET,
                ("eth%d Failed to create TX queue\n", MACInfo->unit));
        goto AllocQFail;
    }

    QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->rxDescCount;
    pRxBuf = MACInfo->pRxDescs;
    if (pRxBuf == NULL) {
        AE531X_PRINT(AE531X_DEBUG_RESET,
                  ("eth%d Failed to allocate RX queue\n", MACInfo->unit));
        goto AllocQFail;
    }

    if (ae531x_RxQueueCreate(MACInfo, &MACInfo->rxQueue, pRxBuf,
                          MACInfo->rxDescCount) < 0)
    {
        AE531X_PRINT(AE531X_DEBUG_RESET,
                ("eth%d Failed to create RX queue\n", MACInfo->unit));
        goto AllocQFail;
    }

    AE531X_PRINT(AE531X_DEBUG_RESET,
            ("eth%d Memory setup complete.\n", MACInfo->unit));

    LEAVE();
    return 0;

AllocQFail:
    MACInfo->txDescCount = 0; /* sanity */
    MACInfo->rxDescCount = 0; /* sanity */

    if (pTxBuf) {
        FREE(pTxBuf);
    }
    if (pRxBuf) {
        FREE(pRxBuf);
    }
    
    LEAVE();
    return -1;
}
Exemple #9
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;
}
Exemple #10
0
static int ae531x_start(struct eth_device *dev, bd_t *bis)
{
    ae531x_priv_data_t *ae531x_priv;
    ae531x_MAC_t *MACInfo;
    unsigned char enet_addr[ETHER_ADDR_LEN];
    int i;

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

    memcpy(ae531x_priv->enet_addr, bis->bi_enetaddr, ETHER_ADDR_LEN);

    /* Attach interrupt handler */
    /* TBDXXX */

    /* Bring MAC and PHY out of reset */

  // ae531x_reset(MACInfo);

    /* Initialize PHY */
   // phySetup(MACInfo->unit, MACInfo->phyBase);

    /* Start thread to poll for phy link status changes */
    /* TBDXXX -- do in ae531x_poll? */

    /* Setup Transmit Descriptors */
    MACInfo->txDescCount = AE531X_TX_DESC_COUNT_DEFAULT;
    MACInfo->pTxDescs = ae531xTxDescs;

    /* Setup Transmit buffer free list */
    for (i=0; i<AE531X_TX_DESC_COUNT_DEFAULT; i++) {
        ae531xTxDataBuf[i].next = ae531xTxFreeList;
        ae531xTxFreeList = &ae531xTxDataBuf[i];
    }
    ae531xTxAvail = AE531X_TX_DESC_COUNT_DEFAULT;

    /* Setup Receive Descriptors */
    MACInfo->rxDescCount = AE531X_RX_DESC_COUNT_DEFAULT;
    MACInfo->pRxDescs = ae531xRxDescs;

    /* Setup Receive buffer free list */
    for (i=0; i<AE531X_RX_DATA_BUF_COUNT; i++) {
        ae531xRxDataBuf[i].next = ae531xRxFreeList;
        ae531xRxFreeList = &ae531xRxDataBuf[i];
    }

    /* Allocate RX/TX Queues */
    if (ae531x_AllocateQueues(MACInfo) < 0) {
        AE531X_PRINT(AE531X_DEBUG_RESET, ("Queue allocation failed"));
        goto skip_start;
    }

    /* Initialize MAC */
    ae531x_MACReset(MACInfo);

    /* Initialize DMA and descriptors */
    ae531x_DmaReset(MACInfo);

    /* Enable Receive/Transmit */
    ae531x_EnableComm(MACInfo);

    MACInfo->port_is_up = TRUE;

skip_start:
    
    return 0;
}