Description
Source
Call Graph
Start Line: 679
unsigned char EMAC_Poll(unsigned char *pFrame, unsigned int frameSize, unsigned int *pRcvSize)
{
unsigned short bufferLength;
unsigned int tmpFrameSize=0;
unsigned char *pTmpFrame=0;
unsigned int tmpIdx = rxTd.idx;
volatile EmacRxTDescriptor *pRxTd = rxTd.td + rxTd.idx;
ASSERT(pFrame, "F: EMAC_Poll\n\r");
char isFrame = 0;
// Set the default return value
*pRcvSize = 0;
// Process received RxTd
while ((pRxTd->addr & EMAC_RX_OWNERSHIP_BIT) == EMAC_RX_OWNERSHIP_BIT) {
// A start of frame has been received, discard previous fragments
if ((pRxTd->status & EMAC_RX_SOF_BIT) == EMAC_RX_SOF_BIT) {
// Skip previous fragment
while (tmpIdx != rxTd.idx) {
pRxTd = rxTd.td + rxTd.idx;
pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
CIRC_INC(rxTd.idx, RX_BUFFERS);
}
// Reset the temporary frame pointer
pTmpFrame = pFrame;
tmpFrameSize = 0;
// Start to gather buffers in a frame
isFrame = 1;
}
// Increment the pointer
CIRC_INC(tmpIdx, RX_BUFFERS);
// Copy data in the frame buffer
if (isFrame) {
if (tmpIdx == rxTd.idx) {
TRACE_INFO("no EOF (Invalid of buffers too small)\n\r");
do {
pRxTd = rxTd.td + rxTd.idx;
pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
CIRC_INC(rxTd.idx, RX_BUFFERS);
} while(tmpIdx != rxTd.idx);
return EMAC_RX_NO_DATA;
}
// Copy the buffer into the application frame
bufferLength = EMAC_RX_UNITSIZE;
if ((tmpFrameSize + bufferLength) > frameSize) {
bufferLength = frameSize - tmpFrameSize;
}
memcpy(pTmpFrame, (void*)(pRxTd->addr & EMAC_ADDRESS_MASK), bufferLength);
pTmpFrame += bufferLength;
tmpFrameSize += bufferLength;
// An end of frame has been received, return the data
if ((pRxTd->status & EMAC_RX_EOF_BIT) == EMAC_RX_EOF_BIT) {
// Frame size from the EMAC
*pRcvSize = (pRxTd->status & EMAC_LENGTH_FRAME);
// Application frame buffer is too small all data have not been copied
if (tmpFrameSize < *pRcvSize) {
printf("size req %d size allocated %d\n\r", *pRcvSize, frameSize);
return EMAC_RX_FRAME_SIZE_TOO_SMALL;
}
TRACE_DEBUG("packet %d-%d (%d)\n\r", rxTd.idx, tmpIdx, *pRcvSize);
// All data have been copied in the application frame buffer => release TD
while (rxTd.idx != tmpIdx) {
pRxTd = rxTd.td + rxTd.idx;
pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
CIRC_INC(rxTd.idx, RX_BUFFERS);
}
EmacStatistics.rx_packets++;
return EMAC_RX_OK;
}
}
// SOF has not been detected, skip the fragment
else {
pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
rxTd.idx = tmpIdx;
}
// Process the next buffer
pRxTd = rxTd.td + tmpIdx;
}
//TRACE_DEBUG("E");
return EMAC_RX_NO_DATA;
}