📄 if_cs.c
字号:
else
{
/* If there was an error in the transmit bid */
if ( BusStatus & BUS_ST_TX_BID_ERR )
{
/* Set TX not in progress */
pMbuf = pCS->pTxFrameChain;
pCS->pTxFrameChain = NULL;
pCS->TxInProgress = FALSE;
if ( !pCS->InISR )
{
/* Re-enable interrupts at the CPU */
intUnlock( State);
/* Free the bad mbuf chain */
m_freem( pMbuf );
}
else
{
/* queue the mbuf chain to be freed at task level */
csEnqueue( pCS->pTxBuffFreeList, pMbuf );
}
/* Update output stats */
/* @kml The definition of the MIB-II variable ifOutUcastPkts in Interface
group from RFC 1158 is "The total number of packets that higher-level
protocols requested be transmitted to a subnetwork-unicast address,
INCLUDE those that were discarded or not sent."*/
/* pCS->ArpCom.ac_if.if_opackets--;*/
pCS->ArpCom.ac_if.if_oerrors++;
LOGMSG("csStartOutput: unit %d, Transmit bid error (too big)\n",
pCS->ArpCom.ac_if.if_unit, 0,0,0,0,0 );
/* Loop up to transmit the next chain */
}
else
{
/* Start the TX on Rdy4Tx interrupt */
/* TX buff space not available now. */
/* Mark TX as in progress */
pCS->TxInProgress = TRUE;
if ( !pCS->InISR )
{
/* Re-enable interrupts at the CPU */
intUnlock( State );
}
/* Exit loop */
break;
}
}
}
}
/*******************************************************************************
*
* csCopyTxFrame -
*
* This routine copies the packet from a chain of mbufs to the chip. When all
* the data has been copied, then the chip automatically begins transmitting
* the data.
*
* The reason why this "simple" copy routine is so long and complicated is
* because all reads and writes to the chip must be done as 16-bit words.
* If an mbuf has an odd number of bytes, then the last byte must be saved
* and combined with the first byte of the next mbuf. Also, some processors,
* such as the MIPS do not allow word writes to non-word aligned addresses.
*
*/
LOCAL void csCopyTxFrame( CS_SOFTC *pCS, struct mbuf *pMbufChain )
{
struct mbuf *pMbuf;
FAST USHORT *pFrame;
FAST USHORT *pBuff;
FAST USHORT *pBuffLimit;
IOADDR TxDataPort;
UCHAR *pStart;
USHORT Length;
BOOL HaveExtraByte;
union
{
UCHAR byte[2];
USHORT word;
} Straddle;
/* Initialize frame pointer and data port address */
pFrame = pCS->pPacketPage + (PKTPG_TX_FRAME/2);
TxDataPort = pCS->IOAddr + PORT_RXTX_DATA;
HaveExtraByte = FALSE; /* Start out with no extra byte */
/* Process the chain of mbufs */
for ( pMbuf=pMbufChain; pMbuf!=NULL; pMbuf=pMbuf->m_next )
{
/* Setup starting pointer and length */
pStart = mtod( pMbuf, UCHAR * );
Length = pMbuf->m_len;
#ifdef ALIGMENT_32BIT
/* if the mbuf payload starts on an odd address boundary */
if( (UINT32)pStart & 0x01 )
{
/* If there is an extra byte left over from the previous mbuf */
if ( HaveExtraByte )
{
/* Add the first byte from this mbuf to make a word */
Straddle.byte[1] = *pStart;
/* Write the word which straddles the mbufs to the chip */
if ( pCS->InMemoryMode )
*pFrame++ = Straddle.word;
else
SYS_ENET_OUT_WORD( TxDataPort, Straddle.word );
/* Adjust starting pointer and length */
pStart++;
Length--;
HaveExtraByte = FALSE;
}
else
{
while( Length>=2 )
{
/* fetch 16 bits, 8 bits at a time */
Straddle.byte[0] = *(UCHAR *)pStart++;
Straddle.byte[1] = *(UCHAR *)pStart++;
/* Write the word which straddles the mbufs to the chip */
if ( pCS->InMemoryMode )
*pFrame++ = Straddle.word;
else
SYS_ENET_OUT_WORD( TxDataPort, Straddle.word );
Length -= 2;
}
/* @kml Fixed the bug that if CPU type is MIPS, an extra byte is sent
when an odd-aligned buffer and odd length data are passed.*/
/* if ( Length == 1 )
{
HaveExtraByte = TRUE;
// Save the extra byte for later
Straddle.byte[0] = *(UCHAR *)pStart++;
}
*/
}
}
#endif
/* If there is an extra byte left over from the previous mbuf */
if ( HaveExtraByte )
{
/* Add the first byte from this mbuf to make a word */
Straddle.byte[1] = *pStart;
/* Write the word which straddles the mbufs to the chip */
if ( pCS->InMemoryMode )
*pFrame++ = Straddle.word;
else
SYS_ENET_OUT_WORD( TxDataPort, Straddle.word );
/* Adjust starting pointer and length */
pStart++;
Length--;
#ifdef ALIGMENT_32BIT
while( Length>=2 )
{
/* fetch 16 bits, 8 bits at a time */
Straddle.byte[0] = *(UCHAR *)pStart++;
Straddle.byte[1] = *(UCHAR *)pStart++;
/* Write the word which straddles the mbufs to the chip */
if ( pCS->InMemoryMode )
*pFrame++ = Straddle.word;
else
SYS_ENET_OUT_WORD( TxDataPort, Straddle.word );
Length -= 2;
}
#endif
}
/* Point pBuff to the correct starting point */
pBuff = (USHORT *)pStart;
/* If there are odd bytes remaining in the mbuf */
if ( Length & 1 )
{
HaveExtraByte = TRUE;
/* Point pBuffLimit to the extra byte */
pBuffLimit = (USHORT *)(pStart+Length-1);
}
else /* There is an even number of bytes remaining */
{
HaveExtraByte = FALSE;
/* Point pBuffLimit to just beyond the last word */
pBuffLimit = (USHORT *)(pStart+Length);
}
/* Copy the words in the mbuf to the chip */
if ( pCS->InMemoryMode )
{
while ( pBuff < pBuffLimit )
*pFrame++ = *pBuff++;
}
else
{
while ( pBuff < pBuffLimit )
SYS_ENET_OUT_WORD( TxDataPort, *pBuff++ );
}
/* If there is an extra byte left over in this mbuf */
if ( HaveExtraByte )
{
/* Save the extra byte for later */
Straddle.byte[0] = *(UCHAR *)pBuff;
}
} /* end Process the chain of mbufs */
/* If there is an extra byte left over from the last mbuf */
if ( HaveExtraByte )
{
/* Add a zero byte to make a word */
Straddle.byte[1] = 0;
/* Write the last word to the chip */
if ( pCS->InMemoryMode )
*pFrame = Straddle.word;
else
SYS_ENET_OUT_WORD( TxDataPort, Straddle.word );
}
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* Receive-related Routines *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*******************************************************************************
*
* csCopyRxFrame -
*
* This routine copies a received frame from the chip to a receive buffer.
*
*/
LOCAL void csCopyRxFrame( CS_SOFTC *pCS, PRXBUF pRxBuff )
{
FAST USHORT *pFrame;
FAST USHORT *pBuff;
FAST USHORT *pBuffLimit;
FAST int RxDataPort;
USHORT RxLength, RxStatus;
/* Initialize the frame pointer and data port address */
pFrame = pCS->pPacketPage + (PKTPG_RX_LENGTH/2);
RxDataPort = pCS->IOAddr + PORT_RXTX_DATA;
/* Get the length of the received frame */
if ( pCS->InMemoryMode )
{
RxLength = *pFrame++;
pRxBuff->Length = BYTE_SWAP( RxLength );
}
else /* In IO mode */
{
RxStatus = SYS_ENET_IN_WORD( RxDataPort ); /* Discard RxStatus */
RxLength = SYS_ENET_IN_WORD( RxDataPort );
pRxBuff->Length = BYTE_SWAP( RxLength );
}
/* Setup pointers to the buffer for copying */
pBuff = (USHORT *)pRxBuff->Data;
pBuffLimit = pBuff + ((pRxBuff->Length+1)/2);
/* Copy the frame from the chip to the buffer */
if ( pCS->InMemoryMode )
{
while ( pBuff < pBuffLimit )
*pBuff++ = *pFrame++;
}
else
{
while ( pBuff < pBuffLimit )
*pBuff++ = SYS_ENET_IN_WORD( RxDataPort );
}
}
/*******************************************************************************
*
* csProcessReceive -
*
* This routine processes a received packet. The received packet was copied to
* a receive buffer at interrupt time and this routine processses the receive
* buffer at task time via netTask().
*
* If a recieve hook routine is specified, then the packet is given to the
* hook routine for processing. If the received packet does not use trailers
* and the packet is large, then a cluster mbuf is built that points to the
* receive buffer directly. If a cluster mbuf is not used, then the packet
* is copied to an mbuf chain. The cluster mbuf or mbuf chain is then passed
* up to the protocol stack.
*
*/
LOCAL void csProcessReceive( CS_SOFTC *pCS, PRXBUF pRxBuff )
{
struct ifnet *pIf;
struct mbuf *pMbufChain;
struct ether_header *pEtherHeader;
UCHAR *pData;
int DataLength;
int Spl;
#ifdef BSD43_DRIVER
int TrailerOffset;
USHORT Type;
#endif /* BSD43_DRIVER */
pIf = &pCS->ArpCom.ac_if;
/*pIf->if_ipackets++;*/
/* If a hook routine is specified */
if ( etherInputHookRtn != NULL )
{
/* Call the hook routine */
if ( (*etherInputHookRtn)(pIf,pRxBuff->Data,pRxBuff->Length) != 0 )
{
/* The hook routine has handled the received frame */
csFreeRxBuff( pCS, pRxBuff );
return;
}
}
/* Setup working variables */
pEtherHeader = (struct ether_header *)pRxBuff->Data;
pData = &pRxBuff->Data[SIZEOF_ETHERHEADER];
DataLength = pRxBuff->Length - SIZEOF_ETHERHEADER;
#ifdef BSD43_DRIVER
/* Check if the received frame uses trailers */
check_trailer( pEtherHeader, pData, &DataLength, &TrailerOffset, pIf );
/* Save the type because build_cluster() will overwrite it */
Type = pEtherHeader->ether_type;
#endif
#if (CPU_FAMILY != MIPS )
/* Current VxWorks build_cluster routine causes a bus fault with the MIPS
* processor. Likely due to an addressing violation.
*/
#ifdef BSD43_DRIVER
/* If trailers are not used and there is enough data for clustering */
if ( (TrailerOffset==0) && USE_CLUSTER(DataLength) )
#else
if ( USE_CLUSTER(DataLength) )
#endif /* BSD43_DRIVER */
{
/* Build a cluster mbuf that points to my receive buffer */
Spl = splnet( );
pMbufChain = build_cluster( pData, DataLength, pIf, MC_LOANED,
&pRxBuff->RefCount, (FUNCPTR)csFreeRxBuff, (int)pCS, (int)pRxBuff, 0 );
splx( Spl );
if ( pMbufChain != NULL )
{
pRxBuff->Status = RXBUF_LOANED;
pCS->LoanCount++;
}
else
{
csFreeRxBuff( pCS, pRxBuff );
}
}
else /* Can not do clustering */
#endif
{
/* Copy the received data to a chain of mbufs */
Spl = splnet( );
#ifdef BSD43_DRIVER
pMbufChain = copy_to_mbufs( pData, DataLength, TrailerOffset, pIf );
#else
pMbufChain = copy_to_mbufs( pData, DataLength, 0, pIf ); /*Cannot use Trailer*/
#endif
splx( Spl );
csFreeRxBuff( pCS, pRxBuff );
}
/* If could not get an mbuf */
if ( pMbufChain == NULL )
{
pIf->if_ierrors++;
LOGMSG( "csProcessReceive: unit %d, No receive mbuf available\n",
pCS->ArpCom.ac_if.if_unit, 0,0,0,0,0 );
return;
}
/* Pass the mbuf chain up to the protocol stack */
Spl = splnet( );
/* @kml */
pIf->if_ipackets++;
#ifdef BSD43_DRIVER
do_protocol_with_type(Type, pMbufChain, &pCS->ArpCom, DataLength);
#else /* BSD4.4 DRIVER */
do_protocol(pEtherHeader, pMbufChain, &pCS->ArpCom, DataLength);
#endif /* BSD4.4 DRIVER */
splx( Spl );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -