📄 cs8950.c
字号:
/* 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;
}
//****************************************************************************
// 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 int PHYAutoNegotiation()
{
unsigned short val;
int x;
unsigned short PhyId;
unsigned char b8;
WORD Result;
char *strDuplex, *strSpeed;
PhyId = 0x1;
//
// 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 to Half_Duplex 10 Mbit.
//
Result = WritePHY( pChip, 0x0, PHYReg_BMCR, 0x0000);
EdbgOutputDebugString("CS8950: Error! PHY cannot complete Auto Negotiation.\n");
return FALSE;
}
/* 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);
//}
Result = ReadPHY( pChip, PhyId, PHYReg_SSR, &val );
if(val & SSR_Full_Duplex )
{
b8 = ReadByte(OpReg_TestCTL);
b8 |= TestCTL_MACFDX;
WriteByte(OpReg_TestCTL, b8);
}
//
// Lets print out the current mode that we are operating in.
//
if(val & SSR_Full_Duplex)
{
strDuplex = "Full";
}
else
{
strDuplex = "Half";
}
if(val & SSR_10_Mbps)
{
strSpeed = "10";
}
else
{
strSpeed = "100";
}
//
// Show the current link mode.
//
EdbgOutputDebugString("CS8950: Speed = %s Mbs, Duplex = %s.\n", strSpeed, strDuplex);
return TRUE;
}
/******************************************************************************
*
* StartupPHY()
*
******************************************************************************/
static WORD StartupPHY( PCHIP pChip )
{
PCD pCD;
WORD Result;
pCD = (PCD)pChip->pData;
/* Disable 2nd PHY */
//Result = WritePHY( pChip, 0x1f, PHYReg_BMCR, BMCR_Power_Down);
//ASSERT(Result);
/* QQQQQQQ Disable SQE in Reg 0x13 */
Result = WritePHY( pChip, 0x0, 0x13, 0x0000);
ASSERT(Result);
/* Set PHY Internal LoopBack */
/* Result = WritePHY( pChip, 0x0, PHYReg_BMCR, BMCR_Full_Duplex|BMCR_Loopback);*/
/*Result = WritePHY( pChip, 0x0, PHYReg_BMCR, BMCR_Auto_Neg_Enable|BMCR_Restart_Auto_Neg);*/
// Result = WritePHY( pChip, 0x0, PHYReg_BMCR, BMCR_Full_Duplex); }
//Result = WritePHY( pChip, 0x0, PHYReg_BMCR, 0x0000); //Half_Duplex
// @melody 09/10/01 Result = WritePHY( pChip, 0x0, PHYReg_BMCR, 0x0000); //Half_Duplex
//ASSERT(Result);
/* @melody 09/10/01 */
Result =PHYAutoNegotiation();
ASSERT(Result);
return MAC_SUCCESSFUL;
}
/******************************************************************************
*
* ReadPHY()
*
******************************************************************************/
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;
}
/******************************************************************************
*
* WritePHY()
*
******************************************************************************/
BOOL WritePHY( PCHIP pChip, WORD Address, WORD Register, WORD Value )
{
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 write failed, Address = 0x%x, Register = 0x%x, Value = 0x%x.\r\n",
(ULONG)Address,
(ULONG)Register,
(ULONG)Value
);
return FALSE;
}
/* Put the PHY data into the PHY Data register */
WriteWord( OpReg_MIIData, Value );
/* Issue the command to write to the register within the PHY */
WriteWord( OpReg_MIICmd,(WORD)(MIICmd_Opcode_Write |(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 write failed, Address = 0x%x, Register = 0x%x, Value = 0x%x.\r\n",
(ULONG)Address,
(ULONG)Register,
(ULONG)Value
);
return FALSE;
}
return TRUE;
}
/******************************************************************************
*
* FindPHYType()
*
******************************************************************************/
BOOL FindPHYType( PCHIP pChip )
{
PCD pCD;
WORD PHYAddress;
BOOL Result;
union
{
WORD Word[2];
DWORD DWord;
} PHYID;
pCD = (PCD)pChip->pData;
/* Search for a known type of PHY */
for ( PHYAddress=0; PHYAddress<32; PHYAddress++ )
{
/* Read PHY ID register 1 */
Result = ReadPHY( pChip, PHYAddress, PHYReg_PHYIDR1, &PHYID.Word[1] );
if ( Result != TRUE )
{
EdbgOutputDebugString("Cannot read PHY ID register 1!\r\n");
return FALSE;
}
/* Read PHY ID register 2 */
Result = ReadPHY( pChip, PHYAddress, PHYReg_PHYIDR2, &PHYID.Word[0] );
if ( Result != TRUE )
{
EdbgOutputDebugString("Cannot read PHY ID register 2!\r\n");
return FALSE;
}
/* Check if it is a PHY that we know about */
if ( ((PHYID.DWord & PHYID_OUI_Mask) == PHYID_OUI_National) &&
((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_DP83840) )
{
pCD->PHYType = PHY_TYPE_NATIONAL;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -