?? csend.c
字號:
/* Bid for space on the chip and start the TX if bid successful */
if ( pCS->InMemoryMode )
{
csWritePacketPage( pCS, PKTPG_TX_CMD, pCS->TxStartCMD );
csWritePacketPage( pCS, PKTPG_TX_LENGTH, BYTE_SWAP(pCS->TxLength) );
}
else /* In IO mode */
{
SYS_ENET_OUT_WORD( (pCS->IOAddr)+PORT_TX_CMD, pCS->TxStartCMD );
SYS_ENET_OUT_WORD( (pCS->IOAddr)+PORT_TX_LENGTH,
BYTE_SWAP(pCS->TxLength));
}
/* Read BusStatus register which indicates success of the request */
BusStatus = csReadPacketPage( pCS, PKTPG_BUS_ST );
if ( BusStatus & BUS_ST_RDY4TXNOW )
{
/* The chip is ready for transmission now */
/* Copy the frame to the chip to start transmission */
csCopyTxFrame( pCS, pCS->pTxFrameChain );
/* Mark TX as in progress */
pCS->TxInProgress = TRUE;
/* Transmission now in progress */
if ( !pCS->InISR )
{
/* Re-enable interrupts at the CPU */
INT_UNLOCK( State );
}
break;
}
else /* Not ready for TX */
{
/* 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 */
INT_UNLOCK( State );
/* Free the bad mbuf chain */
netMblkClChainFree (pMbuf);
}
else
{
/* queue the mbuf chain to be freed at task level */
csEnqueue( pCS->pTxBuffFreeList, pMbuf );
}
/* Update output stats */
END_ERR_ADD (&pCS->end, MIB2_OUT_ERRS, +1);
/* END_ERR_ADD (&pCS->end, MIB2_OUT_UCAST, -1);*/
/* @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."*/
#ifdef CS_DEBUG_ENABLE
logMsg("csStartOutput: CS_END_DEVICE %d, Transmit bid error (too big)\n",
pCS->unit, 0,0,0,0,0 );
#endif
/* Loop up to transmit the next chain */
}
else /* Not Rdy4Tx and Not Bid Error */
{
/* Start the TX on Rdy4Tx interrupt */
/* TX buff space not available now. */
/* Mark TX as in progress */
pCS->TxInProgress = TRUE;
/* Re-enable interrupts at the CPU */
INT_UNLOCK( 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_END_DEVICE *pCS, M_BLK_ID pMbufChain )
{
M_BLK_ID 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;
pFrame += (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->mBlkHdr.mNext )
{
/* Setup starting pointer and length */
pStart = pMbuf->mBlkHdr.mData;
Length = pMbuf->mBlkHdr.mLen;
#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 )
{
#if CPU_FAMILY == ARM
SYS_ENET_OUT_WORD(pFrame++, Straddle.word);
#else
*pFrame++ = Straddle.word;
#endif
}
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 )
{
#if CPU_FAMILY == ARM
SYS_ENET_OUT_WORD(pFrame++, Straddle.word);
#else
*pFrame++ = Straddle.word;
#endif
}
else
SYS_ENET_OUT_WORD( TxDataPort, Straddle.word );
Length -= 2;
}
}
}
#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 )
{
#if CPU_FAMILY == ARM
SYS_ENET_OUT_WORD(pFrame++, Straddle.word);
#else
*pFrame++ = Straddle.word;
#endif
}
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 )
{
#if CPU_FAMILY == ARM
SYS_ENET_OUT_WORD(pFrame++, Straddle.word);
#else
*pFrame++ = Straddle.word;
#endif
}
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 )
{
#if CPU_FAMILY == ARM
SYS_ENET_OUT_WORD(pFrame++, *pBuff++);
#else
*pFrame++ = *pBuff++;
#endif
}
}
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 )
{
#if CPU_FAMILY == ARM
SYS_ENET_OUT_WORD(pFrame++, Straddle.word);
#else
*pFrame++ = Straddle.word;
#endif
}
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 int csCopyRxFrame( CS_END_DEVICE *pCS, char *pRxBuff )
{
FAST USHORT *pFrame;
FAST USHORT *pBuff;
FAST USHORT *pBuffLimit;
FAST int RxDataPort;
USHORT RxLength, RxStatus;
int test_int;
/* Initialize the frame pointer and data port address */
pFrame = pCS->pPacketPage;
pFrame += (PKTPG_RX_LENGTH/2);
RxDataPort = pCS->IOAddr + PORT_RXTX_DATA;
/* Get the length of the received frame */
if ( pCS->InMemoryMode )
{
#if CPU_FAMILY == ARM
RxLength = SYS_ENET_IN_WORD(pFrame++);
#else
RxLength = *pFrame++;
#endif
RxLength = BYTE_SWAP( RxLength );
}
else /* In IO mode */
{
RxStatus = SYS_ENET_IN_WORD( RxDataPort ); /* Discard RxStatus */
RxLength = SYS_ENET_IN_WORD( RxDataPort );
RxLength = BYTE_SWAP( RxLength );
}
/* Setup pointers to the buffer for copying */
pBuff = (USHORT *)pRxBuff;
test_int = (int) pBuff;
if ((test_int % 2) != 0)
{
#ifdef CS_DEBUG_ENABLE
logMsg("receive buffer not on half word boundary: %x\n", (int)pBuff,0,0,0,0,0);
#endif
}
pBuffLimit = pBuff;
pBuffLimit += ((RxLength+1)/2);
/* Copy the frame from the chip to the buffer */
if ( pCS->InMemoryMode )
{
while ( pBuff < pBuffLimit )
#if CPU_FAMILY == ARM
*pBuff++ = SYS_ENET_IN_WORD(pFrame++);
#else
*pBuff++ = *pFrame++;
#endif
}
else
{
while ( pBuff < pBuffLimit )
*pBuff++ = SYS_ENET_IN_WORD( RxDataPort );
}
return (RxLength);
}
/*******************************************************************************
*
* 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().
*
* The packet is copied to an mbuf chain. The mbuf chain is then
* passed up to the protocol stack.
*
*/
LOCAL void csProcessReceive( CS_END_DEVICE *pCS, M_BLK_ID pMBuff )
{
/* Spl = splnet( );*/
/* Update the MIB2 Static */
END_ERR_ADD (&pCS->end, MIB2_IN_UCAST, +1);
/* Pass the mbuf chain up to the protocol stack */
/* Call the upper layer's receive routine. */
END_RCV_RTN_CALL(&pCS->end, pMBuff);
/* splx( Spl ); */
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* Misc. Routines
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -