📄 vchip8950.c
字号:
);
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;
}
static BOOL Check_PHY_ID_Type( PCHIP pChip, WORD PHYAddress)
{
PCD pCD;
BOOL Result;
union
{
WORD Word[2];
DWORD DWord;
} PHYID;
pCD = (PCD)pChip->pData;
/* Read PHY ID register 1 */
Result = ReadPHY( pChip, PHYAddress, PHYReg_PHYIDR1, &PHYID.Word[1] );
if ( Result != TRUE )
{
return FALSE;
}
/* Read PHY ID register 2 */
Result = ReadPHY( pChip, PHYAddress, PHYReg_PHYIDR2, &PHYID.Word[0] );
if ( Result != TRUE )
{
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;
DEBUGMSG(ZONE_INIT,(TEXT("Detected National PHY at address: %x\r\n"), PHYAddress) );
}
else if ( ((PHYID.DWord & PHYID_OUI_Mask) == PHYID_OUI_Crystal) &&
((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_CS8952) )
{
pCD->PHYType = PHY_TYPE_CRYSTAL;
DEBUGMSG(ZONE_INIT,(TEXT("Detected Crystal PHY at address: %x\r\n"), PHYAddress) );
}
else if ( ((PHYID.DWord & PHYID_OUI_Mask) == PHYID_OUI_ICS) &&
((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_ICS1890) )
{
pCD->PHYType = PHY_TYPE_ICS;
DEBUGMSG(ZONE_INIT,(TEXT("Detected ICS1890 PHY at address: %x\r\n"), PHYAddress) );
}
else if ( ((PHYID.DWord & PHYID_OUI_Mask) == PHYID_OUI_BROADCOM) &&
((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_BCM5201) )
{
pCD->PHYType = PHY_TYPE_BROADCOM;
DEBUGMSG(ZONE_INIT,(TEXT("Detected Broadcom PHY at address: %x\r\n"), PHYAddress) );
}
else if ( ((PHYID.DWord & PHYID_OUI_Mask) == PHYID_OUI_MICREL) &&
((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_KS8721BL) )
{
pCD->PHYType = PHY_TYPE_MICREL_8721BL;
DEBUGMSG(ZONE_INIT,(TEXT("Detected Micrel KS8721BL PHY at address: %x\r\n"), PHYAddress ));
}
else if (PHYID.DWord == 0x00406212)
{
pCD->PHYType = PHY_TYPE_BROADCOM;
DEBUGMSG(ZONE_INIT,(TEXT("Detected Broadcom PHY at address: %x\r\n"), PHYAddress) );
}
else if (PHYID.DWord == 0x78100003)
{
pCD->PHYType = PHY_TYPE_LEVEL1; /* clc */
DEBUGMSG(ZONE_INIT,(TEXT("Detected Level1 PHY at address: %x\r\n"), PHYAddress) );
} else
{
pCD->PHYType = PHY_TYPE_UNKNOWN;
DEBUGMSG(ZONE_INIT,(TEXT("Detected Unknown PHY at address: %x\r\n"), PHYAddress) );
}
/* Save the address of the PHY */
pCD->PHYAddress = PHYAddress;
/* Get the PHY revision level */
pCD->PHYRevision = (BYTE)(PHYID.DWord & PHYID_Revision_Mask);
return TRUE;
}
static BOOL FindPHYType( PCHIP pChip )
{
PCD pCD;
WORD PHYAddress;
BOOL IsPHYFound;
pCD = (PCD)pChip->pData;
/* Search for a known type of PHY */
for ( PHYAddress=1; PHYAddress<=31; PHYAddress++ )
{
IsPHYFound=Check_PHY_ID_Type(pChip, PHYAddress);
if (IsPHYFound == TRUE )
{
break;
}
} //end for PhyId 1-31
/* If did not find a PHY */
if ( IsPHYFound == FALSE )
{
//PHY address 0 is for broadcasting. All PHYs will respond to address 0.
//However, some users may connect PHY to address 0. So search it.
IsPHYFound=Check_PHY_ID_Type(pChip, 0);
}
if ( IsPHYFound == FALSE )
{
// DEBUGMSG(ZONE_ERROR,(TEXT("Error: EthernetMAC: A PHY is not found!\r\n") ));
RETAILMSG(1,( TEXT("Error: EthernetMAC: PHY is not found!\n")));
}
return IsPHYFound;
}
/******************************************************************************
*
* 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;
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);
//
//
// 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, BMCR_Full_Duplex|BMCR_100_MBPS);
//set MAC for Full Duplex too.
b8 = ReadByte(OpReg_TestCTL);
b8 |= TestCTL_MACFDX;
WriteByte(OpReg_TestCTL, b8);
DEBUGMSG
(
ZONE_ERROR,
(
TEXT("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)
{
Sleep(1000);
}
strDuplex = L"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 = L"Full";
}
strSpeed = L"10";
//
// Lets print out the current mode that we are operating in.
//
if((val & ANLPAR_100BaseTX_FDX_Able) || (val & ANLPAR_100BaseTX_HDX_Able))
{
strSpeed = L"100";
}
//
// Show the current link mode.
//
DEBUGMSG
(
ZONE_INIT,
(
TEXT("EthernetMAC: PhyID=%d PhyType=%d Speed=%s Mbs, Duplex=%s.\n"),
PhyId,
((PCD)pChip->pData)->PHYType,
strSpeed,
strDuplex
)
);
/*
RETAILMSG(1,
( TEXT("EthernetMAC: PhyID=%d PhyType=%d Speed=%s Mbs, Duplex=%s.\n"),
PhyId,
((PCD)pChip->pData)->PHYType,
strSpeed,
strDuplex
)
);
*/
return TRUE;
}
/******************************************************************************
*
* StartupPHY()
*
******************************************************************************/
static BOOL StartupPHY( PCHIP pChip )
{
PCD pCD;
WORD Result;
WORD val=0;
BYTE b8;
pCD = (PCD)pChip->pData;
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 )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -