EMAC_Send
Default mainpageat91libperipheralsemacEMAC_Send
Description Source Call Graph
Start Line: 607
unsigned char EMAC_Send(void *pBuffer, unsigned int size, EMAC_TxCallback fEMAC_TxCallback)
{
    volatile EmacTxTDescriptor *pTxTd;
    volatile EMAC_TxCallback   *pTxCb;

    //TRACE_DEBUG("EMAC_Send\n\r");

    // Check parameter
    if (size > EMAC_TX_UNITSIZE) {

        TRACE_ERROR("EMAC driver does not split send packets.");
        TRACE_ERROR(" It can send %d bytes max in one packet (%d bytes requested)\n\r",
            EMAC_TX_UNITSIZE, size);
        return EMAC_TX_INVALID_PACKET;
    }

    // If no free TxTd, buffer can't be sent, schedule the wakeup callback
    if( CIRC_SPACE(txTd.head, txTd.tail, TX_BUFFERS) == 0) {
        return EMAC_TX_BUFFER_BUSY;

    }

    // Pointers to the current TxTd
    pTxTd = txTd.td + txTd.head;
    pTxCb = txTd.txCb + txTd.head;

    // Sanity check
    ASSERT((pTxTd->status & EMAC_TX_USED_BIT) != 0, 
        "-F- Buffer is still under EMAC control\n\r");

    // Setup/Copy data to transmition buffer
    if (pBuffer && size) {
        // Driver manage the ring buffer
        memcpy((void *)pTxTd->addr, pBuffer, size);
    }
    
    // Tx Callback
    *pTxCb = fEMAC_TxCallback;

    // Update TD status
    // The buffer size defined is length of ethernet frame
    // so it's always the last buffer of the frame.
    if (txTd.head == TX_BUFFERS-1) {
        pTxTd->status = 
            (size & EMAC_LENGTH_FRAME) | EMAC_TX_LAST_BUFFER_BIT | EMAC_TX_WRAP_BIT;
    }
    else {
        pTxTd->status = (size & EMAC_LENGTH_FRAME) | EMAC_TX_LAST_BUFFER_BIT;
    }
    
    CIRC_INC(txTd.head, TX_BUFFERS)

    // Tx packets count
    EmacStatistics.tx_packets++;

    // Now start to transmit if it is not already done
    AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART;

    return EMAC_TX_OK;
}