📄 cs8950.c
字号:
volatile DWORD Status;
// volatile DWORD BufIndx;
WORD Errors;
WORD Index;
DWORD RxDecDW1,RxDecDW2;
DWORD *pRxDecDW;
static unsigned char tempFrame[1524];
pCD = (PCD)pChip->pData;
// ULONG ulAvaliableBuffers;
//ulAvaliableBuffers = AvaliableRecieveBuffers();
//
//if(ulAvaliableBuffers < 16)
//{
// EdbgOutputDebugString("Avaliable = %d\r\n", ulAvaliableBuffers);
//}
//
// The documentation says that if there is no frame in the frame buffer then
// return.
//
Status=pCD->pRxStatNext->RxStat;
if (!(Status & RxStat_RxFP))
{
Status = ReadDWord(OpReg_IntStsC);
return FALSE;
}
//BufIndx=pCD->pRxStatNext->BufIndx;
//if (!(BufIndx & RxStat_RxFP))
//{
//Status = ReadDWord(OpReg_IntStsC);
// return FALSE;
//}
/* Get the total length of the frame */
*pwLength = pCD->pRxStatNext->FrameLength;
/* If the received frame has errors */
if ( !(Status & RxStat_RxWE) )
{
Errors = (WORD)((Status & RxStat_Error_Mask) >> 16);
VpsRecvError( pChip, Errors );
*pwLength=0; // 0 means a frame with error. */
}
/* Get the index of the buffer that contains the frame data */
Index = (WORD)(pCD->pRxStatNext->BufIndx & RxStat_BufIndx_Mask);
memcpy(pbData, pCD->RxBuff[Index].pBuff, *pwLength);
/* Mark the buffer as now available */
pRxDecDW= (DWORD *)(pCD->pRxDesc+Index);
RxDecDW1=*pRxDecDW++;
RxDecDW2=*pRxDecDW;
(pCD->pRxDesc+Index)->BufLength = RXBUFFSIZE;
pCD->pRxStatNext->RxStat = 0x0;
pCD->pRxStatNext->BufIndx = 0x0;
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 );
//
// Need to perform a dummy read to clear the interrupt status if there are no
// more interrupt packets.
//
Status = pCD->pRxStatNext->RxStat;
if (!(Status & RxStat_RxFP))
{
Status = ReadDWord(OpReg_IntStsC);
}
Global_RxTotalCnt++;
// EdbgOutputDebugString("\nCS8950 CS8950GetFrame(): Global_RxTotalCnt=%d\n",Global_RxTotalCnt);
//RxWorkaround();
/* Frame Length == 0 means the received frame with error*/
if ( *pwLength == 0 )
{
EdbgOutputDebugString("\n CS8950GetFrame(): Length = 0\r\n");
return FALSE;
}
//
// Lets send the frame out again as a broadcast packet.
//
#if 0
memcpy(tempFrame, pbData,*pwLength);
tempFrame[0] = 0x00;
tempFrame[1] = 0x06;
tempFrame[2] = 0x5B;
tempFrame[3] = 0xd3;
tempFrame[4] = 0xFC;
tempFrame[5] = 0x98;
tempFrame[6] = 0x00;
tempFrame[7] = 0x00;
tempFrame[8] = 0x00;
tempFrame[9] = 0x00;
tempFrame[10] = 0x00;
tempFrame[11] = 0x00;
CS8950SendFrame
(
tempFrame,
*pwLength
);
#endif // 0
return TRUE;
}
//****************************************************************************
// CS8950EnableInts
//****************************************************************************
// Public function that enables ethernet interrupts.
//
//
void CS8950EnableInts(void)
{
EdbgOutputDebugString("CS8950EnableInts\r\n");
WriteDWord(OpReg_IntEn, IntEn_RxEOFiE );
WriteDWord(OpReg_FERMask, GIntMask_Interrupt);
}
//****************************************************************************
// CS8950DisableInts
//****************************************************************************
// Public function that disables ethernet interrupts.
//
//
void CS8950DisableInts(void)
{
EdbgOutputDebugString("CS8950DisableInts\r\n");
WriteDWord(OpReg_IntEn, 0);
WriteDWord(OpReg_FERMask, 0 );
}
//****************************************************************************
// CS8950GetPendingInterrupts
//****************************************************************************
// Public function that return INTR_TYPE_RX if there are pending ethernet
// receive interrupts.
//
//
DWORD CS8950GetPendingInterrupts(void)
{
PCD pCD;
pCD = (PCD)pChip->pData;
if (pCD->pRxStatNext->RxStat & RxStat_RxFP)
{
EdbgOutputDebugString("R");
return INTR_TYPE_RX;
}
EdbgOutputDebugString("n");
return 0;
}
//****************************************************************************
// CS8950ReadEEPROM
//****************************************************************************
// Public function to read the pseudo EEPROM
//
//
BOOL CS8950ReadEEPROM
(
UINT16 EEPROMAddress,
UINT16 *pwVal
)
{
*pwVal = gusMacAddr[EEPROMAddress];
return TRUE;
}
//****************************************************************************
// CS8950WriteEEPROM
//****************************************************************************
// Public function to write the psuedo EEPROM.
//
//
BOOL CS8950WriteEEPROM
(
UINT16 EEPROMAddress,
UINT16 Data
)
{
gusMacAddr[EEPROMAddress] = Data;
return TRUE;
}
/******************************************************************************
*
* CS8950MulticastAddAll()
*
******************************************************************************/
void CS8950MulticastAddAll(void)
{
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 );
}
//****************************************************************************
// GetMACAddress
//****************************************************************************
//
//
//
static int GetMACAddress(USHORT *MacAddr)
{
if(gusMacAddr[0] == 0 && gusMacAddr[1] == 0 && gusMacAddr[2] == 0)
return FALSE;
//
// Currently copy the Mac Address from internal ram.
//
MacAddr[0] = gusMacAddr[0];
MacAddr[1] = gusMacAddr[1];
MacAddr[2] = gusMacAddr[2];
return TRUE;
}
/******************************************************************************
*
* PHYAutoNegotiation();
* Purpose: PHY Auto Negotiation to detect the link speed (10/100Mbps) and
* duplex (half/full).
* return: TRUE: successful. FALSE: fail
*
******************************************************************************/
static BOOL PHYAutoNegotiation()
{
unsigned short val;
int x;
unsigned short PhyId;
unsigned char b8;
WORD Result;
char *strDuplex, *strSpeed;
FindPHYType(pChip);
PhyId = ((PCD)pChip->pData)->PHYAddress;
//
// Write to Auto-Negotiation Advertisement Register (0x04)
// Set IEEE_802.3, and advertise 100/10M full/half duplex available
//
val = ANAR_SeltField_IEEE8023 | ANAR_10BaseT_HDX_Able | ANAR_10BaseT_FDX_Able |
ANAR_100BaseTX_HDX_Able | ANAR_100BaseTX_FDX_Able;
Result = WritePHY( pChip, PhyId, PHYReg_ANAR, val);
ASSERT(Result);
/*write to Basic Mode Control Register (0x00), enable and restart auto negotiation*/
val = BMCR_Restart_Auto_Neg| BMCR_Auto_Neg_Enable;
Result = WritePHY( pChip, PhyId, PHYReg_BMCR, val);
for(x = 0; x<MAX_AUTOCONFIGTIME; x++) /* 02/14/02 @melody Auto_Neg should be compeleted in 5 min.*/
{
/* Check if Auto-Negotiation complete? */
DelayInMsec(1);
Result = ReadPHY( pChip, PhyId, PHYReg_BMSR, &val );
if((val & BMSR_Auto_Neg_Complete) )
{
break;
}
}
if(x == MAX_AUTOCONFIGTIME)
{
//
// If this fails set PHY to Full_Duplex 100 Mbit.
//
Result = WritePHY( pChip, 0x0, PHYReg_BMCR, BMCR_Full_Duplex|BMCR_100_MBPS);
//set MAC for Full Duplex too.
b8 = ReadByte(OpReg_TestCTL);
b8 |= TestCTL_MACFDX;
WriteByte(OpReg_TestCTL, b8);
EdbgOutputDebugString("EthernetMAC: Error! PHY cannot complete Auto Negotiation. Set to 100MBps Full Duplex.\n");
return FALSE;
}
//CS8952 needs 1 second delay. Otherwise it won't send the 1st frame.
if ( ((PCD)pChip->pData)->PHYType == PHY_TYPE_CRYSTAL)
{
DelayInMsec(1000);
}
strDuplex = "Half";
/* if the Link is Full Duplex, then set MAC for Full Duplex too. */
Result = ReadPHY( pChip, PhyId, PHYReg_ANLPAR, &val );
if((val & ANLPAR_10BaseT_FDX_Able) || (val & ANLPAR_100BaseTX_FDX_Able))
{
b8 = ReadByte(OpReg_TestCTL);
b8 |= TestCTL_MACFDX;
WriteByte(OpReg_TestCTL, b8);
strDuplex = "Full";
}
strSpeed = "10";
//
// Lets print out the current mode that we are operating in.
//
if((val & ANLPAR_100BaseTX_FDX_Able) || (val & ANLPAR_100BaseTX_HDX_Able))
{
strSpeed = "100";
}
//
// Show the current link mode.
//
EdbgOutputDebugString("EthernetMAC: PhyId=%d PhyType=%d Speed=%s Mbs Duplex=%s.\n",
PhyId, ((PCD)pChip->pData)->PHYType, strSpeed, strDuplex);
return TRUE;
}
/******************************************************************************
*
* ReadPHY()
*
******************************************************************************/
static BOOL ReadPHY( PCHIP pChip, WORD Address, WORD Register, WORD *pValue )
{
BYTE Status;
int x;
/* Ensure that the PHY is not busy */
for ( x=0; x<MAXLOOP; x++ )
{
Status=ReadByte( OpReg_MIISts );
if ( !(Status & MIISts_Busy) ) break;
}
if ( x == MAXLOOP )
{
EdbgOutputDebugString
(
"First PHY read failed, Address =0x%x, Register= 0x%x. \r\n",
Address,
Register
);
return FALSE;
}
/* Issue the command to read the register within the PHY */
WriteWord(OpReg_MIICmd, (WORD)(MIICmd_Opcode_Read |(Address<<5)| Register));
/* Wait until the command is completed */
for ( x=0; x<MAXLOOP; x++ )
{
Status=ReadByte( OpReg_MIISts);
if ( !(Status & MIISts_Busy) )
break;
}
if ( x == MAXLOOP )
{
EdbgOutputDebugString("Second PHY read failed!");
return MAC_FAILED;
}
/* Get the PHY data from the PHY Data register */
*pValue=ReadWord( OpReg_MIIData );
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -