📄 csend.c
字号:
/* 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)
{
LOGMSG("receive buffer not on half word boundary: %x\n", (int)pBuff,0,0,0,0,0);
}
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 *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*******************************************************************************
* csInitQueue -
*
* Initializes an array-implemented circular queue.
*
* RETURNS: Nothing.
*
*/
LOCAL void csInitQueue( CIR_QUEUE *Q )
{
Q->Head = Q->Tail = 0;
}
/*******************************************************************************
* csQueueEmpty -
*
* Checks the queue's status.
*
* RETURNS: TRUE if queue is empty, FALSE if queue is not empty.
*
*/
LOCAL BOOL csQueueEmpty( CIR_QUEUE *Q )
{
if( Q->Head == Q->Tail )
return TRUE; /* Queue is empty */
else
return FALSE;
}
/*******************************************************************************
* csDequeue -
*
* This routine removes a pointer to a value from the end off an
* array-implemented circular queue. Assumes the queue is not empty.
*
* RETURNS: Pointer to the dequeued value.
*
*/
LOCAL void *csDequeue( CIR_QUEUE *Q )
{
FAST void *Element;
Element = Q->Queue[Q->Head];
Q->Head = (Q->Head == CS_QUEUE_SIZE) ? 0 : (Q->Head + 1);
return Element;
}
/*******************************************************************************
* csEnqueue -
*
* This routine adds a pointer to a value to the front of an array-implmented
* circular queue.
*
* RETURNS: OK, or ERROR if the enqueue would cause a queue overflow.
*
*/
LOCAL STATUS csEnqueue( CIR_QUEUE *Q, void *pBuff )
{
/* If queue is full return ERROR */
if ( Q->Tail == ((Q->Head == 0) ? CS_QUEUE_SIZE : (Q->Head -1)) )
{
LOGMSG("csEnqueue: CS_END_DEVICE %d, Queue Overflow\n",
0,0,0,0,0,0 );
return ERROR; /* Queue overflow */
}
/* Else, add data to the queue and return OK */
Q->Queue[Q->Tail] = pBuff;
Q->Tail = (Q->Tail == CS_QUEUE_SIZE) ? 0 : (Q->Tail + 1);
return OK;
}
/*******************************************************************************
*
* csInitChip -
*
* This routine uses the instance global variables in the CS_END_DEVICE structure to
* initialize the CS8900.
*
*/
LOCAL void csInitChip( CS_END_DEVICE *pCS )
{
PIA pIA;
USHORT RxCtl;
int i;
/* Configure the adapter for board-specific IO and media type support */
sysEnetHWInit( pCS );
/* Initialize the config and control registers */
csWritePacketPage( pCS, PKTPG_RX_CFG, RX_CFG_ALL_IE );
csWritePacketPage( pCS, PKTPG_RX_CTL,
(RX_CTL_RX_OK_A|RX_CTL_IND_A|RX_CTL_BCAST_A|RX_CTL_MCAST_A));
csWritePacketPage( pCS, PKTPG_TX_CFG, TX_CFG_ALL_IE );
csWritePacketPage( pCS, PKTPG_BUF_CFG, BUF_CFG_ALL_IE );
/* Put Ethernet address into the Individual Address register */
pIA = (PIA)pCS->enetAddr;
csWritePacketPage( pCS, PKTPG_IND_ADDR, pIA->word[0] );
csWritePacketPage( pCS, PKTPG_IND_ADDR+2, pIA->word[1] );
csWritePacketPage( pCS, PKTPG_IND_ADDR+4, pIA->word[2] );
/* Set the interrupt level in the chip */
if ( pCS->IntLevel == 5 )
csWritePacketPage( pCS, PKTPG_INT_NUM, BYTE_SWAP(3) );
else
csWritePacketPage( pCS, PKTPG_INT_NUM, BYTE_SWAP( (pCS->IntLevel)-10 ) );
/* @kml If need to enable the promiscuous mode */
if ( pCS->ConfigFlags & CFGFLG_PROMISC_MODE ) {
RxCtl=csRe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -