📄 vchip8950.c
字号:
DWORD Status;
WORD moreRxFrames=1;
BOOL IDidSomething=FALSE;
/* Read and clear the interrupt status */
Status = ReadDWord( OpReg_IntStsC);
while ( Status != 0L )
{
IDidSomething=TRUE;
if ( Status & IntSts_RxStsQ )
{
while (moreRxFrames)
{
moreRxFrames=ProcessRxStatusQueue( pChip );
}
}
if ( Status & IntSts_TxStsQ )
{
ProcessTxStatusQueue( pChip );
}
/* Read and clear the interrupt status again */
Status = ReadDWord(OpReg_IntStsC);
}
return IDidSomething;
}
/******************************************************************************
*
* ProcessRxStatusQueue()
*
******************************************************************************/
static WORD ProcessRxStatusQueue( PCHIP pChip )
{
PCD pCD;
RxStat_t * volatile pRxStat;
WORD freeIndex;
WORD bufIndex;
WORD enqIndex;
WORD TotalLength;
WORD Errors;
int LoopCount=0;
volatile DWORD Status;
static int TotalRx=0;
PNDIS_PACKET PacketArray[FREE_RX_PKT_CNT];
PNDIS_BUFFER pNdisBuffer;
WORD PacketArrayCount=0;
WORD numTobeEnQ=0;
WORD enableResource=0;
WORD i, j;
WORD moreRxFrames=0;
PVPMINIPDATA pvMini_Context = (PVPMINIPDATA)(pChip->pPSD);
NDIS_HANDLE MiniportAdapterHandle = pvMini_Context->vpMiniportAdapterHandle;
pCD = pChip->pData;
// enqIndex= ((unsigned long)(pCD->pRxStatNext) - (unsigned long)(pCD->pRxStat))/sizeof(RxDesc_t);
enqIndex = pCD->RxIndex;
//RETAILMSG(1,( L"\r\n ==== ProcessRxStatusQueue() Begin. enqIndes=%d ====\r\n",enqIndex ));
//RETAILMSG(1,( L" Begin. RxIndex=0x%x pRxStatNext=0x%x\r\n", pCD->RxIndex, (unsigned long)(pCD->pRxStatNext), (unsigned long)(pCD->pRxStat) ));
/* No receive descriptors have been processed yet */
// DescCount = 0;
/* While the receive status entry is not processed */
while ( pCD->pRxStatNext->RxStat & RxStat_RxFP )
{
if ( numTobeEnQ >= RXBUFFCOUNT/2 )
{ moreRxFrames=1;
//RETAILMSG(1,( L" S1 numTobeEnQ=%d \r\n",numTobeEnQ ));
break;
}
pRxStat = pCD->pRxStatNext;
/* Software Workaround for second DWORD of RxStatus remaining invalid */
while ((pRxStat->BufIndx & RxStat_RFP) != RxStat_RFP)
{
/* Make sure length and index are valid */
if (LoopCount++ > 0x256)
break;
}
/* End of Software Workaround */
/* Get a deferenced copy of the status */
Status = pRxStat->RxStat;
/* Get the index of the buffer that contains the frame data */
bufIndex = (WORD)(pRxStat->BufIndx & RxStat_BufIndx_Mask);
//RETAILMSG(1,( L" S2 BufIndex=%d\r\n", bufIndex));
/* Get the total length of the frame */
TotalLength = pRxStat->FrameLength;
//RETAILMSG(1,( L" S3 TotalLength=%d\r\n", TotalLength ));
/* If the received frame has errors */
if ( !(Status & RxStat_RxWE) )
{
Errors = (WORD)((Status & RxStat_Error_Mask) >> 16);
VpsRecvError( pChip, Errors );
TotalLength = 0; // 0 means a frame with error. */
//Change BufLength to 0 so we know to reuse the buffer when enq the RxDesc.
((pCD->pRxDesc) + (pCD->RxIndex))->BufLength=0x0;
//RETAILMSG(1,( L" S4 Errors=0x%x \r\n",Errors ));
}
if ( TotalLength )
{
/* Put the address of the fragment buffer into the fragment array */
//pCD->RxFrag[0].pBuffer = pCD->RxBuff[Index].pBuff;
//pCD->RxFrag[0].BuffLength = TotalLength;
/* Pass the received frame up to the protocol stack */
//VpsRecvComplete( pChip, TotalLength, 1, pCD->RxFrag );
PacketArray[PacketArrayCount]=pCD->RxPacketPtQ[bufIndex];
pNdisBuffer = pCD->RxBuffPtQ[bufIndex];
/* Adjust the buffer length in the NDIS_BUFFER */
NdisAdjustBufferLength( pNdisBuffer, TotalLength);
PacketArrayCount++;
//RETAILMSG(1,( L" S5 PacketArrayCount=%d\r\n", PacketArrayCount));
}
/* Increment to the next receive status entry (with wrap-around) */
pCD->pRxStatNext++;
if ( pCD->pRxStatNext == pCD->pRxStatLimit )
{
pCD->pRxStatNext = pCD->pRxStat;
}
pCD->RxIndex++;
if (pCD->RxIndex == RXBUFFCOUNT)
{
pCD->RxIndex=0;
}
numTobeEnQ++;
//RETAILMSG(1,( L" S6 numTobeEnQ=0x%x RxIndex=%d\r\n", numTobeEnQ, pCD->RxIndex ));
} //End while()
if ( PacketArrayCount > pCD->numRxFreePackets )
{ //No enough Free Packets avail, enableResource.
enableResource=1;
//RETAILMSG(1,( L" S7 enableResource=1\r\n" ));
for (i=0; i<PacketArrayCount; i++)
{
/* indicate STATUS_RESOURCES, so that the ownership of the
* NDIS packet will be immediately handed back to the driver.
* i.e. NDIS copies data from driver's buffer to its own buffer.
*/
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_RESOURCES);
}
j=enqIndex;
for (i=0; i<numTobeEnQ; i++)
{ //Mark BufLength=0 so we know we can reuse the buffer immediately.
(pCD->pRxDesc+j)->BufLength = 0;
j++;
if (j == RXBUFFCOUNT)
{
j=0;
}
}
} else {
for (i=0; i<PacketArrayCount; i++)
{
/* indicate STATUS_SUCCESS, so that the ownership of the
* NDIS packet will be NDIS (the upper layer).
* NDIS won't copies data from driver's buffer to its buffer.
* NDIS returns this buffer to driver after the user application
* has finished reading the buffer.
*/
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
}
pCD->numNdisPacketsIndicated += PacketArrayCount;
// RETAILMSG(1,( L" S8 End numNdisPacketsIndicated=%d\r\n", pCD->numNdisPacketsIndicated));
} //end if
NdisMIndicateReceivePacket(MiniportAdapterHandle,
PacketArray,
PacketArrayCount);
// RETAILMSG(1,( L" S9 End PacketArrayCount=%d\r\n", PacketArrayCount));
for (i=0; i<numTobeEnQ; i++)
{
if ((pCD->pRxDesc+enqIndex)->BufLength != 0)
{ //The buffer is hold by NDIS. Cannot Reuse it
// Get the index of a Free packet from RxFreeQueue.
freeIndex=GetTheIndexOfAFreePakcet(pChip);
// RETAILMSG(1,( L"ProcessRxStatusQueue() End freeIndex=0x%x\r\n", freeIndex));
/* Initialize the Receive Descriptor */
(pCD->pRxDesc+enqIndex)->RxBufAdr = pCD->RxBuff[freeIndex].PhysAddr;
(pCD->pRxDesc+enqIndex)->BufIndx = freeIndex;
}
/* Mark the buffer as now available */
(pCD->pRxDesc+enqIndex)->BufLength = RXBUFFSIZE;
/* The receive status entry is now processed */
(pCD->pRxStat+enqIndex)->RxStat = 0;
(pCD->pRxStat+enqIndex)->BufIndx = 0;
(pCD->pRxStat+enqIndex)->FrameLength = 0x0;
/* Enqueue the number of receive descriptors processed to the chip */
WriteDWord( OpReg_RxDEQ, 1);
/* Enqueue the number of receive status entries processed to the chip */
WriteDWord( OpReg_RxSEQ, 1 );
enqIndex++;
if (enqIndex == RXBUFFCOUNT)
{
enqIndex=0;
}
//RETAILMSG(1,( L" S10 Next enqIndex=%d\r\n", enqIndex));
}//end for numToBeEnQ
// TotalRx++;
// DbgPrint("CS8950.dll ProcessRxStatusQueue() TotalRx=%d \n", TotalRx);
//RETAILMSG(1,( L"======== End ========\r\n"));
return (moreRxFrames);
}
/******************************************************************************
*
* VpsRecvComplete()
*
******************************************************************************/
static BOOL VpsRecvComplete( PCHIP pChip, WORD TotalLength, WORD FragCount,
PFRAG pFrag)
{
RECEIVE_CONTEXT ReceiveContext;
VPM_SetupMiniContextFromPchip
pvMini_Context->RcvOKs++;
if ((TotalLength < VP_MIN_FRAMESIZE) ||
(TotalLength > VP_MAX_FRAMESIZE))
{
pvMini_Context->RcvErrors++;
return FALSE;
} /* endif */
ReceiveContext.pChip = pChip;
ReceiveContext.FrameSize = (WORD)TotalLength;
ReceiveContext.FragCount = (WORD)FragCount;
ReceiveContext.pFrag = pFrag;
NdisMEthIndicateReceive
(
MiniportAdapterHandle,
(NDIS_HANDLE)&ReceiveContext,
pFrag->pBuffer,
VP_HEADERSIZE,
pFrag->pBuffer+VP_HEADERSIZE,
pFrag->BuffLength-VP_HEADERSIZE,
TotalLength-VP_HEADERSIZE
);
NdisMEthIndicateReceiveComplete( MiniportAdapterHandle );
return FALSE; // Don't hold buffer
}
/******************************************************************************
*
* VpsRecvError(()
*
******************************************************************************/
static void VpsRecvError( PCHIP pChip, WORD Errors )
{
VPM_SetupMiniContextFromPchip;
// Keep track of OKs, Errors and confirm packet if necessary
pvMini_Context->XmitErrors++;
// Keep track of OKs, Errors and confirm packet if necessary
if (Errors & RX_ERR_CRC_ERROR)
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_CRC_ERROR\n"))
);
pvMini_Context->RcvCRCErrors++;
}
if (Errors & RX_ERR_EXTRA_DATA)
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_EXTRA_DATA\n"))
);
}
if (Errors & RX_ERR_RUNT)
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_RUNT\n"))
);
}
if (Errors & RX_ERR_FRAMING)
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_FRAMING\n"))
);
pvMini_Context->RcvErrorAlignments++;
}
if (Errors & RX_ERR_OVERRUN)
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_OVERRUN\n"))
);
pvMini_Context->RcvOverrun++;
}
if (Errors & RX_ERR_RX_ERR)
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_RX_ERR\n"))
);
}
if (Errors & RX_ERR_RX_MISS)
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_RX_MISS\n"))
);
}
if (Errors & RX_ERR_DRIBBLE)
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_DRIBBLE\n"))
);
}
if (Errors & RX_ERR_TOO_MANY_FRAGS)
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_TOO_MANY_FRAGS\n"))
);
}
if ( Errors & RX_ERR_NO_BUFFER )
{
DEBUGMSG
(
ZONE_RECVERROR,
(TEXT("VpsRecvError(): RX_ERR_NO_BUFFER\n"))
);
pvMini_Context->RcvNoBuffers++;
}
}
/******************************************************************************
*
* ProcessTxStatusQueue()
*
******************************************************************************/
void ProcessTxStatusQueue( PCHIP pChip )
{
PCD pCD;
WORD Status;
MAXFL MaxFL;
PTXREQ pTxReq;
pCD = pChip->pData;
/* While the transmit status entry is not processed */
while ( pCD->pTxStatNext->TxStat & TxStat_TxFP )
{
/* Get a derefrenced copy of the status */
Status = pCD->pTxStatNext->TxStat;
/* Find the associated transmit request */
pTxReq = &pCD->TxReq[pCD->pTxStatNext->BufIndx];
/* If the frame was not sent without errors */
if ( !(Status & TxStat_TxWE) )
{
/* Report the errors */
VpsSendError( pChip, pTxReq->SendID, (WORD)(Status&TxStat_Error_Mask));
}
if ( Status & TxStat_TxUnderrun )
{
/* If two underruns happen close together */
if ( pCD->TxGoodCount < TXGOODMIN )
{
/* Read the Max Frame Length register */
MaxFL.DWord = ReadDWord(OpReg_MaxFL);
/* If the transmit start threshold is less than the maximum */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -