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

📄 physet.c

📁 ddk开发pci范例,使用9054芯片
💻 C
📖 第 1 页 / 共 3 页
字号:
                {
                    DebugPrint(INFO, DBG_HW_ACCESS, "   Forcing 100mb auto duplex\n");
                    MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
                    MdiControlReg |= MDI_CR_10_100;
                    ForcePhySetting = TRUE;
                    FdoData->AiForceDpx = 1;
                }
            }
        }

        if (ForcePhySetting == FALSE)
        {
            DebugPrint(INFO, DBG_HW_ACCESS, "   Can't force speed=%d, duplex=%d\n",FdoData->AiTempSpeed, FdoData->AiForceDpx);

            return(STATUS_UNSUCCESSFUL);
        }

        //
        // Write the MDI control register with our new Phy configuration
        //
        MdiWrite(FdoData, MDI_CONTROL_REG, FdoData->PhyAddress, MdiControlReg);

        //
        // wait 100 milliseconds for auto-negotiation to complete
        //
        MP_STALL_EXECUTION(100);

    }

    //
    // Find out specifically what Phy this is.  We do this because for certain
    // phys there are specific bits that must be set so that the phy and the
    // 82557 work together properly.
    //
    MdiRead(FdoData, PHY_ID_REG_1, FdoData->PhyAddress, FALSE, &MdiIdLowReg);
    MdiRead(FdoData, PHY_ID_REG_2, FdoData->PhyAddress, FALSE, &MdiIdHighReg);

    PhyId =  ((UINT) MdiIdLowReg | ((UINT) MdiIdHighReg << 16));

    DebugPrint(TRACE, DBG_HW_ACCESS, "   Phy ID is %x\n", PhyId);

    //
    // And out the revsion field of the Phy ID so that we'll be able to detect
    // future revs of the same Phy.
    //
    PhyId &= PHY_MODEL_REV_ID_MASK;

    //
    // Handle the National TX
    //
    if (PhyId == PHY_NSC_TX)
    {
        DebugPrint(INFO, DBG_HW_ACCESS, "   Found a NSC TX Phy\n");

        MdiRead(FdoData, NSC_CONG_CONTROL_REG, FdoData->PhyAddress, FALSE, &MdiMiscReg);

        MdiMiscReg |= (NSC_TX_CONG_TXREADY | NSC_TX_CONG_F_CONNECT);

        //
        // If we are configured to do congestion control, then enable the
        // congestion control bit in the National Phy
        //
        if (FdoData->Congest)
            MdiMiscReg |= NSC_TX_CONG_ENABLE;
        else
            MdiMiscReg &= ~NSC_TX_CONG_ENABLE;

        MdiWrite(FdoData, NSC_CONG_CONTROL_REG, FdoData->PhyAddress, MdiMiscReg);
    }

    FindPhySpeedAndDpx(FdoData, PhyId);

    DebugPrint(INFO, DBG_HW_ACCESS, "   Current Speed=%d, Current Duplex=%d\n",FdoData->usLinkSpeed, FdoData->usDuplexMode);

    return(STATUS_SUCCESS);
}


//-----------------------------------------------------------------------------
// Procedure:   FindPhySpeedAndDpx
//
// Description: This routine will figure out what line speed and duplex mode
//              the PHY is currently using.
//
// Arguments:
//      FdoData - ptr to FdoData object instance
//      PhyId - The ID of the PHY in question.
//
// Returns:
//      NOTHING
//-----------------------------------------------------------------------------

VOID FindPhySpeedAndDpx(
    IN PFDO_DATA  FdoData,
    IN UINT         PhyId
    )
{
    USHORT  MdiStatusReg = 0;
    USHORT  MdiMiscReg = 0;
    USHORT  MdiOwnAdReg = 0;
    USHORT  MdiLinkPartnerAdReg = 0;
    
    //
    // If there was a speed and/or duplex override, then set our current
    // value accordingly
    //
    FdoData->usLinkSpeed = FdoData->AiTempSpeed;
    FdoData->usDuplexMode = (USHORT) FdoData->AiForceDpx;

    //
    // If speed and duplex were forced, then we know our current settings, so
    // we'll just return.  Otherwise, we'll need to figure out what NWAY set
    // us to.
    //
    if (FdoData->usLinkSpeed && FdoData->usDuplexMode)
    {
        return;
    }

    //
    // If we didn't have a valid link, then we'll assume that our current
    // speed is 10mb half-duplex.
    //

    //
    // 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 there wasn't a valid link then use default speed & duplex
    //
    if (!(MdiStatusReg & MDI_SR_LINK_STATUS))
    {
        DebugPrint(INFO, DBG_HW_ACCESS, "   Link Not found for speed detection!!!  Using defaults.\n");

        FdoData->usLinkSpeed = 10;
        FdoData->usDuplexMode = 1;

        return;
    }

    //
    // If this is an Intel PHY (a T4 PHY_100 or a TX PHY_TX), then read bits
    // 1 and 0 of extended register 0, to get the current speed and duplex
    // settings.
    //
    if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) || (PhyId == PHY_TX_ID))
    {
        DebugPrint(INFO, DBG_HW_ACCESS, "   Detecting Speed/Dpx for an Intel PHY\n");

        //
        // Read extended register 0
        //
        MdiRead(FdoData, EXTENDED_REG_0, FdoData->PhyAddress, FALSE, &MdiMiscReg);

        //
        // Get current speed setting
        //
        if (MdiMiscReg & PHY_100_ER0_SPEED_INDIC)
        {
            FdoData->usLinkSpeed = 100;
        }
        else 
        {
            FdoData->usLinkSpeed    = 10;
        }

        //
        //
        // Get current duplex setting -- if bit is set then FDX is enabled
        //
        if (MdiMiscReg & PHY_100_ER0_FDX_INDIC)
        {
            FdoData->usDuplexMode = 2;
        }
        else
        {
            FdoData->usDuplexMode   = 1;
        }

        return;
    }

    //
    // Read our link partner's advertisement register
    //
    MdiRead(FdoData, 
            AUTO_NEG_LINK_PARTNER_REG, 
            FdoData->PhyAddress, 
            FALSE,
            &MdiLinkPartnerAdReg);
    //
    // See if Auto-Negotiation was complete (bit 5, reg 1)
    //
    MdiRead(FdoData, MDI_STATUS_REG, FdoData->PhyAddress, FALSE, &MdiStatusReg);

    //
    // If a True NWAY connection was made, then we can detect speed/duplex by
    // ANDing our FdoData's advertised abilities with our link partner's
    // advertised ablilities, and then assuming that the highest common
    // denominator was chosed by NWAY.
    //
    if ((MdiLinkPartnerAdReg & NWAY_LP_ABILITY) &&
        (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE))
    {
        DebugPrint(INFO, DBG_HW_ACCESS, "   Detecting Speed/Dpx from NWAY connection\n");

        //
        // Read our advertisement register
        //
        MdiRead(FdoData, AUTO_NEG_ADVERTISE_REG, FdoData->PhyAddress, FALSE, &MdiOwnAdReg);

        //
        // AND the two advertisement registers together, and get rid of any
        // extraneous bits.
        //
        MdiOwnAdReg &= (MdiLinkPartnerAdReg & NWAY_LP_ABILITY);

        //
        // Get speed setting
        //
        if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX | NWAY_AD_TX_FULL_DPX | NWAY_AD_T4_CAPABLE))
        {
            FdoData->usLinkSpeed = 100;
        }
        else
        {
            FdoData->usLinkSpeed    = 10;
        }

        //
        // Get duplex setting -- use priority resolution algorithm
        //
        if (MdiOwnAdReg & (NWAY_AD_T4_CAPABLE))
        {
            FdoData->usDuplexMode = 1;
            return;
        }
        else if (MdiOwnAdReg & (NWAY_AD_TX_FULL_DPX))
        {
            FdoData->usDuplexMode = 2;
            return;
        }
        else if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX))
        {
            FdoData->usDuplexMode = 1;
            return;
        }
        else if (MdiOwnAdReg & (NWAY_AD_10T_FULL_DPX))
        {
            FdoData->usDuplexMode = 2;
            return;
        }
        else
        {
            FdoData->usDuplexMode = 1;
            return;
        }
    }

    //
    // If we are connected to a non-NWAY repeater or hub, and the line
    // speed was determined automatically by parallel detection, then we have
    // no way of knowing exactly what speed the PHY is set to unless that PHY
    // has a propietary register which indicates speed in this situation.  The
    // NSC TX PHY does have such a register.  Also, since NWAY didn't establish
    // the connection, the duplex setting should HALF duplex.
    //
    FdoData->usDuplexMode = 1;

    if (PhyId == PHY_NSC_TX)
    {
        DebugPrint(INFO, DBG_HW_ACCESS, "   Detecting Speed/Dpx from non-NWAY NSC connection\n");

        //
        // Read register 25 to get the SPEED_10 bit
        //
        MdiRead(FdoData, NSC_SPEED_IND_REG, FdoData->PhyAddress, FALSE, &MdiMiscReg);

        //
        // If bit 6 was set then we're at 10mb
        //
        if (MdiMiscReg & NSC_TX_SPD_INDC_SPEED)
        {
            FdoData->usLinkSpeed = 10;
        }
        else 
        {
            FdoData->usLinkSpeed    = 100;
        }
    }
    //
    // If we don't know what line speed we are set at, then we'll default to
    // 10mbs
    //
    else 
    {
        FdoData->usLinkSpeed  = 10;
    }
}


//-----------------------------------------------------------------------------
// Procedure:   ResetPhy
//
// Description: This routine will reset the PHY that the FdoData is currently
//              configured to use.
//
// Arguments:
//      FdoData - ptr to FdoData object instance
//
// Returns:
//      NOTHING
//-----------------------------------------------------------------------------

VOID ResetPhy(
    IN PFDO_DATA FdoData
    )
{
    USHORT  MdiControlReg;

    //
    // Reset the Phy, enable auto-negotiation, and restart auto-negotiation.
    //
    MdiControlReg = (MDI_CR_AUTO_SELECT | MDI_CR_RESTART_AUTO_NEG | MDI_CR_RESET);

    //
    // Write the MDI control register with our new Phy configuration
    //
    MdiWrite(FdoData, MDI_CONTROL_REG, FdoData->PhyAddress, MdiControlReg);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -