📄 csl_emac.c
字号:
/* Keep the old count around */
CountOrg = pdc->DescCount;
/* Fill RX Packets Until Full */
while( pdc->DescCount < pdc->DescMax )
{
/* Get a buffer from the application */
pPkt = (*localDev.Config.pfcbGetPacket)(pdc->pd->hApplication);
/* If no more buffers are available, break out of loop */
if( !pPkt )
break;
/* Fill in the descriptor for this buffer */
pDesc = pdc->pDescWrite;
/* Move the write pointer and bump count */
if( pdc->pDescWrite == pdc->pDescLast )
pdc->pDescWrite = pdc->pDescFirst;
else
pdc->pDescWrite++;
pdc->DescCount++;
/* Supply buffer pointer with application supplied offset */
pDesc->pNext = 0;
pDesc->pBuffer = pPkt->pDataBuffer + pPkt->DataOffset;
pDesc->BufOffLen = localDev.PktMTU;
pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
/* Make the previous buffer point to us */
if( pDesc == pdc->pDescFirst )
pdc->pDescLast->pNext = pDesc;
else
(pDesc-1)->pNext = pDesc;
/* Push the packet buffer on the local descriptor queue */
pqPush( &pdc->DescQueue, pPkt );
}
/* Restart RX if we had ran out of descriptors and got some here */
if( fRestart && !CountOrg && pdc->DescCount )
EMAC_RSET( RX0HDP, (Uint32)pdc->pDescRead );
}
/*--------------------------------------------------------------------*\
* emacDequeueRx()
*
* Dequeue all completed RX packets and give buffers to application
\*--------------------------------------------------------------------*/
static void emacDequeueRx( EMAC_DescCh *pdc, EMAC_Desc *pDescAck )
{
EMAC_Pkt *pPkt;
EMAC_Pkt *pPktNew;
EMAC_Desc *pDescNewRxFirst,*pDescNewRxLast=0;
uint tmp;
Uint32 PktFlgLen;
/* Remember the first new descriptor slot */
pDescNewRxFirst = pdc->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 = pdc->pDescRead->PktFlgLen;
/* Recover the buffer and free it */
pPkt = pqPop( &pdc->DescQueue );
if( pPkt )
{
/* Fill in the necessary packet header fields */
pPkt->Flags = PktFlgLen & 0xFFFF0000;
pPkt->ValidLen = pPkt->PktLength = PktFlgLen & 0xFFFF;
pPkt->PktChannel = 0;
pPkt->PktFrags = 1;
/* Pass the packet to the application */
pPktNew = (*localDev.Config.pfcbRxPacket)
(pdc->pd->hApplication,pPkt);
}
/* See if this was the last buffer */
if( pdc->pDescRead == pDescAck )
tmp = 0;
/* Move the read pointer and decrement count */
if( pdc->pDescRead == pdc->pDescLast )
pdc->pDescRead = pdc->pDescFirst;
else
pdc->pDescRead++;
pdc->DescCount--;
/* See if we got a replacement packet */
if( pPktNew )
{
/* We know we can immediately queue this packet */
/* Fill in the descriptor for this buffer */
pDescNewRxLast = pdc->pDescWrite;
/* Move the write pointer and bump count */
if( pdc->pDescWrite == pdc->pDescLast )
pdc->pDescWrite = pdc->pDescFirst;
else
pdc->pDescWrite++;
pdc->DescCount++;
/* Supply buffer pointer with application supplied offset */
pDescNewRxLast->pBuffer = pPktNew->pDataBuffer + pPktNew->DataOffset;
pDescNewRxLast->BufOffLen = localDev.PktMTU;
pDescNewRxLast->PktFlgLen = EMAC_DSC_FLAG_OWNER;
/* Push the packet buffer on the local descriptor queue */
pqPush( &pdc->DescQueue, pPktNew );
}
}
/*
// 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;
/* Make the previous buffer point to us */
if( pDescNewRxFirst == pdc->pDescFirst )
pdc->pDescLast->pNext = pDescNewRxFirst;
else
(pDescNewRxFirst-1)->pNext = pDescNewRxFirst;
}
/* If the receiver stopped and we have more descriptors, then restart */
if( (PktFlgLen & EMAC_DSC_FLAG_EOQ) && pdc->DescCount )
EMAC_RSET( RX0HDP, (Uint32)pdc->pDescRead );
}
/*-----------------------------------------------------------------------*\
* STANDARD API FUNCTIONS
*
* Note on Exclusion (Serialization):
* The application is charged with verifying that only one of the
* following API calls may only be executing at a given time across
* all threads and all interrupt functions.
*
\*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*\
* EMAC_enumerate()
*
* Enumerates the EMAC peripherals installed in the system and returns an
* integer count. The EMAC devices are enumerated in a consistent
* fashion so that each device can be later referenced by its physical
* index value ranging from "1" to "n" where "n" is the count returned
* by this function.
\*-----------------------------------------------------------------------*/
uint EMAC_enumerate( void )
{
return(1);
}
/*-----------------------------------------------------------------------*\
* EMAC_open()
*
* Opens the EMAC peripheral at the given physical index and initializes
* it to an embryonic state.
*
* The calling application must supply a operating configuration that
* includes a callback function table. Data from this config structure is
* copied into the device's internal instance structure so the structure
* may be discarded after EMAC_open() returns. In order to change an item
* in the configuration, the the EMAC device must be closed and then
* re-opened with the new configuration.
*
* The application layer may pass in an hApplication callback handle,
* that will be supplied by the EMAC device when making calls to the
* application callback functions.
*
* An EMAC device handle is written to phEMAC. This handle must be saved
* by the caller and then passed to other EMAC device functions.
*
* The default receive filter prevents normal packets from being received
* until the receive filter is specified by calling EMAC_receiveFilter().
*
* A device reset is achieved by calling EMAC_close() followed by EMAC_open().
*
* The function returns zero on success, or an error code on failure.
*
* Possible error codes include:
* EMAC_ERROR_ALREADY - The device is already open
* EMAC_ERROR_INVALID - A calling parameter is invalid
*
\*-----------------------------------------------------------------------*/
uint EMAC_open( int physicalIndex, Handle hApplication,
EMAC_Config *pEMACConfig, Handle *phEMAC )
{
int i;
volatile Uint32 *pRegAddr;
Uint32 tmpval;
EMAC_Pkt *pPkt;
uint utemp1;
EMAC_Desc *pDesc;
/* We only handle a single instance */
if( physicalIndex != 1 )
return( EMAC_ERROR_INVALID );
/* If the device is alread open, return an error */
if( openFlag )
return( EMAC_ERROR_ALREADY );
/*
// Validate the supplied configuration structure
*/
if( !pEMACConfig || !phEMAC )
return( EMAC_ERROR_INVALID );
/* Rx pool must be at least 8 to 192 */
if( pEMACConfig->RxMaxPktPool < 8 || pEMACConfig->RxMaxPktPool > 192 )
return( EMAC_ERROR_INVALID );
/* MAC address must be supplied and not a multicast address */
if( pEMACConfig->MacAddr[0] & 1 )
return( EMAC_ERROR_INVALID );
for( i=0; i<6 && !(pEMACConfig->MacAddr[i]); i++ )
if( i==6 )
return( EMAC_ERROR_INVALID );
/* Tx Channels must be 1-8 */
if( pEMACConfig->TxChannels < 1 || pEMACConfig->TxChannels > 8 )
return( EMAC_ERROR_INVALID );
/* Callback functions must be supplied */
if( !pEMACConfig->pfcbGetPacket || !pEMACConfig->pfcbFreePacket ||
!pEMACConfig->pfcbRxPacket || !pEMACConfig->pfcbStatus ||
!pEMACConfig->pfcbStatistics )
return( EMAC_ERROR_INVALID );
/* MDIO settings must be valid - at least one bit must be set */
if( !(pEMACConfig->MdioModeFlags & ( MDIO_MODEFLG_AUTONEG |
MDIO_MODEFLG_HD10 | MDIO_MODEFLG_FD10 |
MDIO_MODEFLG_HD100 | MDIO_MODEFLG_FD100 )) )
return( EMAC_ERROR_INVALID );
/*
// Init the instance structure
*/
/* Default everything in our instance structure to zero */
memset( &localDev, 0, sizeof(EMAC_Device) );
/* Set the hApplication and RxFilter */
localDev.hApplication = hApplication;
localDev.RxFilter = EMAC_RXFILTER_NOTHING;
/* Setup the new configuration */
localDev.Config = *pEMACConfig;
/*
// 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 );
/* Start the MII Configuration */
localDev.hMDIO = MDIO_open( pEMACConfig->MdioModeFlags );
/*
// 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, localDev.Config.MacAddr[5] );
EMAC_RSET( MACADDRM, localDev.Config.MacAddr[4] );
tmpval = 0;
for( i=3; i>=0; i-- )
tmpval = (tmpval<<8) | localDev.Config.MacAddr[i];
EMAC_RSET( MACADDRH, tmpval );
/*
// Setup Special Receive Conditions (loopback, error frames, etc)
*/
/* 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 and adjust max buffer accordingly */
if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_RXCRC )
{
EMAC_FSETS( RXMBPENABLE, RXPASSCRC, INCLUDE );
localDev.PktMTU = 1518;
}
else
localDev.PktMTU = 1514;
/* If PASSERROR is set, enable both ERROR and short frames */
if( localDev.Config.ModeFlags & EMAC_CONFIG_MODEFLG_PASSERROR )
{
EMAC_FSETS( RXMBPENABLE, RXCEFEN, ENABLE );
EMAC_FSETS( RXMBPENABLE, RXCSFEN, ENABLE );
}
/* If PASSCONTROL is set, enable control frames */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -