📄 physet.c
字号:
#if DBG
if (!( (MdiControlReg == 0xffff) || ((MdiStatusReg == 0) && (MdiControlReg == 0))))
{
DebugPrint(TRACE, DBG_HW_ACCESS, " Found a Phy at address %d\n", FdoData->PhyAddress);
}
#endif
//
// Store highest priority phy found for NO link case
//
if (FdoData->CurrentScanPhyIndex < FdoData->FoundPhyAt && FdoData->FoundPhyAt != 1)
{
// this phy is higher priority
FdoData->FoundPhyAt = (UCHAR) FdoData->PhyAddress;
}
//
// Select Phy before checking link status
// NOTE: may take up to 3.5 Sec if LookForLink == TRUE
//SelectPhy(FdoData, FdoData->PhyAddress, (BOOLEAN)LookForLink);
//
SelectPhy(FdoData, FdoData->PhyAddress, FALSE);
NEGOTIATION_WAIT:
//
// wait for auto-negotiation to complete (up to 3.5 seconds)
//
if (FdoData->LinkDetectionWaitCount++ < RENEGOTIATE_TIME)
{
// Read the status register twice because of sticky bits
MdiRead(FdoData, MDI_STATUS_REG, FdoData->PhyAddress, FALSE, &MdiStatusReg);
MdiRead(FdoData, MDI_STATUS_REG, FdoData->PhyAddress, FALSE, &MdiStatusReg);
if (!(MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE))
{
return STATUS_PENDING;
}
}
else
{
FdoData->LinkDetectionWaitCount = 0;
}
//
// 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);
//
// If there is a valid link or we alreadry tried once then use this Phy.
//
if ((MdiStatusReg & MDI_SR_LINK_STATUS) || (!FdoData->bLookForLink))
{
#if DBG
if (MdiStatusReg & MDI_SR_LINK_STATUS)
{
DebugPrint(TRACE, DBG_HW_ACCESS, " Using Phy at address %d with link\n", FdoData->PhyAddress);
}
else
{
DebugPrint(TRACE, DBG_HW_ACCESS, " Using Phy at address %d WITHOUT link!!!\n", FdoData->PhyAddress);
}
#endif
return(SetupPhy(FdoData)); // Exit with Link Path
}
} // End if valid PHY
SCAN_PHY_NEXT:
FdoData->CurrentScanPhyIndex++;
if (FdoData->CurrentScanPhyIndex >= 32)
{
FdoData->bLookForLink = FALSE;
}
goto SCAN_PHY_START;
}
//***************************************************************************
//
// Name: SelectPhy
//
// Description: This routine will Isolate all Phy addresses on the MII
// Bus except for the one address to be 'selected'. This
// Phy address will be un-isolated and auto-negotiation will
// be enabled, started, and completed. The Phy will NOT be
// reset and the speed will NOT be set to any value (that is
// done in SetupPhy).
//
// Arguments: SelectPhyAddress - PhyAddress to select
// WaitAutoNeg - Flag TRUE = Wait for Auto Negociation to complete.
// FALSE = don't wait. Good for 'No Link' case.
//
// Returns: Nothing
//
// Modification log:
// Date Who Description
// -------- --- --------------------------------------------------------
//***************************************************************************
VOID SelectPhy(
IN PFDO_DATA FdoData,
IN UINT SelectPhyAddress,
IN BOOLEAN WaitAutoNeg
)
{
UCHAR i;
USHORT MdiControlReg = 0;
USHORT MdiStatusReg = 0;
//
// Isolate all other phys and unisolate the one to query
//
for (i = 0; i < 32; i++)
{
if (i != SelectPhyAddress)
{
// isolate this phy
MdiWrite(FdoData, MDI_CONTROL_REG, i, MDI_CR_ISOLATE);
// wait 100 microseconds for the phy to isolate.
KeStallExecutionProcessor(100);
}
}
// unisolate the phy to query
//
// Read the MDI control register
//
MdiRead(FdoData, MDI_CONTROL_REG, SelectPhyAddress, FALSE, &MdiControlReg);
//
// Set/Clear bit unisolate this phy
//
MdiControlReg &= ~MDI_CR_ISOLATE; // Clear the Isolate Bit
//
// issue the command to unisolate this Phy
//
MdiWrite(FdoData, MDI_CONTROL_REG, SelectPhyAddress, MdiControlReg);
//
// sticky bits on link
//
MdiRead(FdoData, MDI_STATUS_REG, SelectPhyAddress, FALSE, &MdiStatusReg);
MdiRead(FdoData, MDI_STATUS_REG, SelectPhyAddress, FALSE, &MdiStatusReg);
//
// if we have link, don't mess with the phy
//
if (MdiStatusReg & MDI_SR_LINK_STATUS)
return;
//
// Read the MDI control register
//
MdiRead(FdoData, MDI_CONTROL_REG, SelectPhyAddress, FALSE, &MdiControlReg);
//
// set Restart auto-negotiation
//
MdiControlReg |= MDI_CR_AUTO_SELECT; // Set Auto Neg Enable
MdiControlReg |= MDI_CR_RESTART_AUTO_NEG; // Restart Auto Neg
//
// restart the auto-negotion process
//
MdiWrite(FdoData, MDI_CONTROL_REG, SelectPhyAddress, MdiControlReg);
//
// wait 200 microseconds for the phy to unisolate.
//
KeStallExecutionProcessor(200);
if (WaitAutoNeg)
{
//
// wait for auto-negotiation to complete (up to 3.5 seconds)
//
for (i = RENEGOTIATE_TIME; i != 0; i--)
{
// Read the status register twice because of sticky bits
MdiRead(FdoData, MDI_STATUS_REG, SelectPhyAddress, FALSE, &MdiStatusReg);
MdiRead(FdoData, MDI_STATUS_REG, SelectPhyAddress, FALSE, &MdiStatusReg);
if (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE)
break;
MP_STALL_EXECUTION(100);
}
}
}
//-----------------------------------------------------------------------------
// Procedure: SetupPhy
//
// Description: This routine will setup phy 1 or phy 0 so that it is configured
// to match a speed and duplex over-ride option. If speed or
// duplex mode is not explicitly specified in the registry, the
// driver will skip the speed and duplex over-ride code, and
// assume the FdoData is automatically setting the line speed, and
// the duplex mode. At the end of this routine, any truly Phy
// specific code will be executed (each Phy has its own quirks,
// and some require that certain special bits are set).
//
// NOTE: The driver assumes that SPEED and FORCEFDX are specified at the
// same time. If FORCEDPX is set without speed being set, the driver
// will encouter a fatal error and log a message into the event viewer.
//
// Arguments:
// FdoData - ptr to FdoData object instance
//
// Result:
// Returns:
// STATUS_SUCCESS
// NDIS_STATUS_FAILURE
//-----------------------------------------------------------------------------
NTSTATUS SetupPhy(
IN PFDO_DATA FdoData)
{
USHORT MdiControlReg = 0;
USHORT MdiStatusReg = 0;
USHORT MdiIdLowReg = 0;
USHORT MdiIdHighReg = 0;
USHORT MdiMiscReg = 0;
UINT PhyId;
BOOLEAN ForcePhySetting = FALSE;
//
// If we are NOT forcing a setting for line speed or full duplex, then
// we won't force a link setting, and we'll jump down to the phy
// specific code.
//
if (((FdoData->AiTempSpeed) || (FdoData->AiForceDpx)))
{
//
// Find out what kind of technology this Phy is capable of.
//
MdiRead(FdoData, MDI_STATUS_REG, FdoData->PhyAddress, FALSE, &MdiStatusReg);
//
// Read the MDI control register at our phy
//
MdiRead(FdoData, MDI_CONTROL_REG, FdoData->PhyAddress, FALSE, &MdiControlReg);
//
// Now check the validity of our forced option. If the force option is
// valid, then force the setting. If the force option is not valid,
// we'll set a flag indicating that we should error out.
//
//
// If speed is forced to 10mb
//
if (FdoData->AiTempSpeed == 10)
{
// If half duplex is forced
if (FdoData->AiForceDpx == 1)
{
if (MdiStatusReg & MDI_SR_10T_HALF_DPX)
{
DebugPrint(INFO, DBG_HW_ACCESS, " Forcing 10mb 1/2 duplex\n");
MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
ForcePhySetting = TRUE;
}
}
// If full duplex is forced
else if (FdoData->AiForceDpx == 2)
{
if (MdiStatusReg & MDI_SR_10T_FULL_DPX)
{
DebugPrint(INFO, DBG_HW_ACCESS, " Forcing 10mb full duplex\n");
MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT);
MdiControlReg |= MDI_CR_FULL_HALF;
ForcePhySetting = TRUE;
}
}
// If auto duplex (we actually set phy to 1/2)
else
{
if (MdiStatusReg & (MDI_SR_10T_FULL_DPX | MDI_SR_10T_HALF_DPX))
{
DebugPrint(INFO, DBG_HW_ACCESS, " Forcing 10mb auto duplex\n");
MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
ForcePhySetting = TRUE;
FdoData->AiForceDpx = 1;
}
}
}
//
// If speed is forced to 100mb
//
else if (FdoData->AiTempSpeed == 100)
{
// If half duplex is forced
if (FdoData->AiForceDpx == 1)
{
if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE))
{
DebugPrint(INFO, DBG_HW_ACCESS, " Forcing 100mb half duplex\n");
MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
MdiControlReg |= MDI_CR_10_100;
ForcePhySetting = TRUE;
}
}
// If full duplex is forced
else if (FdoData->AiForceDpx == 2)
{
if (MdiStatusReg & MDI_SR_TX_FULL_DPX)
{
DebugPrint(INFO, DBG_HW_ACCESS, " Forcing 100mb full duplex\n");
MdiControlReg &= ~MDI_CR_AUTO_SELECT;
MdiControlReg |= (MDI_CR_10_100 | MDI_CR_FULL_HALF);
ForcePhySetting = TRUE;
}
}
// If auto duplex (we set phy to 1/2)
else
{
if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -