📄 vchip8950.c
字号:
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 );
// pTxBuff += pFrag->BuffLength;
// }
/* 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->SendID = SendID;
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;
/* Enqueue the transmit descriptors to the chip */
WriteDWord(OpReg_TxDEQ, DescCount );
return FALSE; /* Transmit buffers are not held, can be released immiately*/
}
/******************************************************************************
*
* VchipGetConfig()
*
******************************************************************************/
BOOL VchipGetConfig( PCHIP pChip)
{
pChip->Config.EthernetAddr.Part[0]=0x0000;
pChip->Config.EthernetAddr.Part[1]=0x2401;
pChip->Config.EthernetAddr.Part[2]=0x0300;
/* Get duplex mode from auto-negotiation control */
pChip->Config.RequestedDuplexMode = DUPLEX_AUTO_NEGOTIATE;
pChip->Config.RequestedMediaSpeed = MEDIA_AUTO_DETECT;
pChip->Config.LookAheadSize = (WORD)UNSPECIFIED;
pChip->Config.CurrentDuplexMode = DUPLEX_NONE;
pChip->Config.DetectedMediaType = MEDIA_NONE;
/* The maximum number of outstanding transmits is the number of entries */
/* in the Transmit Request table */
pChip->Config.MaxTxCount = TXREQCOUNT;
/* The maximum number of outstanding receives is the number of entries */
/* in the Receive Status Queue */
pChip->Config.MaxRxCount = RXSTATCOUNT;
pChip->Config.IntLine = 9; //default interrupt line
/* QQQQ */
//pChip->Config.Memoryize = 2048;
return TRUE;
}
/******************************************************************************
*
* VchipMulticastAddAll()
*
******************************************************************************/
void VchipMulticastAddAll( PCHIP pChip )
{
DWORD RxControl;
/* Get the current settings of the receiver control register */
RxControl=ReadDWord( OpReg_RxCTL );
/* Turn off the receiver while changing the hash table */
WriteDWord( OpReg_RxCTL, RxControl & ~RxCTL_SerRxON );
/* Set all the bits in the hash table */
WriteByte( OpReg_AFP, AFP_Hash );
WriteDWord( OpReg_HashTb , 0xFFFFFFFF );
WriteDWord( OpReg_HashTb+4, 0xFFFFFFFF );
/* Turn the receiver back on */
WriteDWord(OpReg_RxCTL, RxControl );
}
/******************************************************************************
*
* VchipMulticastDeleteAll()
*
******************************************************************************/
void VchipMulticastDeleteAll( PCHIP pChip )
{
DWORD RxControl;
/* Get the current settings of the receiver control register */
RxControl=ReadDWord( OpReg_RxCTL );
/* Turn off the receiver while changing the hash table */
WriteDWord( OpReg_RxCTL, RxControl & ~RxCTL_SerRxON );
/* Clear all the bits in the hash table */
WriteByte(OpReg_AFP, AFP_Hash );
WriteDWord( OpReg_HashTb , 0 );
WriteDWord( OpReg_HashTb+4, 0 );
/* Turn the receiver back on */
WriteDWord( OpReg_RxCTL, RxControl );
}
/******************************************************************************
*
* VchipMulticastAdd()
*
******************************************************************************/
void VchipMulticastAdd( PCHIP pChip, PEA pMulticastAddr )
{
DWORD RxControl;
DWORD HashTable;
BYTE HashIndex;
DWORD HashValue;
HashTable = OpReg_HashTb;
/* Calculate the hash index for this multicast address */
HashIndex = CalculateHashIndex( (BYTE *)pMulticastAddr );
/* If the hash index is in the second double word of the hash table */
if ( HashIndex >= 32 )
{
HashTable += 4;
HashIndex -= 32;
}
/* Get the current settings of the receiver control register */
RxControl=ReadDWord( OpReg_RxCTL );
/* Turn off the receiver while changing the hash table */
WriteDWord( OpReg_RxCTL, RxControl & ~RxCTL_SerRxON );
/* Set the hash bit in the hash table */
WriteByte( OpReg_AFP, AFP_Hash );
HashValue = ReadDWord( HashTable);
WriteDWord( HashTable, HashValue | (1L<<HashIndex) );
/* Turn the receiver back on */
WriteDWord( OpReg_RxCTL, RxControl );
}
/******************************************************************************
*
* VchipMulticastDelete()
*
******************************************************************************/
v
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -