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