📄 csl_emac.c
字号:
if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_PASSCONTROL )
EMAC_FSETS( RXMBPENABLE, RXCMFEN, ENABLE );
/* Set the channel configuration to priority if requested */
if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_CHPRIORITY )
EMAC_FSETS( MACCONTROL, TXPTYPE, CHANNELPRI );
/* Set MAC loopback if requested */
if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_MACLOOPBACK )
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 );
for(i=0; i<localDev.Config.TxChannels; i++)
EMAC_RSET( TXINTMASKSET, (1<<i) );
EMAC_RSET( MACINTMASKSET, EMAC_FMK(MACINTMASKSET,HOSTERRINT,1) |
EMAC_FMK(MACINTMASKSET,STATINT,1) );
/*
// Setup Receive Buffers
*/
/*
// We give the first descriptors to RX The rest of the descriptors
// will be divided evenly among the TX channels. Odds are this
// will leave TX with a very large number of TX descriptors, but
// we'll only use what we need (driven from the application send
// requests). The RX descriptors are always kept fully populated.
*/
/* Pointer to first descriptor to use on RX */
pDesc = (EMAC_Desc *)_EMAC_DSC_BASE_ADDR;
/* Number of descriptors for RX channel */
utemp1 = localDev.Config.RxMaxPktPool;
/* Init Rx */
localDev.RxCh.pd = &localDev;
localDev.RxCh.DescMax = utemp1;
localDev.RxCh.pDescFirst = pDesc;
localDev.RxCh.pDescLast = pDesc + (utemp1 - 1);
localDev.RxCh.pDescRead = pDesc;
localDev.RxCh.pDescWrite = pDesc;
/* Fill the descriptor table */
emacEnqueueRx( &localDev.RxCh, 0 );
/*
// If we didn't get the number of descriptor buffers that the
// application said we should, then the app lied to us. This is
// bad because we'll be constantly calling to the app to fill
// up our buffers. So we'll close now to make the problem
// obvious.
*/
if( localDev.RxCh.DescCount < utemp1 )
{
/* Free all RX descriptors */
while( pPkt = pqPop( &localDev.RxCh.DescQueue ) )
(*localDev.Config.pfcbFreePacket)(localDev.hApplication, pPkt);
/* Close the MDIO Module */
MDIO_close( localDev.hMDIO );
/* Return the error condition */
return( EMAC_ERROR_INVALID );
}
/*
// Setup Transmit Buffers
*/
/* Pointer to first descriptor to use on TX */
pDesc += utemp1;
/* Number of descriptors (max) per channel */
utemp1 = (_EDMA_DSC_ENTRY_COUNT-utemp1)/localDev.Config.TxChannels;
/* Init all TX channels in use */
for( i=0; i<(int)localDev.Config.TxChannels; i++)
{
localDev.TxCh[i].pd = &localDev;
localDev.TxCh[i].DescMax = utemp1;
localDev.TxCh[i].pDescFirst = pDesc;
localDev.TxCh[i].pDescLast = pDesc + (utemp1 - 1);
localDev.TxCh[i].pDescRead = pDesc;
localDev.TxCh[i].pDescWrite = pDesc;
pDesc += utemp1;
}
/*
// 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)localDev.RxCh.pDescRead );
/* Validate the device handle */
localDev.DevMagic = EMAC_DEVMAGIC;
/* Set the open flag */
openFlag = 1;
/* Give a handle back to the caller */
*phEMAC = &localDev;
/* Enable global interrupt in wrapper */
EMAC_FSETS( EWCTL, INTEN, ENABLE );
/* Return Success */
return( 0 );
}
/*-----------------------------------------------------------------------*\
* EMAC_close()
*
* Closed the EMAC peripheral indicated by the supplied instance handle.
* When called, the EMAC device will shutdown both send and receive
* operations, and free all pending transmit and receive packets.
*
* The function returns zero on success, or an error code on failure.
*
* Possible error code include:
* EMAC_ERROR_INVALID - A calling parameter is invalid
*
\*-----------------------------------------------------------------------*/
uint EMAC_close( Handle hEMAC )
{
EMAC_Device *pd = (EMAC_Device *)hEMAC;
Uint32 i,tmp;
EMAC_Pkt *pPkt;
/* Validate our handle */
if( !pd || pd->DevMagic != EMAC_DEVMAGIC )
return( EMAC_ERROR_INVALID );
/* Disable EMAC/MDIO interrupts in wrapper */
EMAC_FSETS( EWCTL, INTEN, DISABLE );
/*
// The close process consists of tearing down all the active
// channels (RX and TX) and then waiting for the teardown
// complete indication from the MAC. Then, all queued packets
// will be returned.
*/
/* Teardown RX */
EMAC_RSET( RXTEARDOWN, 0 );
/* Teardown TX channels in use */
for( i=0; i<pd->Config.TxChannels; i++)
EMAC_RSET( TXTEARDOWN, i );
/* Only check teardown status if there was no fatal error */
/* Otherwise; the EMAC is halted and can抰 be shutdown gracefully */
if( !pd->FatalError )
{
/* Wait for the teardown to complete */
for( tmp=0; tmp!=0xFFFFFFFC; tmp=EMAC_RGET(RX0INTACK) );
EMAC_RSET( RX0INTACK, tmp );
for( i=0; i<pd->Config.TxChannels; i++ )
{
for( tmp=0; tmp!=0xFFFFFFFC; tmp=EMAC_RGETI(TXINTACK,i) );
EMAC_RSETI( TXINTACK, i, tmp );
}
}
/* Disable RX, TX, and Clear MACCONTROL */
EMAC_FSETS( TXCONTROL, TXEN, DISABLE );
EMAC_FSETS( RXCONTROL, RXEN, DISABLE );
EMAC_RSET( MACCONTROL, 0 );
/* Free all RX buffers */
while( pPkt = pqPop( &pd->RxCh.DescQueue ) )
(*pd->Config.pfcbFreePacket)(localDev.hApplication, pPkt);
/* Free all TX buffers */
for( i=0; i<pd->Config.TxChannels; i++)
{
while( pPkt = pqPop( &pd->TxCh[i].DescQueue ) )
(*pd->Config.pfcbFreePacket)(localDev.hApplication, pPkt);
while( pPkt = pqPop( &pd->TxCh[i].WaitQueue ) )
(*pd->Config.pfcbFreePacket)(localDev.hApplication, pPkt);
}
/* Close the MDIO Module */
MDIO_close( pd->hMDIO );
/* Invalidate the EMAC handle */
pd->DevMagic = 0;
/* Clear the open flag */
openFlag = 0;
/* Exit with interrupts still disabled in the wrapper */
return(0);
}
/*-----------------------------------------------------------------------*\
* EMAC_getStatus()
*
* Called to get the current status of the device. The device status
* is copied into the supplied data structure.
*
* The function returns zero on success, or an error code on failure.
*
* Possible error code include:
* EMAC_ERROR_INVALID - A calling parameter is invalid
*
\*-----------------------------------------------------------------------*/
uint EMAC_getStatus( Handle hEMAC, EMAC_Status *pStatus )
{
EMAC_Device *pd = (EMAC_Device *)hEMAC;
uint i,tmp;
/* Validate our handle */
if( !pd || pd->DevMagic != EMAC_DEVMAGIC || !pStatus )
return( EMAC_ERROR_INVALID );
/* Get the MDIO status */
MDIO_getStatus(pd->hMDIO, &pStatus->PhyDev, &pStatus->MdioLinkStatus );
/* Number of rx packets held */
pStatus->RxPktHeld = pd->RxCh.DescCount;
/* Number of tx packets held */
tmp = 0;
for( i=0; i<pd->Config.TxChannels; i++)
{
tmp += pd->TxCh[i].DescCount;
tmp += pd->TxCh[i].WaitQueue.Count;
}
pStatus->TxPktHeld = tmp;
/* Fatal error value */
pStatus->FatalError = pd->FatalError;
return(0);
}
/*-----------------------------------------------------------------------*\
* EMAC_setReceiveFilter()
*
* Called to set the packet filter for received packets. The filtering
* level is inclusive, so BROADCAST would include both BROADCAST and
* DIRECTED (UNICAST) packets.
*
* Available filtering modes include the following:
* EMAC_RXFILTER_NOTHING - Receive nothing
* EMAC_RXFILTER_DIRECT - Receive only Unicast to local MAC addr
* EMAC_RXFILTER_BROADCAST - Receive direct and Broadcast
* EMAC_RXFILTER_MULTICAST - Receive above plus multicast in mcast list
* EMAC_RXFILTER_ALLMULTICAST - Receive above plus all multicast
* EMAC_RXFILTER_ALL - Receive all packets
*
* Note that if error frames and control frames are desired, reception of
* these must be specified in the device configuration.
*
* The function returns zero on success, or an error code on failure.
*
* Possible error code include:
* EMAC_ERROR_INVALID - A calling parameter is invalid
*
\*-----------------------------------------------------------------------*/
uint EMAC_setReceiveFilter( Handle hEMAC, uint ReceiveFilter )
{
EMAC_Device *pd = (EMAC_Device *)hEMAC;
/* Validate our handle */
if( !pd || pd->DevMagic != EMAC_DEVMAGIC || ReceiveFilter > EMAC_RXFILTER_ALL )
return( EMAC_ERROR_INVALID );
/*
// The following code relies on the numberic relation of the filter
// value such that the higher filter values receive more types of
// packets.
*/
/* Disable Section */
if( ReceiveFilter < EMAC_RXFILTER_ALL )
EMAC_FSETS( RXMBPENABLE, RXCAFEN, DISABLE );
if( ReceiveFilter < EMAC_RXFILTER_ALLMULTICAST )
{
EMAC_RSET( MACHASH1, pd->MacHash1 );
EMAC_RSET( MACHASH2, pd->MacHash2 );
}
if( ReceiveFilter < EMAC_RXFILTER_MULTICAST )
EMAC_FSETS( RXMBPENABLE, MULTEN, DISABLE );
if( ReceiveFilter < EMAC_RXFILTER_BROADCAST )
EMAC_FSETS( RXMBPENABLE, BROADEN, DISABLE );
if( ReceiveFilter < EMAC_RXFILTER_DIRECT )
EMAC_RSET( RXUNICASTCLEAR, 1 );
/* Enable Section */
if( ReceiveFilter >= EMAC_RXFILTER_DIRECT )
EMAC_RSET( RXUNICASTSET, 1 );
if( ReceiveFilter >= EMAC_RXFILTER_BROADCAST )
EMAC_FSETS( RXMBPENABLE, BROADEN, ENABLE );
if( ReceiveFilter >= EMAC_RXFILTER_MULTICAST )
EMAC_FSETS( RXMBPENABLE, MULTEN, ENABLE );
if( ReceiveFilter >= EMAC_RXFILTER_ALLMULTICAST )
{
EMAC_RSET( MACHASH1, 0xffffffff );
EMAC_RSET( MACHASH1, 0xffffffff );
}
if( ReceiveFilter == EMAC_RXFILTER_ALL )
EMAC_FSETS( RXMBPENABLE, RXCAFEN, ENABLE );
pd->RxFilter = ReceiveFilter;
return(0);
}
/*-----------------------------------------------------------------------*\
* EMAC_getReceiveFilter()
*
* Called to get the current packet filter setting for received packets.
* The filter values are the same as those used in EMAC_setReceiveFilter().
*
* The current filter value is writter to the pointer supplied in
* pReceiveFilter.
*
* The function returns zero on success, or an error code on failure.
*
* Possible error code include:
* EMAC_ERROR_INVALID - A calling parameter is invalid
*
\*-----------------------------------------------------------------------*/
uint EMAC_getReceiveFilter( Handle hEMAC, uint *pReceiveFilter )
{
EMAC_Device *pd = (EMAC_Device *)hEMAC;
/* Validate our handle */
if( !pd || pd->DevMagic != EMAC_DEVMAGIC || !pReceiveFilter )
return( EMAC_ERROR_INVALID );
*pReceiveFilter = pd->RxFilter;
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -