📄 vchip8950.c
字号:
/******************************************************************************
*
* 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 */
if ( MaxFL.Word.TxStartThresh < TXSTARTMAX )
{
/* Increase the transmit start threshold */
MaxFL.Word.TxStartThresh += TXSTARTSTEP;
WriteDWord( OpReg_MaxFL, MaxFL.DWord );
}
}
/* Reset the number of frames transmitted without underruns */
pCD->TxGoodCount = 0;
RestartTransmit( pChip, pTxReq->StartIndex );
}
else /* The frame did not have an underrun error */
{
/* Another frame has been transmitted without an underrun */
pCD->TxGoodCount++;
/* The transmit descriptors for this frame are now available */
pCD->TxDescAvail += pTxReq->DescCount;
/* Report that this send is now complete */
VpsSendComplete( pChip, pTxReq->SendID );
}
/* 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;
}
}
}
/******************************************************************************
*
* VpsSendError(()
*
******************************************************************************/
static void VpsSendError( PCHIP pChip, DWORD SendID, WORD Errors )
{
VPM_SetupMiniContextFromPchip
pvMini_Context->XmitErrors++;
if (Errors & TX_ERR_EXCESS_COLL)
{
DEBUGMSG
(
ZONE_SENDERROR,
(TEXT("VpsSendError(): TX_ERR_EXCESS_COLL!\n"))
);
pvMini_Context->XmitMaxCollisions++;
}
if (Errors & TX_ERR_UNDERRUN)
{
DEBUGMSG
(
ZONE_SENDERROR,
(TEXT("VpsSendError(): TX_ERR_UNDERRUN!\n"))
);
pvMini_Context->XmitUnderrun++;
}
if (Errors & TX_ERR_LOSS_CRS)
{
DEBUGMSG
(
ZONE_SENDERROR,
(TEXT("VpsSendError(): TX_ERR_EXCESS_LOSS_CRS!\n"))
);
pvMini_Context->XmitLostCRS++;
}
}
/******************************************************************************
*
* RestartTransmit()
*
******************************************************************************/
void RestartTransmit( PCHIP pChip, WORD StartIndex )
{
PCD pCD;
WORD NextIndex;
WORD BMControl;
BYTE BMStatus;
int x;
pCD = pChip->pData;
/* Reset the transmit channel */
BMControl=ReadWord( OpReg_BMCTL);
WriteWord( OpReg_BMCTL, (WORD)(BMControl | BMCTL_TxChRes) );
/* Wait until the channel reset is complete */
for ( x=0; x<MAXLOOP; x++ )
{
BMControl=ReadWord( OpReg_BMCTL);
if ( !(BMControl & BMCTL_TxChRes) )
break;
}
/* Set descriptor current address to the starting transmit descriptor */
WriteDWord( OpReg_TxDCA,
pCD->TxDescPhysAddr + (StartIndex * sizeof(TxDesc_t)) );
/* Re-enable (and initialize) the transmit descriptor processor */
BMControl=ReadWord( OpReg_BMCTL);
WriteWord( OpReg_BMCTL, (WORD)(BMControl | BMCTL_TxEn) );
/* Wait until the transmit descriptor processor is active */
for ( x=0; x<MAXLOOP; x++ )
{
BMStatus=ReadByte( OpReg_BMSts);
if ( BMStatus & BMSts_TxAct )
break;
}
/* Get the index of the next transmit descriptor */
NextIndex = (WORD)(pCD->pTxDescNext - pCD->pTxDesc);
if ( NextIndex <= StartIndex )
{
NextIndex += TXDESCCOUNT;
}
/* Re-enqueue the unprocessed transmit descriptors */
WriteDWord( OpReg_TxDEQ, NextIndex-StartIndex );
}
/******************************************************************************
*
* VpsSendComplete()
*
******************************************************************************/
static void VpsSendComplete( PCHIP pChip, DWORD SendID )
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNDIS_PACKET Packet;
PNDIS_PACKET pTempTxPacket;
PTXQUEUEELEMENT pTempTxQueueElem;
PTXQUEUEELEMENT pTxQueueElem;
VPM_SetupMiniContextFromPchip;
// DEBUGMSG(ZONE_ERROR,(TEXT("VpsSendComplete packet %d\n"),(DWORD)SendID));
pvMini_Context->XmitOKs++;
if (pvMini_Context->TxQueueHead != NULL)
{
pvMini_Context->XmitQueueDepth--;
pTxQueueElem = (PVOID)&(pvMini_Context->TxQueueHead->MiniportReserved);
if ( pTxQueueElem->XmitRC == NDIS_STATUS_NOT_INDICATING )
{
// No Indication needed, Send has not returned
pTxQueueElem->XmitRC = Status;
}
else
{
Packet = NULL;
// Run the Queue to the End or till packet SendID is found
for (pTempTxPacket=pvMini_Context->TxQueueHead,
pTempTxQueueElem=(PVOID)&pTempTxPacket->MiniportReserved ;
pvMini_Context->TxQueueHead != NULL;
pTempTxPacket=pvMini_Context->TxQueueHead,
pTempTxQueueElem=(PVOID)&pTempTxPacket->MiniportReserved )
{
pvMini_Context->TxQueueHead = pTempTxQueueElem->NextPacket;
if (pTempTxPacket == (PNDIS_PACKET)SendID)
{
Packet = pTempTxPacket;
break;
}
else
{
NdisMSendComplete
(
MiniportAdapterHandle,
pTempTxPacket,
NDIS_STATUS_FAILURE
);
}
}
// Confirm Send
if (Packet != NULL)
{
NdisMSendComplete(MiniportAdapterHandle,
Packet,
Status
);
}
}
}
else
{
pvMini_Context->XmitQueueDepth = 0;
}
}
/******************************************************************************
*
* VchipSend()
*
* The return code indicates if the VCHIP held on the the transmit buffers.
* If the return code is TRUE, 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 FALSE, then the VCHIP
* did not hold on to the transmit buffers and the VPS may immediately reuse
* them.
*
******************************************************************************/
WORD VchipSend( PCHIP pChip, DWORD SendID, WORD TotalLength)
{
PCD pCD;
PTXREQ pTxReq;
WORD DescCount;
TxDesc_t *pTxDesc;
// BYTE *pTxBuff;
// int Frag;
pCD = pChip->pData;
/* Verify that the total length is not too big */
if ( TotalLength > 1514 )
{
VpsSendError( pChip, SendID, TX_ERR_TOO_BIG );
VpsSendComplete( pChip, SendID);
return FALSE; /* Transmit buffers are not held */
}
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 fragment buffers to the transmit buffer */
// for ( Frag=0; Frag<FragCount; Frag++,pFrag++ )
// {
// NdisMoveMemory( pTxBuff, pFrag->pBuffer, pFrag->BuffLength );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -