📄 physet.c
字号:
/****************************************************************************
** COPYRIGHT (C) 1994-1997 INTEL CORPORATION **
** DEVELOPED FOR MICROSOFT BY INTEL CORP., HILLSBORO, OREGON **
** HTTP://WWW.INTEL.COM/ **
** THIS FILE IS PART OF THE INTEL ETHEREXPRESS PRO/100B(TM) AND **
** ETHEREXPRESS PRO/100+(TM) NDIS 5.0 MINIPORT SAMPLE DRIVER **
****************************************************************************/
/****************************************************************************
Module Name:
physet.c
This driver runs on the following hardware:
- 82558 based PCI 10/100Mb ethernet adapters
(aka Intel EtherExpress(TM) PRO Adapters)
Environment:
Kernel Mode - Or whatever is the equivalent on WinNT
Revision History
- JCB 8/14/97 Example Driver Created
- Dchen 11-01-99 Modified for the new sample driver
*****************************************************************************/
//#pragma warning (disable: 4514)
//-----------------------------------------------------------------------------
// Procedure: PhyDetect
//
// Description: This routine will detect what phy we are using, set the line
// speed, FDX or HDX, and configure the phy if necessary.
//
// The following combinations are supported:
// - TX or T4 PHY alone at PHY address 1
// - T4 or TX PHY at address 1 and MII PHY at address 0
// - 82503 alone (10Base-T mode, no full duplex support)
// - 82503 and MII PHY (TX or T4) at address 0
//
// The sequence / priority of detection is as follows:
// If there is a PHY Address override use that address.
// else scan based on the 'Connector' setting.
// Switch Connector
// 0 = AutoScan
// 1 = Onboard TPE only
// 2 = MII connector only
//
// Each of the above cases is explained below.
//
// AutoScan means:
// Look for link on addresses 1, 0, 2..31 (in that order). Use the first
// address found that has link.
// If link is not found then use the first valid PHY found in the same scan
// order 1,0,2..31. NOTE: this means that NO LINK or Multi-link cases will
// default to the onboard PHY (address 1).
//
// Onboard TPE only:
// Phy address is set to 1 (No Scanning).
//
// MII connector only means:
// Look for link on addresses 0, 2..31 (again in that order, Note address 1 is
// NOT scanned). Use the first address found that has link.
// If link is not found then use the first valid Phy found in the same scan
// order 0, 2..31.
// In the AutoScan case above we should always find a valid PHY at address 1,
// there is no such guarantee here, so, If NO Phy is found then the driver
// should default to address 0 and continue to load. Note: External
// transceivers should be at address 0 but our early Nitro3 testing found
// transceivers at several non-zero addresses (6,10,14).
//
//
// NWAY
// Additionally auto-negotiation capable (NWAY) and parallel
// detection PHYs are supported. The flow-chart is described in
// the 82557 software writer's manual.
//
// NOTE: 1. All PHY MDI registers are read in polled mode.
// 2. The routines assume that the 82557 has been RESET and we have
// obtained the virtual memory address of the CSR.
// 3. PhyDetect will not RESET the PHY.
// 4. If FORCEFDX is set, SPEED should also be set. The driver will
// check the values for inconsistency with the detected PHY
// technology.
// 5. PHY 1 (the PHY on the adapter) MUST be at address 1.
// 6. Driver ignores FORCEFDX and SPEED overrides if a 503 interface
// is detected.
//
//
// Arguments:
// FdoData - ptr to FdoData object instance
//
// Result:
// Returns:
// STATUS_SUCCESS
// NDIS_STATUS_FAILURE
//-----------------------------------------------------------------------------
#include "precomp.h"
#if defined(EVENT_TRACING)
#include "physet.tmh"
#endif
NTSTATUS PhyDetect(
IN PFDO_DATA FdoData
)
{
#if DBG
USHORT MdiControlReg;
USHORT MdiStatusReg;
#endif
//
// Check for a phy address over-ride of 32 which indicates a 503
//
if (FdoData->PhyAddress == 32)
{
//
// 503 interface over-ride
//
DebugPrint(INFO, DBG_HW_ACCESS, " 503 serial component over-ride\n");
FdoData->PhyAddress = 32;
//
// Record the current speed and duplex. We will be in half duplex
// mode unless the user used the force full duplex over-ride.
//
FdoData->usLinkSpeed = 10;
FdoData->usDuplexMode = (USHORT) FdoData->AiForceDpx;
if (!FdoData->usDuplexMode)
{
FdoData->usDuplexMode = 1;
}
return(STATUS_SUCCESS);
}
//
// Check for other phy address over-rides.
// If the Phy Address is between 0-31 then there is an over-ride.
// Or the connector was set to 1
//
if ((FdoData->PhyAddress < 32) || (FdoData->Connector == CONNECTOR_TPE))
{
//
// User Override nothing to do but setup Phy and leave
//
if ((FdoData->PhyAddress > 32) && (FdoData->Connector == CONNECTOR_TPE))
{
FdoData->PhyAddress = 1; // Connector was forced
// Isolate all other PHYs and unisolate this one
SelectPhy(FdoData, FdoData->PhyAddress, FALSE);
}
DebugPrint(INFO, DBG_HW_ACCESS,
" Phy address Override to address %d\n", FdoData->PhyAddress);
#if DBG
//
// Read the MDI control register at override address.
//
MdiRead(FdoData, MDI_CONTROL_REG, FdoData->PhyAddress, FALSE, &MdiControlReg);
//
// Read the status register at override address.
//
MdiRead(FdoData, MDI_STATUS_REG, FdoData->PhyAddress, FALSE, &MdiStatusReg);
//
// Read the status register again because of sticky bits
//
MdiRead(FdoData, MDI_STATUS_REG, FdoData->PhyAddress, FALSE, &MdiStatusReg);
//
// check if we found a valid phy
//
if (!((MdiControlReg == 0xffff) || ((MdiStatusReg == 0) && (MdiControlReg == 0))))
{
//
// we have a valid phy1
//
DebugPrint(INFO, DBG_HW_ACCESS, " Over-ride address %d has a valid Phy.\n", FdoData->PhyAddress);
//
// Read the status register again
//
MdiRead(FdoData, MDI_STATUS_REG, FdoData->PhyAddress, FALSE, &MdiStatusReg);
//
// If there is a valid link then use this Phy.
//
if (MdiStatusReg & MDI_SR_LINK_STATUS)
{
DebugPrint(INFO, DBG_HW_ACCESS, " Phy at address %d has link\n", FdoData->PhyAddress);
}
}
else
{
//
// no PHY at over-ride address
//
DebugPrint(INFO, DBG_HW_ACCESS, " Over-ride address %d has no Phy!!!!\n", FdoData->PhyAddress);
}
#endif
return(SetupPhy(FdoData));
}
else // Need to scan - No address over-ride and Connector is AUTO or MII
{
FdoData->CurrentScanPhyIndex = 0;
FdoData->LinkDetectionWaitCount = 0;
FdoData->FoundPhyAt = 0xff;
FdoData->bLookForLink = TRUE;
return(ScanAndSetupPhy(FdoData));
} // End else scan
}
NTSTATUS ScanAndSetupPhy(
IN PFDO_DATA FdoData
)
{
USHORT MdiControlReg = 0;
USHORT MdiStatusReg = 0;
if (FdoData->bLinkDetectionWait)
{
goto NEGOTIATION_WAIT;
}
SCAN_PHY_START:
//
// For each PhyAddress 0 - 31
//
DebugPrint(TRACE, DBG_HW_ACCESS, " Index=%d, bLookForLink=%d\n",
FdoData->CurrentScanPhyIndex, FdoData->bLookForLink);
if (FdoData->bLookForLink)
{
//
// Phy Addresses must be tested in the order 1,0,2..31.
//
switch(FdoData->CurrentScanPhyIndex)
{
case 0:
FdoData->PhyAddress = 1;
break;
case 1:
FdoData->PhyAddress = 0;
break;
default:
FdoData->PhyAddress = FdoData->CurrentScanPhyIndex;
break;
}
//
// Skip OnBoard for MII only case
//
if ((FdoData->PhyAddress == 1)&&(FdoData->Connector == CONNECTOR_MII))
{
goto SCAN_PHY_NEXT;
}
DebugPrint(TRACE, DBG_HW_ACCESS, " Scanning Phy address %d for link\n", FdoData->PhyAddress);
//
// Read the MDI control register
//
MdiRead(FdoData, MDI_CONTROL_REG, FdoData->PhyAddress, FALSE, &MdiControlReg);
//
// Read the status register
//
MdiRead(FdoData, MDI_STATUS_REG, FdoData->PhyAddress, FALSE, &MdiStatusReg);
MdiRead(FdoData, MDI_STATUS_REG, FdoData->PhyAddress, FALSE, &MdiStatusReg);
// Sticky Bits
}
else
{
//
// Not looking for link
//
if (FdoData->FoundPhyAt < 32)
{
FdoData->PhyAddress = FdoData->FoundPhyAt;
}
else if (FdoData->Connector == CONNECTOR_MII)
{
//
// No valid PHYs were found last time so just default
//
FdoData->PhyAddress = 0; // Default for MII
}
else
{
//
// assume a 503 interface
//
FdoData->PhyAddress = 32;
//
// Record the current speed and duplex. We will be in half duplex
// mode unless the user used the force full duplex over-ride.
//
FdoData->usLinkSpeed = 10;
FdoData->usDuplexMode = (USHORT) FdoData->AiForceDpx;
if (!FdoData->usDuplexMode)
{
FdoData->usDuplexMode = 1;
}
return(STATUS_SUCCESS);
}
DebugPrint(TRACE, DBG_HW_ACCESS, " No Links Found!!\n");
}
//
// check if we found a valid phy or on !LookForLink pass
//
if (!( (MdiControlReg == 0xffff) || ((MdiStatusReg == 0) && (MdiControlReg == 0)))
|| (!FdoData->bLookForLink))
{
//
// Valid phy or Not looking for Link
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -