📄 dm642.c
字号:
/*
// There are "EMAC_NUMSTATS" statistics registers
// Note that when MIIEN is set in MACCONTROL, these registers
// are "write to decrement".
*/
for( tmp=0; tmp<EMAC_NUMSTATS; tmp++ )
{
statval = *pRegAddr;
*pRegAddr++ = statval;
}
}
// Look for TX interrupt (channel 0)
if( intflags & EMAC_FMK( MACINVECTOR, TXPEND, 1<<0 ) )
{
Desc = EMAC_RGET( TX0INTACK );
EMAC_RSET( TX0INTACK, Desc );
emacDequeueTx( (EMAC_Desc *)Desc );
}
// Look for RX interrupt (channel 0)
if( intflags & EMAC_FMK( MACINVECTOR, RXPEND, 1<<0 ) )
{
Desc = EMAC_RGET( RX0INTACK );
EMAC_RSET( RX0INTACK, Desc );
emacDequeueRx( (EMAC_Desc *)Desc );
}
// Enable EMAC/MDIO interrupts in wrapper
EMAC_FSETS( EWCTL, INTEN, ENABLE );
}
/*--------------------------------------------------------------------*\
* emacInit()
*
* Initialize EMAC. Return "1" if all is OK
\*--------------------------------------------------------------------*/
static uint emacInit()
{
Uint32 tmpval;
int i;
volatile Uint32 *pRegAddr;
uint utemp1;
EMAC_Desc *pDesc;
PBM_Handle hPkt;
/*
// Initialize the EMAC and MDIO devices
*/
/*
// Globally disable EMAC/MDIO interrupts in wrapper and put both
// EMAC and MDIO modules into reset
*/
EMAC_RSET( EWCTL, EMAC_FMKS( EWCTL, INTEN, DISABLE ) |
EMAC_FMKS( EWCTL, EMACRST, YES ) |
EMAC_FMKS( EWCTL, MDIORST, YES ) );
/* Wait about 100 cycles */
for( i=0; i<5; i++ )
tmpval = EMAC_RGET( EWCTL );
/* Leave EMAC/MDIO interrupts disabled and take both
EMAC and MDIO modules out of reset */
EMAC_RSET( EWCTL, EMAC_FMKS( EWCTL, INTEN, DISABLE ) |
EMAC_FMKS( EWCTL, EMACRST, NO ) |
EMAC_FMKS( EWCTL, MDIORST, NO ) );
/* Wait about 100 cycles */
for( i=0; i<5; i++ )
tmpval = EMAC_RGET( EWCTL );
/* Program the interrupt pacer */
EMAC_RSET( EWINTTCNT, 4000 );
/* Start the MII Configuration */
hMDIO = MDIO_open( MDIO_MODEFLG_AUTONEG );
/*
// Setup the EMAC
*/
/* Reset MAC Control */
EMAC_RSET( MACCONTROL, 0 );
/* Must manually init HDPs to NULL */
pRegAddr = EMAC_ADDR(TX0HDP);
for( i=0; i<8; i++ )
*pRegAddr++ = 0;
pRegAddr = EMAC_ADDR(RX0HDP);
for( i=0; i<8; i++ )
*pRegAddr++ = 0;
/*
// While MIIEN is clear in MACCONTROL, we can write directly to
// the statistics registers (there are "EMAC_NUMSTATS" of them).
*/
pRegAddr = EMAC_ADDR(RXGOODFRAMES);
for( i=0; i<EMAC_NUMSTATS; i++ )
*pRegAddr++ = 0;
/* Setup device MAC address */
EMAC_RSET( MACADDRL0, *(pPDI->bMacAddr+5) );
EMAC_RSET( MACADDRM, *(pPDI->bMacAddr+4) );
tmpval = 0;
for( i=3; i>=0; i-- )
tmpval = (tmpval<<8) | *(pPDI->bMacAddr+i);
EMAC_RSET( MACADDRH, tmpval );
/* For us buffer offset will always be zero */
EMAC_RSET( RXBUFFEROFFSET, 0 );
/* Reset RX (M)ulticast (B)roadcast (P)romiscuous Enable register */
EMAC_RSET( RXMBPENABLE, 0 );
EMAC_RSET( MACHASH1, 0 );
EMAC_RSET( MACHASH2, 0 );
/* Clear Unicast RX on channel 0-7 */
EMAC_RSET( RXUNICASTCLEAR, 0xFF );
/* Set the pass RX CRC mode */
EMAC_FSETS( RXMBPENABLE, RXPASSCRC, INCLUDE );
/* Set MAC loopback if requested */
// EMAC_FSETS( MACCONTROL, LOOPBACK, ENABLE );
/*
// Enable TX and RX channel interrupts (set mask bits)
// Enable Host interrupts
*/
EMAC_RSET( RXINTMASKCLEAR, 0xFF );
EMAC_RSET( TXINTMASKCLEAR, 0xFF );
EMAC_RSET( RXINTMASKSET, 1 );
EMAC_RSET( TXINTMASKSET, 1 );
EMAC_RSET( MACINTMASKSET, EMAC_FMK(MACINTMASKSET,HOSTERRINT,1) |
EMAC_FMK(MACINTMASKSET,STATINT,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.
*/
EMAC_FSETS( TXCONTROL, TXEN, ENABLE );
EMAC_FSETS( RXCONTROL, RXEN, ENABLE );
EMAC_FSETS( MACCONTROL, MIIEN, ENABLE );
/* Startup RX */
EMAC_RSET( RX0HDP, (Uint32)chRx.pDescRead );
/* Enable global interrupt in wrapper */
ICR = IntFlag;
EMAC_FSETS( 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_RSET( 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 & 0x80000000 )
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 & 0x80000000 )
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_RSET( 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 )
{
// Enque the packet and signal the stack
PBM_setIFRx( hPkt, pPDI->hEther );
PBM_setValidLen(hPkt,(PktFlgLen & 0xFFFF));
PBMQ_enq( &PBMQ_rx, hPkt );
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 addesses
if( (UINT32)buffer & 0x80000000 )
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;
pDescNewRxLast->BufOffLen = 1518;
pDescNewRxLast->PktFlgLen = EMAC_DSC_FLAG_OWNER;
// 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 & 0x80000000 )
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_RSET( 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 + -