📄 cs8950.c
字号:
/* Initialize the Receive Control register */
//********************************************************************
// From EP9312 errata
//
// Description:
// The ethernet Mac does not correctly receive frames that have a
// size of 64 bytes.
//
// Workaround:
// In order to receive frames of 64 bytes, enable the RCRCA bit in
// the RxCTRL register. This will allow the ethernet controller
// to ingore the CRC information and not discard the frames.
//
// The Windows CE ethernet debugger sends lots of frames that are
// 64 bytes in length.
//********************************************************************
WriteDWord( OpReg_RxCTL, RxCTL_SerRxON | RxCTL_RuntCRCA );
/* Initialize the filtering criteria */
VchipChangeFiltering(FILTER_INDIVIDUAL_ACCEPT | FILTER_BROADCAST_ACCEPT);
/* WriteByte(OpReg_SelfCTL, ReadByte( OpReg_SelfCTL)| SelfCTL_MIILoopback);*/
return MAC_SUCCESSFUL;
}
/******************************************************************************
*
* VchipReset()
*
******************************************************************************/
static WORD VchipReset( PCHIP pChip )
{
volatile BYTE Status;
int x;
/* Reset the chip */
WriteByte( OpReg_SelfCTL, SelfCTL_RESET );
/* Wait until the reset is complete */
for ( x=0; x<MAXLOOP; x++ )
{
Status=ReadByte( OpReg_SelfCTL);
if ( !(Status & SelfCTL_RESET) )
break;
}
if ( x == MAXLOOP )
{
EdbgOutputDebugString("The CS Chip reset does not complete!\r\n");
return MAC_FAILED;
}
return MAC_SUCCESSFUL;
}
/******************************************************************************
*
* ResetQueues()
*
******************************************************************************/
static void ResetQueues( PCHIP pChip )
{
PCD pCD;
RxDesc_t *pRxDesc;
RxStat_t *pRxStat;
TxStat_t *pTxStat;
pCD = (PCD)pChip->pData;
/* Set receive descriptor queue current address to the base address */
WriteDWord( OpReg_RxDCA, pCD->RxDescPhysAddr );
/* Set receive status queue current address to the base address */
WriteDWord( OpReg_RxSCA, pCD->RxStatPhysAddr );
/* Set transmit descriptor queue current address to the base address */
WriteDWord( OpReg_TxDCA, pCD->TxDescPhysAddr );
/* Set transmit status queue current address to the base address */
WriteDWord( OpReg_TxSCA, pCD->TxStatPhysAddr );
/* Set the queue pointers to be beginning of the queues */
pCD->pRxStatNext = pCD->pRxStat;
pCD->pTxStatNext = pCD->pTxStat;
pCD->pTxDescNext = pCD->pTxDesc;
/* No Tx frames that have been euqueued but Tx status haven't been processed yet. */
pCD->TxQueueDepth=0;
/* No frames have been transmitted (without underruns) yet */
pCD->TxGoodCount = 0;
/* Start filling in the transmit request table at index zero */
pCD->TxReqIndex = 0;
/* All the transmit descriptors are available */
pCD->TxDescAvail = TXDESCCOUNT;
/* Set all the receive descriptors to available (not held) */
for ( pRxDesc=pCD->pRxDesc; pRxDesc<pCD->pRxDescLimit; pRxDesc++ )
pRxDesc->BufLength = RXBUFFSIZE;
/* Clear all the Frame Processed flags in the receive status queue */
for ( pRxStat=pCD->pRxStat; pRxStat<pCD->pRxStatLimit; pRxStat++ )
pRxStat->RxStat = 0;
/* Clear all the Frame Processed flags in the transmit status queue */
for ( pTxStat=pCD->pTxStat; pTxStat<pCD->pTxStatLimit; pTxStat++ )
pTxStat->TxStat = 0;
}
/******************************************************************************
*
* VchipChangeFiltering()
*
******************************************************************************/
static void VchipChangeFiltering(unsigned int uiFilteringOpts)
{
DWORD RxControl;
/* Get the current settings of the receiver control register */
RxControl=ReadDWord( OpReg_RxCTL);
/* Turn off the receiver while changing the filtering criteria */
WriteDWord( OpReg_RxCTL, RxControl & ~RxCTL_SerRxON );
/* Clear all of the accept bits */
RxControl &= ~(RxCTL_IndividualAccept0 | RxCTL_BroadcastA |
RxCTL_MulticastA | RxCTL_PromiscuousA);
/* Set only the specified accept bits */
if (uiFilteringOpts & FILTER_INDIVIDUAL_ACCEPT )
RxControl |= RxCTL_IndividualAccept0;
if (uiFilteringOpts & FILTER_BROADCAST_ACCEPT )
RxControl |= RxCTL_BroadcastA;
if (uiFilteringOpts & FILTER_MULTICAST_ACCEPT )
RxControl |= RxCTL_MulticastA;
if (uiFilteringOpts & FILTER_PROMISCUOUS_ACCEPT )
RxControl |= RxCTL_PromiscuousA;
/* Write the new filtering criteria to the chip and turn receiver back on */
WriteDWord( OpReg_RxCTL, RxControl );
}
/******************************************************************************
*
* VpsRecvError(()
*
******************************************************************************/
static void VpsRecvError( PCHIP pChip, WORD Errors )
{
Global_RxNotOkCnt++;
// Keep track of OKs, Errors and confirm packet if necessary
//if (Errors & RX_ERR_CRC_ERROR){
// EdbgOutputDebugString("VpsRecvError(): RX_ERR_CRC_ERROR\n");
//}
if (Errors & RX_ERR_EXTRA_DATA)
{
EdbgOutputDebugString("VpsRecvError(): RX_ERR_EXTRA_DATA\n");
}
if (Errors & RX_ERR_RUNT)
{
EdbgOutputDebugString("VpsRecvError(): RX_ERR_RUNT\n");
}
if (Errors & RX_ERR_FRAMING)
{
EdbgOutputDebugString("VpsRecvError(): RX_ERR_FRAMING\n");
}
if (Errors & RX_ERR_OVERRUN)
{
EdbgOutputDebugString("VpsRecvError(): RX_ERR_OVERRUN\n");
}
if (Errors & RX_ERR_RX_ERR)
{
EdbgOutputDebugString("VpsRecvError(): RX_ERR_RX_ERR\n");
}
if (Errors & RX_ERR_RX_MISS)
{
EdbgOutputDebugString("VpsRecvError(): RX_ERR_RX_MISS\n");
}
if (Errors & RX_ERR_DRIBBLE)
{
EdbgOutputDebugString("VpsRecvError(): RX_ERR_DRIBBLE\n");
}
if (Errors & RX_ERR_TOO_MANY_FRAGS)
{
EdbgOutputDebugString("VpsRecvError(): RX_ERR_TOO_MANY_FRAGS\n");
}
if (Errors & RX_ERR_NO_BUFFER)
{
EdbgOutputDebugString("VpsRecvError(): RX_ERR_NO_BUFFER\n");
}
}
/******************************************************************************
*
* ProcessTxStatusQueue()
*
******************************************************************************/
static int ProcessTxStatusQueue( PCHIP pChip )
{
PCD pCD;
volatile WORD Status;
PTXREQ pTxReq;
unsigned int loopCnt=0;
pCD = (PCD)pChip->pData;
/* While the transmit status entry is not processed */
while ( 1 )
{
Status=pCD->pTxStatNext->TxStat;
if (Status & TxStat_TxFP )
{
break; //break the while loop
} //end if
/* 02/14/02 @melody It doesn't matter whether Suicide bit is set or not.
if(ReadDWord( OpReg_MacCfg0) & 0x00000008)
{
EdbgOutputDebugString("ProcessTxStatusQueue: Suicide bit has turned on!\r\n");
DumpRegisters();
}
*/
loopCnt++;
DelayInuSec(1);
if ( loopCnt > 90000 )
{
EdbgOutputDebugString("CS8950 ProcessTxStatusQueue(): Error Tx not complete!\n");
return FALSE;
}
}//end while
/* Find the associated transmit request */
pTxReq = &pCD->TxReq[pCD->pTxStatNext->BufIndx];
/* The transmit descriptors for this frame are now available */
pCD->TxDescAvail += pTxReq->DescCount;
/* The transmit status entry is now processed */
pCD->pTxStatNext->TxStat = 0;
/* Increment to the next transmit status entry (with wrap-around) */
pCD->pTxStatNext++;
if ( pCD->pTxStatNext == pCD->pTxStatLimit )
pCD->pTxStatNext = pCD->pTxStat;
pCD->TxQueueDepth--;
if (pCD->TxQueueDepth < 0 ) {
EdbgOutputDebugString(
"CS8950 ProcessTxStatusQueue(): Error TxQueueDepth is less than 0!\n");
}
/* If the frame was not sent without errors */
if ( !(Status & TxStat_TxWE) )
{
/* Report the errors */
VpsSendError( pChip, (WORD)(Status&TxStat_Error_Mask));
return FALSE;
}
else
{
/* Another frame has been transmitted without an error */
pCD->TxGoodCount++;
Global_TxOkCnt++;
}
return TRUE;
}
//****************************************************************************
// AvaliableRecieveBuffers
//****************************************************************************
//
//
//
static ULONG AvaliableRecieveBuffers(void)
{
ULONG ulCount;
ULONG ulAvailable = 0;
for(ulCount = 0; ulCount < RXSTATCOUNT ; ulCount++)
{
if(!pCS8950Buffer->RxStat[ulCount].RxStat)
{
ulAvailable++;
}
}
return ulAvailable;
}
/******************************************************************************
*
* VpsSendError(()
*
******************************************************************************/
static void VpsSendError( PCHIP pChip, WORD Errors )
{
Global_TxNotOkCnt++;
if (Errors & TX_ERR_EXCESS_COLL){
EdbgOutputDebugString("VpsSendError(): TX_ERR_EXCESS_COLL!\n");
}
if (Errors & TX_ERR_UNDERRUN){
EdbgOutputDebugString("VpsSendError(): TX_ERR_UNDERRUN!\n");
}
if (Errors & TX_ERR_LOSS_CRS){
EdbgOutputDebugString("VpsSendError(): TX_ERR_EXCESS_LOSS_CRS!\n");
}
}
/******************************************************************************
*
* VchipSend()
*
* The return code indicates if the VCHIP held on the the transmit buffers.
* If the return code is MAC_SUCCESSFUL, then the VCHIP held on to the transmit buffers
* and the VPS can not reuse the buffers until the VCHIP calls the
* ChipFreeSendBuff() routine. If the return code is MAC_FAILED, then the VCHIP
* did not hold on to the transmit buffers and the VPS may immediately reuse
* them.
*
******************************************************************************/
static void VchipSend( PCHIP pChip, WORD TotalLength, BYTE *pBuff )
{
PCD pCD;
PTXREQ pTxReq;
WORD DescCount;
TxDesc_t *pTxDesc;
BYTE *pTxBuff;
//EdbgOutputDebugString
//(
// "VchipSend pChip = 0x%x, TotalLength = 0x%x, pBuff = 0x%x \r\n",
// (ULONG)pChip,
// (ULONG)TotalLength,
// (ULONG)pBuff
//);
pCD = (PCD)pChip->pData;
pTxDesc= pCD->pTxDescNext;
/* Only one transmit descriptor is used */
DescCount=1;
/* Fill in the transmit descriptor */
pTxDesc->TxBufAdr = pCD->TxBuff[pCD->TxReqIndex].PhysAddr;
pTxDesc->BufLength = TotalLength;
pTxDesc->BufIndx = pCD->TxReqIndex;
/* Start copying at the beginning of the next transmit buffer */
pTxBuff = pCD->TxBuff[pCD->TxReqIndex].pBuff;
/* Copy the contents of the data buffers to the transmit buffer */
memcpy( pTxBuff, pBuff,TotalLength );
/* Increment to the next transmit descriptor (with wrap-around) */
pTxDesc++;
if ( pTxDesc == pCD->pTxDescLimit )
pTxDesc = pCD->pTxDesc;
/* Save the transmit request in the transmit request table */
pTxReq = &pCD->TxReq[pCD->TxReqIndex];
pTxReq->StartIndex = (WORD)(pCD->pTxDescNext - pCD->pTxDesc);
pTxReq->DescCount = DescCount;
/* Increment to the next entry in the transmit request table */
pCD->TxReqIndex++;
if ( pCD->TxReqIndex == TXREQCOUNT )
pCD->TxReqIndex = 0;
/* Update the pointer to the next transmit descriptor */
pCD->pTxDescNext = pTxDesc;
/* Update the number of transmit descriptors available */
pCD->TxDescAvail -= DescCount;
/* Set the End-of-Frame bit in the last transmit descriptor */
if ( pTxDesc == pCD->pTxDesc )
pTxDesc = pCD->pTxDescLimit;
pTxDesc--;
pTxDesc->BufIndx |= TxDesc_EOF;
/* The number of Tx frames enqueued but needs to process statuses.*/
pCD->TxQueueDepth++;
if (pCD->TxQueueDepth > TXBUFFCOUNT )
{
EdbgOutputDebugString
(
"CS8950 VchipSend(): Error TxQueueDepth is larger than TXBUFFCOUNT!\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -