📄 c6455_emac.c
字号:
{
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXCEFEN, ENABLE );
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXCSFEN, ENABLE );
}
/* If PASSCONTROL is set, enable control frames */
if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_PASSCONTROL )
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXCMFEN, ENABLE );
/* Set the channel configuration to priority if requested */
if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_CHPRIORITY )
CSL_FINST(EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_TXPTYPE, CHANNELPRI );
/* Set MAC loopback if requested */
if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_MACLOOPBACK )
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 = 1;
for(i=0; i<localDev.Config.TxChannels; i++)
EMAC_REGS->TXINTMASKSET = (1<<i);
EMAC_REGS->MACINTMASKSET = CSL_FMK(EMAC_MACINTMASKSET_HOSTMASK, 1) |
CSL_FMK(EMAC_MACINTMASKSET_STATMASK, 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 GMII
//
// 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 );
#if USE_EMAC_OPT
CSL_FINST( EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RXOWNERSHIP, ONE );
CSL_FINST( EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_RXOFFLENBLOCK, BLOCK );
#endif
CSL_FINST( EMAC_REGS->MACCONTROL, EMAC_MACCONTROL_GMIIEN, ENABLE );
/* Startup RX */
EMAC_REGS->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 */
CSL_FINST( ECTL_REGS->EWCTL, ECTL_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;
volatile Uint32 *pRegAddr;
/* Validate our handle */
if( !pd || pd->DevMagic != EMAC_DEVMAGIC )
return( EMAC_ERROR_INVALID );
/* Disable EMAC/MDIO interrupts in wrapper */
CSL_FINST(ECTL_REGS->EWCTL, ECTL_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_REGS->RXTEARDOWN = 0 ;
/* Teardown TX channels in use */
for( i=0; i<pd->Config.TxChannels; i++)
EMAC_REGS->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_REGS->RX0CP );
EMAC_REGS->RX0CP = tmp;
pRegAddr = &EMAC_REGS->TX0CP;
for( i=0; i<pd->Config.TxChannels; i++ )
{
for( tmp=0; tmp!=0xFFFFFFFC; tmp=*(pRegAddr + i) );
*(pRegAddr + i) = tmp;
}
}
/* Disable RX, TX, and Clear MACCONTROL */
CSL_FINST(EMAC_REGS->TXCONTROL, EMAC_TXCONTROL_TXEN, DISABLE );
CSL_FINST(EMAC_REGS->RXCONTROL, EMAC_RXCONTROL_RXEN, DISABLE );
EMAC_REGS->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 numeric relation of the filter
// value such that the higher filter values receive more types of
// packets.
*/
/* Disable Section */
if( ReceiveFilter < EMAC_RXFILTER_ALL )
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXCAFEN, DISABLE );
if( ReceiveFilter < EMAC_RXFILTER_ALLMULTICAST )
{
#if !RAM_MCAST
EMAC_REGS->MACHASH1 = pd->MacHash1;
EMAC_REGS->MACHASH2 = pd->MacHash2;
#else
/* Don't set any hash bits - we handle them in the MACADDR table */
EMAC_REGS->MACHASH1 = 0 ;
EMAC_REGS->MACHASH2 = 0 ;
#endif
}
if( ReceiveFilter < EMAC_RXFILTER_MULTICAST )
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXMULTEN, DISABLE );
if( ReceiveFilter < EMAC_RXFILTER_BROADCAST )
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXBROADEN, DISABLE );
if( ReceiveFilter < EMAC_RXFILTER_DIRECT )
EMAC_REGS->RXUNICASTCLEAR = 1;
/* Enable Section */
if( ReceiveFilter >= EMAC_RXFILTER_DIRECT )
EMAC_REGS->RXUNICASTSET = 1;
if( ReceiveFilter >= EMAC_RXFILTER_BROADCAST )
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXBROADEN, ENABLE );
#if !RAM_MCAST
if( ReceiveFilter >= EMAC_RXFILTER_MULTICAST )
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_RXMBPENABLE_RXMULTEN, ENABLE );
#endif
if( ReceiveFilter >= EMAC_RXFILTER_ALLMULTICAST )
{
EMAC_REGS->MACHASH1 = 0xffffffff;
EMAC_REGS->MACHASH1 = 0xffffffff;
}
if( ReceiveFilter == EMAC_RXFILTER_ALL )
CSL_FINST(EMAC_REGS->RXMBPENABLE, EMAC_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);
}
/*-----------------------------------------------------------------------*\
* EMAC_getStatistics()
*
* Called to get the current device statistics. The statistics structure
* contains a collection of event counts for various packet sent and
* receive properties. Reading the statistics also clears the current
* statistic counters, so the values read represent a delta from the last
* call.
*
* The statistics information is copied into the structure pointed to
* by the pStatistics argument.
*
* The function returns zero on success, or an error code on failure.
*
* Possible error code include:
* EMAC_ERROR_INVALID - A calling parameter is invalid
*
\*-----------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -