📄 vchip8950.c
字号:
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 )
{
DEBUGMSG
(
ZONE_ERROR,
(
TEXT("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 )
{
DEBUGMSG
(
ZONE_ERROR,
(
TEXT("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;
}
/******************************************************************************
*
* PHYAutoNegotiation(PCHIP pChip);
* Purpose: PHY Auto Negotiation to detect the link speed (10/100Mbps) and
* duplex (half/full).
* return: TRUE: successful. FALSE: fail
*
******************************************************************************/
#define MAX_AUTOCONFIGTIME (4 * 100)
static int PHYAutoNegotiation(PCHIP pChip)
{
unsigned short val;
int x;
unsigned short PhyId;
unsigned char b8;
WORD Result;
WCHAR *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);
//
//
// 02/14/02 @melody Auto_Neg should be compeleted in 5 min.
//
// I am not going to hang the system for 5 minutes while whating to boot
// If it doesn't autoconfigure in 4 seconds then assume it is 10Mbit Half.
//
for(x = 0; x<MAX_AUTOCONFIGTIME; x++)
{
/* Check if Auto-Negotiation complete? */
Sleep(10);
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);
DEBUGMSG
(
ZONE_ERROR,
(
TEXT("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 );
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 = L"Full";
}
else
{
strDuplex = L"Half";
}
if(val & SSR_10_Mbps)
{
strSpeed = L"10";
}
else
{
strSpeed = L"100";
}
//
// Show the current link mode.
//
DEBUGMSG
(
ZONE_INIT,
(
TEXT("CS8950: Speed = %s Mbs, Duplex = %s.\n"),
strSpeed,
strDuplex
)
);
return TRUE;
}
/******************************************************************************
*
* StartupPHY()
*
******************************************************************************/
static BOOL StartupPHY( PCHIP pChip )
{
PCD pCD;
WORD Result;
WORD val=0;
BYTE b8;
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 */
pChip->Config.DetectedMediaType = MEDIA_BASE_T;
pChip->Config.DetectedMediaSpeed = MEDIA_10_MBPS;
pChip->Config.CurrentDuplexMode = DUPLEX_HALF;
if ( pChip->Config.RequestedMediaSpeed == MEDIA_AUTO_DETECT ||
pChip->Config.RequestedDuplexMode == DUPLEX_AUTO_NEGOTIATE )
{
Result =PHYAutoNegotiation(pChip);
}
else
{
if ( pChip->Config.RequestedMediaSpeed == MEDIA_100_MBPS )
{
val = BMCR_100_MBPS;
pChip->Config.DetectedMediaSpeed = MEDIA_100_MBPS;
}
if ( pChip->Config.RequestedDuplexMode == DUPLEX_FULL )
{
val = val | DUPLEX_FULL;
pChip->Config.CurrentDuplexMode = DUPLEX_FULL;
/* if the Link is Full Duplex, then set MAC for Full Duplex too. */
b8 = ReadByte(OpReg_TestCTL);
b8 |= TestCTL_MACFDX;
WriteByte(OpReg_TestCTL, b8);
}
Result = WritePHY( pChip, 0x0, PHYReg_BMCR, val);
}
return TRUE;
}
/******************************************************************************
*
* StartupQueues()
*
******************************************************************************/
static BOOL StartupQueues( PCHIP pChip )
{
PCD pCD;
WORD Index;
BOOL Result;
pCD = pChip->pData;
/* Allocate shared memory for the Receive Descriptor Queue */
Result = VosAllocSharedMemory( pChip, sizeof(RxDesc_t)*RXDESCCOUNT,
&(PVOID)pCD->pRxDesc, &pCD->RxDescPhysAddr );
if ( Result != TRUE )
{
return FALSE;
}
/* Initialize Receive Descriptor Queue limit pointer */
pCD->pRxDescLimit = pCD->pRxDesc + RXDESCCOUNT;
/* Initialize the Receive Descriptor Queue registers */
WriteDWord( OpReg_RxDBA, pCD->RxDescPhysAddr );
WriteWord( OpReg_RxDBL, sizeof(RxDesc_t)*RXDESCCOUNT );
WriteDWord( OpReg_RxDTH, 0x00040002 );
/* Allocate shared memory for the Receive Status Queue */
Result = VosAllocSharedMemory( pChip, sizeof(RxStat_t)*RXSTATCOUNT,
&(PVOID)pCD->pRxStat, &pCD->RxStatPhysAddr );
if ( Result != TRUE)
{
return FALSE;
}
/* Initialize Receive Status Queue limit pointer */
pCD->pRxStatLimit = pCD->pRxStat + RXSTATCOUNT;
/* Initialize the Receive Status Queue registers */
WriteDWord( OpReg_RxSBA, pCD->RxStatPhysAddr );
WriteWord( OpReg_RxSBL, sizeof(RxStat_t)*RXSTATCOUNT);
WriteDWord(OpReg_RxSTH, 0x00040002 );
/* Allocate shared memory for the Transmit Descriptor Queue */
Result = VosAllocSharedMemory( pChip, sizeof(TxDesc_t)*TXDESCCOUNT,
&(PVOID)pCD->pTxDesc, &pCD->TxDescPhysAddr );
if ( Result != TRUE )
{
return FALSE;
}
/* Initialize Transmit Descriptor Queue limit pointer */
pCD->pTxDescLimit = pCD->pTxDesc + TXDESCCOUNT;
/* Initialize the Transmit Descriptor Queue registers */
WriteDWord( OpReg_TxDBA, pCD->TxDescPhysAddr );
WriteWord( OpReg_TxDBL, sizeof(TxDesc_t)*TXDESCCOUNT );
WriteDWord( OpReg_TxDTH, 0x00040002 );
/* Allocate shared memory for the Transmit Status Queue */
Result = VosAllocSharedMemory( pChip, sizeof(TxStat_t)*TXSTATCOUNT,
&(PVOID)pCD->pTxStat, &pCD->TxStatPhysAddr );
if ( Result != TRUE )
{
return FALSE;
}
/* Initialize Transmit Status Queue limit pointer */
pCD->pTxStatLimit = pCD->pTxStat + TXSTATCOUNT;
/* Initialize the Transmit Status Queue registers */
WriteDWord( OpReg_TxSBA, pCD->TxStatPhysAddr );
WriteWord( OpReg_TxSBL, sizeof(TxStat_t)*TXSTATCOUNT );
WriteDWord( OpReg_TxSTH, 0x00040002 );
/* Allocate receive buffers and initialize the Receive Descriptor Queue */
for ( Index=0; Index<RXDESCCOUNT; Index++ )
{
/* Allocate shared memory for a receive buffer */
Result = VosAllocSharedMemory( pChip, RXBUFFSIZE,
&(PVOID)pCD->RxBuff[Index].pBuff, &pCD->RxBuff[Index].PhysAddr );
if ( Result != TRUE )
{
return FALSE;
}
/* Initialize the Receive Descriptor */
(pCD->pRxDesc+Index)->RxBufAdr = pCD->RxBuff[Index].PhysAddr;
(pCD->pRxDesc+Index)->BufLength = RXBUFFSIZE;
(pCD->pRxDesc+Index)->BufIndx = Index;
}
/* Allocate the transmit buffers */
for ( Index=0; Index<TXBUFFCOUNT; Index++ )
{
/* Allocate shared memory for a transmit buffer */
Result = VosAllocSharedMemory( pChip, TXBUFFSIZE,
&(PVOID)pCD->TxBuff[Index].pBuff, &pCD->TxBuff[Index].PhysAddr );
if ( Result != TRUE )
{
return FALSE;
}
}
/* Initialize receive and transmit buffer thresholds */
WriteDWord( OpReg_RxBTH, 0x00800040 );
WriteDWord( OpReg_TxBTH, 0x00200010 );
return TRUE;
}
/******************************************************************************
*
* VchipInit()
*
******************************************************************************/
static BOOL VchipInit( PCHIP pChip )
{
PCD pCD;
BYTE Status;
BOOL b;
LARGE_INTEGER liCurrent, liStart;
pCD = pChip->pData;
/* Reset the chip */
//Result = VchipReset( pChip );
//if ( Result != TRUE )
//{
// return FALSE;
//}
/* Reset the queues */
ResetQueues( pChip );
/* Enable the transmit descriptor processor */
WriteWord( OpReg_BMCTL, BMCTL_TxEn );
/* Wait until the transmit descriptor processor is active */
b = QueryPerformanceCounter(&liStart);
for(;;)
{
b = QueryPerformanceCounter(&liCurrent);
ASSERT(b);
if((liCurrent.QuadPart - liStart.QuadPart) > MAC_INITIALIZATION_TIMEOUT)
{
DEBUGMSG
(
ZONE_ERROR,
(
TEXT("CS8950: The transmit descriptor processor is not active 0x%08x!\n"),
Status
)
);
DumpRegisters();
return FALSE;
}
Status=ReadByte( OpReg_BMSts);
if ( Status & BMSts_TxAct )
break;
}
/* Enable the receive descriptor processor */
WriteWord( OpReg_BMCTL, BMCTL_RxEn );
/* Wait until the receive descriptor processor is active */
b = QueryPerformanceCounter(&liStart);
ASSERT(b);
for(;;)
{
b = QueryPerformanceCounter(&liCurrent);
ASSERT(b);
if((liCurrent.QuadPart - liStart.QuadPart) > MAC_INITIALIZATION_TIMEOUT)
{
DEBUGMSG
(
ZONE_ERROR,
(
TEXT("CS8950: The receive descriptor processor is not active! OpReg_BMSts=%x \n"),
Status
)
);
DumpRegisters();
return FALSE;
}
Status=ReadByte( OpReg_BMSts);
if ( Status & BMSts_RxAct )
break;
}
/* Enqueue all the Receive Descriptors to the chip */
WriteDWord(OpReg_RxDEQ, RXDESCCOUNT );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -