📄 c6455.c
字号:
EMAC_REGS->RXMBPENABLE = 0;
EMAC_REGS->MACHASH1 = 0;
EMAC_REGS->MACHASH2 = 0;
/* Clear Unicast RX on channel 0-7 */
EMAC_REGS->RXUNICASTCLEAR = 0xFF;
/* Set the pass RX CRC mode */
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXPASSCRC, INCLUDE );
/* Set MAC loopback if requested */
// CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_LOOPBACK, ENABLE );
/*
// Enable TX and RX channel interrupts (set mask bits)
// Enable Host interrupts
*/
EMAC_REGS->RXINTMASKCLEAR = 0xFF;
EMAC_REGS->TXINTMASKCLEAR = 0xFF;
EMAC_REGS->RXINTMASKSET = 0x1;
EMAC_REGS->TXINTMASKSET = 0x1;
EMAC_REGS->MACINTMASKSET = CSL_FMK( EMAC_MACINTMASKSET_HOSTMASK, 1 ) |
CSL_FMK( EMAC_MACINTMASKSET_STATMASK, 1 ) ;
/*
// Setup Receive Buffers
*/
/* Pointer to first descriptor to use on RX */
pDesc = (EMAC_Desc *)_EMAC_DSC_BASE_ADDR;
/* Number of descriptors for RX channel */
utemp1 = EMAC_MAX_RX;
/* Init Rx channel */
mmZeroInit( &chRx, sizeof(EMAC_DescCh) );
chRx.DescMax = utemp1;
chRx.pDescFirst = pDesc;
chRx.pDescLast = pDesc + (utemp1 - 1);
chRx.pDescRead = pDesc;
chRx.pDescWrite = pDesc;
/* Fill the descriptor table */
emacEnqueueRx(0);
/*
// If we didn't get the number of descriptor buffers that we
// wanted to, abort now.
*/
if( chRx.DescCount < utemp1 )
{
/* Free all RX descriptors */
while( hPkt = PBMQ_deq( &chRx.DescQueue ) )
PBM_free(hPkt);
/* Close the MDIO Module */
MDIO_close( hMDIO );
/* Return the error condition */
return( 0 );
}
/*
// Setup Transmit Buffers
*/
/* Pointer to first descriptor to use on TX */
pDesc += utemp1;
/* Number of descriptors (max) for TX channel */
utemp1 = (_EDMA_DSC_ENTRY_COUNT-utemp1);
/* Init TX channel */
mmZeroInit( &chTx, sizeof(EMAC_DescCh) );
chTx.DescMax = utemp1;
chTx.pDescFirst = pDesc;
chTx.pDescLast = pDesc + (utemp1 - 1);
chTx.pDescRead = pDesc;
chTx.pDescWrite = pDesc;
/*
// Enable RX, TX, and MII
//
// Note in full duplex mode we also need to set the FULLDUPLEX
// bit in MACCRONTROL. However, we don't know what to set until
// we have a link. Also, we must be able to dynamically change
// this bit if the cable is unplugged and re-linked with a different
// duplex.
*/
CSL_FINST( EMAC_REGS->TXCONTROL, EMAC_TXCONTROL_TXEN, ENABLE );
CSL_FINST( EMAC_REGS->RXCONTROL, EMAC_RXCONTROL_RXEN, ENABLE );
EMAC_REGS->MACCONTROL = CSL_FMKT( EMAC_MACCONTROL_RXOWNERSHIP, ONE ) |
CSL_FMKT( EMAC_MACCONTROL_RXOFFLENBLOCK, BLOCK ) |
CSL_FMKT( EMAC_MACCONTROL_GMIIEN, ENABLE );
/* Startup RX */
EMAC_REGS->RX0HDP = (Uint32)chRx.pDescRead ;
/* Enable global interrupt in wrapper */
CSL_FINST( ECTL_REGS->EWCTL, ECTL_EWCTL_INTEN, ENABLE );
return(1);
}
/*--------------------------------------------------------------------*\
* emacDequeueTx()
*
* Dequeue all completed TX packets and return buffers to application
\*--------------------------------------------------------------------*/
static void emacDequeueTx( EMAC_Desc *pDescAck )
{
PBM_Handle hPkt;
Uint32 PktFlgLen;
register uint i,j = (uint)chTx.pDescRead;
/* Get the status of the ACK descriptor */
PktFlgLen = pDescAck->PktFlgLen;
/* Calc the new "Read" descriptor */
if( pDescAck == chTx.pDescLast )
chTx.pDescRead = chTx.pDescFirst;
else
chTx.pDescRead = pDescAck+1;
i = (uint)chTx.pDescRead;
/* Turn i into a descriptor count */
if( j < i )
i = (i-j)/sizeof(EMAC_Desc);
else
i = chTx.DescMax - ((j-i)/sizeof(EMAC_Desc));
chTx.DescCount -= i;
/* Pop & Free Buffers 'till the last Descriptor */
while( i-- )
{
// Recover the packet and free it
hPkt = PBMQ_deq( &chTx.DescQueue );
if( hPkt )
PBM_free( hPkt );
}
// If the transmitter stopped and we have more descriptors, then restart
if( (PktFlgLen & EMAC_DSC_FLAG_EOQ) && chTx.DescCount )
EMAC_REGS->TX0HDP = (Uint32)chTx.pDescRead;
}
/*--------------------------------------------------------------------*\
* emacEnqueueRx()
*
* Fill any empty RX descriptors with new buffers from the application
\*--------------------------------------------------------------------*/
static void emacEnqueueRx( uint fRestart )
{
PBM_Handle hPkt;
EMAC_Desc *pDesc;
uint CountOrg;
UINT8 *buffer;
// Keep the old count around
CountOrg = chRx.DescCount;
// Fill RX Packets Until Full
while( chRx.DescCount < chRx.DescMax )
{
// Try and get a buffer.
hPkt = PBM_alloc( 1518 + PKT_PREPAD );
if( !hPkt )
break;
PBM_setDataOffset( hPkt, PKT_PREPAD );
buffer = PBM_getDataBuffer(hPkt) + PKT_PREPAD;
// Clean the cache for external addesses
if( (UINT32)buffer & EXTMEM )
OEMCacheClean( (void *)buffer, 1518 );
// Fill in the descriptor for this buffer
pDesc = chRx.pDescWrite;
// Move the write pointer and bump count
if( chRx.pDescWrite == chRx.pDescLast )
chRx.pDescWrite = chRx.pDescFirst;
else
chRx.pDescWrite++;
chRx.DescCount++;
// Fill in the descriptor
pDesc->pNext = 0;
pDesc->pBuffer = buffer;
pDesc->BufOffLen = 1518;
pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
// Enqueue this packet onto the desc queue
PBMQ_enq( &chRx.DescQueue, hPkt );
// Synch the cache
if( (UINT32)buffer & EXTMEM )
OEMCacheCleanSynch();
// Make the previous buffer point to us
if( pDesc == chRx.pDescFirst )
chRx.pDescLast->pNext = pDesc;
else
(pDesc-1)->pNext = pDesc;
}
/* Restart RX if we had ran out of descriptors and got some here */
if( fRestart && !CountOrg && chRx.DescCount )
EMAC_REGS->RX0HDP = (Uint32)chRx.pDescRead;
}
/*--------------------------------------------------------------------*\
* emacDequeueRx()
*
* Dequeue all completed RX packets and give buffers to application
\*--------------------------------------------------------------------*/
static void emacDequeueRx( EMAC_Desc *pDescAck )
{
PBM_Handle hPkt;
uint tmp;
Uint32 PktFlgLen;
uint NeedService = 0;
EMAC_Desc *pDescNewRxFirst,*pDescNewRxLast=0,*pTemp;
UINT8 *buffer;
/* Remember the first new descriptor slot */
pDescNewRxFirst = chRx.pDescWrite;
/*
// Pop & Free Buffers 'till the last Descriptor
// One thing we know for sure is that all the decriptors from
// the read pointer to pDescAsk are linked to each other via
// their pNext field.
*/
for( tmp=1; tmp; )
{
/* Get the status of this descriptor */
PktFlgLen = chRx.pDescRead->PktFlgLen;
// Recover the packet and pass it on
hPkt = PBMQ_deq( &chRx.DescQueue );
if( hPkt )
{
// Enqueue the packet and signal the stack
#ifndef _INCLUDE_NIMU_CODE
PBM_setIFRx( hPkt, pPDI->hEther );
PBM_setValidLen(hPkt,(PktFlgLen & 0xFFFF));
PBMQ_enq( &PBMQ_rx, hPkt );
#else
/* Remove the 4 byte CRC at the end of the packet and account for it. */
PktFlgLen = (PktFlgLen & 0xFFFF) - 4;
PBM_setValidLen (hPkt,PktFlgLen);
PBMQ_enq( &pPDI->PBMQ_rx, hPkt );
#endif
NeedService = 1;
}
/* See if this was the last buffer */
if( chRx.pDescRead == pDescAck )
tmp = 0;
/* Move the read pointer and decrement count */
if( chRx.pDescRead == chRx.pDescLast )
chRx.pDescRead = chRx.pDescFirst;
else
chRx.pDescRead++;
chRx.DescCount--;
// Try and get a buffer.
hPkt = PBM_alloc( 1518 + PKT_PREPAD );
if( hPkt )
{
PBM_setDataOffset( hPkt, PKT_PREPAD );
buffer = PBM_getDataBuffer(hPkt) + PKT_PREPAD;
// Clean the cache for external addresses
if( (UINT32)buffer & EXTMEM )
OEMCacheClean( (void *)buffer, 1518 );
// Fill in the descriptor for this buffer
pDescNewRxLast = chRx.pDescWrite;
// Move the write pointer and bump count
if( chRx.pDescWrite == chRx.pDescLast )
chRx.pDescWrite = chRx.pDescFirst;
else
chRx.pDescWrite++;
chRx.DescCount++;
// Fill in the descriptor
pDescNewRxLast->pBuffer = buffer;
// Enqueue this packet onto the desc queue
PBMQ_enq( &chRx.DescQueue, hPkt );
}
}
/*
// If we added descriptors, make the pNext of the last NULL, and
// make the previous descriptor point to the new list we added.
*/
if( pDescNewRxLast )
{
pDescNewRxLast->pNext = 0;
// Synch the cache
if( (UINT32)buffer & EXTMEM )
OEMCacheCleanSynch();
/* Make the previous buffer point to us */
if( pDescNewRxFirst == chRx.pDescFirst )
pTemp = chRx.pDescLast;
else
pTemp = pDescNewRxFirst-1;
/*
// If these pointers wrapped, the RX engine is stopped
// Otherwise; tack the new list to the old
*/
if( pTemp != pDescNewRxLast )
pTemp->pNext = pDescNewRxFirst;
}
/* If the receiver stopped and we have more descriptors, then restart */
if( (PktFlgLen & EMAC_DSC_FLAG_EOQ) && chRx.DescCount )
EMAC_REGS->RX0HDP = (Uint32)chRx.pDescRead ;
// Signal the stack if needed
if( NeedService )
{
FlashActiveLED = 1;
STKEVENT_signal( pPDI->hEvent, STKEVENT_ETHERNET, 1 );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -