📄 vchip8950.c
字号:
/* Enqueue all the Receive Status entries to the chip */
WriteDWord( OpReg_RxSEQ, RXSTATCOUNT );
/* Use MII registers to reset or initialize the PHY chip? */
/* If full duplex mode was negotiated by the PHY then set */
/* the MAC FDX bit in the TestCtl register (10 Mbps only?). */
/* Initialize the Interrupt Enable register */
WriteDWord( OpReg_IntEn, IntEn_TxStsQiE | IntEn_RxEOFiE );
/* Initialize the Transmit Control register */
WriteByte( OpReg_TxCTL, TxCTL_SerTxON );
/* 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( pChip );
/* Initialize chip look ahead */
VchipChangeLookAhead( pChip );
/* Enable interrupts at the chip */
VchipEnableInterrupts(pChip);
return TRUE;
}
/******************************************************************************
*
* VchipReset()
*
******************************************************************************/
BOOL 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 )
{
DEBUGMSG
(
ZONE_ERROR,
(
TEXT("The CS Chip reset does not complete!\r\n")
)
);
return FALSE;
}
return TRUE;
}
/******************************************************************************
*
* ResetQueues()
*
******************************************************************************/
static void ResetQueues( PCHIP pChip )
{
PCD pCD;
RxDesc_t *pRxDesc;
RxStat_t *pRxStat;
TxStat_t *pTxStat;
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 receive buffers are currently held */
pCD->RxHoldCount = 0;
/* The receive fragment array is empty */
pCD->RxFragCount = 0;
/* We have not yet started to receive a frame */
pCD->RxStartIndex = (WORD)UNSPECIFIED;
/* We have not yet received a status, Set to last status possible */
pCD->LastRxStatus = RXBUFFCOUNT-1;
/* 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()
*
******************************************************************************/
void VchipChangeFiltering( PCHIP pChip )
{
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 ( pChip->Config.Filtering & FILTER_INDIVIDUAL_ACCEPT )
RxControl |= RxCTL_IndividualAccept0;
if ( pChip->Config.Filtering & FILTER_BROADCAST_ACCEPT )
RxControl |= RxCTL_BroadcastA;
if ( pChip->Config.Filtering & FILTER_MULTICAST_ACCEPT )
RxControl |= RxCTL_MulticastA;
if ( pChip->Config.Filtering & FILTER_PROMISCUOUS_ACCEPT )
RxControl |= RxCTL_PromiscuousA;
/* Write the new filtering criteria to the chip and turn receiver back on */
WriteDWord( OpReg_RxCTL, RxControl );
}
/******************************************************************************
*
* VchipChangeLookAhead()
*
******************************************************************************/
static void VchipChangeLookAhead( PCHIP pChip )
{
WORD BMControl;
DWORD IntEnable;
/* Read the bus master control register */
BMControl=ReadWord( OpReg_BMCTL);
/* Read the interrupt enable register */
IntEnable=ReadDWord( OpReg_IntEn);
if ( pChip->Config.LookAheadSize == (WORD)UNSPECIFIED )
{
/* Clear the receive header length */
WriteDWord( OpReg_RxHLen, 0 );
/* Disable header status from being put into the receive status queue */
BMControl &= ~BMCTL_EnHeader1;
/* Disable receive header interrupts */
IntEnable &= ~IntEn_RxHdriE;
}
else /* The look ahead size is specified */
{
/* Set the receive header length to the look ahead size */
WriteDWord( OpReg_RxHLen, pChip->Config.LookAheadSize );
/* Enable header status to be put into the receive status queue */
BMControl |= BMCTL_EnHeader1;
/* Enable receive header interrupts */
IntEnable |= IntEn_RxHdriE;
}
/* Update the bus master control register */
WriteWord( OpReg_BMCTL, BMControl );
/* Update the receive enable register */
WriteDWord( OpReg_IntEn, IntEnable );
}
/******************************************************************************
*
* VchipISR()
*
******************************************************************************/
WORD VchipISR( PCHIP pChip )
{
DWORD Status;
BOOL IDidSomething=FALSE;
/* Read and clear the interrupt status */
Status = ReadDWord( OpReg_IntStsC);
while ( Status != 0L )
{
IDidSomething=TRUE;
if ( Status & IntSts_RxStsQ )
{
ProcessRxStatusQueue( pChip );
}
if ( Status & IntSts_TxStsQ )
{
ProcessTxStatusQueue( pChip );
}
/* Read and clear the interrupt status again */
Status = ReadDWord(OpReg_IntStsC);
}
return IDidSomething;
}
/******************************************************************************
*
* ProcessRxStatusQueue()
*
******************************************************************************/
static void ProcessRxStatusQueue( PCHIP pChip )
{
PCD pCD;
RxStat_t * volatile pRxStat;
WORD Index;
WORD TotalLength;
WORD Errors;
int LoopCount=0;
volatile DWORD Status;
static int TotalRx=0;
pCD = pChip->pData;
/* No receive descriptors have been processed yet */
// DescCount = 0;
/* While the receive status entry is not processed */
while ( pCD->pRxStatNext->RxStat & RxStat_RxFP )
{
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 */
Index = (WORD)(pRxStat->BufIndx & RxStat_BufIndx_Mask);
/* Get the total length of the frame */
TotalLength = pRxStat->FrameLength;
/* 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. */
}
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 );
}
/* Mark the buffer as now available */
(pCD->pRxDesc+Index)->BufLength = RXBUFFSIZE;
/* The receive status entry is now processed */
pCD->pRxStatNext->RxStat = 0;
pCD->pRxStatNext->BufIndx = 0;
pCD->pRxStatNext->FrameLength = 0x0;
/* Increment to the next receive status entry (with wrap-around) */
pCD->pRxStatNext++;
if ( pCD->pRxStatNext == pCD->pRxStatLimit )
{
pCD->pRxStatNext = pCD->pRxStat;
}
/* 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 );
}
// TotalRx++;
// DbgPrint("CS8950.dll ProcessRxStatusQueue() TotalRx=%d \n", TotalRx);
}
/******************************************************************************
*
* 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"))
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -