⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 physet.c

📁 ddk开发pci范例,使用9054芯片
💻 C
📖 第 1 页 / 共 3 页
字号:

#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 + -