📄 e100_phy.c
字号:
int speed; if ((bdp->PhyId != PHY_82555_TX) && (bdp->PhyId != PHY_82562ET) && (bdp->PhyId != PHY_82562EM)) return; /* If the user wants auto-polarity disabled, do only that and nothing * * else. * e100_autopolarity == 0 means disable --- we do just the * disabling * e100_autopolarity == 1 means enable --- we do nothing at * all * e100_autopolarity >= 2 means we do the workaround code. */ /* Change for 82558 enhancement */ switch (E100_AUTOPOLARITY) { case 0: e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, &misc_reg); e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, (u16) (misc_reg | DISABLE_AUTO_POLARITY)); break; case 1: e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, &misc_reg); e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, (u16) (misc_reg & ~DISABLE_AUTO_POLARITY)); break; case 2: /* we do this only if link is up */ if (!netif_carrier_ok(bdp->device)) { break; } e100_mdi_read(bdp, PHY_82555_CSR, bdp->phy_addr, &status); speed = (status & PHY_82555_SPEED_BIT) ? 100 : 10; /* we need to do this only if speed is 10 */ if (speed != 10) { break; } /* see if we have any end of frame errors */ e100_mdi_read(bdp, PHY_82555_EOF_COUNTER, bdp->phy_addr, &errors); /* if non-zero, wait for 100 ms before reading again */ if (errors) { udelay(200); e100_mdi_read(bdp, PHY_82555_EOF_COUNTER, bdp->phy_addr, &errors); /* if non-zero again, we disable polarity */ if (errors) { e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, &misc_reg); e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, (u16) (misc_reg | DISABLE_AUTO_POLARITY)); } } if (!errors) { /* it is safe to read the polarity now */ e100_mdi_read(bdp, PHY_82555_CSR, bdp->phy_addr, &status); /* if polarity is normal, disable polarity */ if (!(status & PHY_82555_POLARITY_BIT)) { e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, &misc_reg); e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, (u16) (misc_reg | DISABLE_AUTO_POLARITY)); } } break; default: break; }}/* * Procedure: e100_find_speed_duplex * * Description: This routine will figure out what line speed and duplex mode * the PHY is currently using. * * Arguments: * bdp - Ptr to this card's e100_bdconfig structure * * Returns: * NOTHING */static voide100_find_speed_duplex(struct e100_private *bdp){ unsigned int PhyId; u16 stat_reg, misc_reg; u16 ad_reg, lp_ad_reg; PhyId = bdp->PhyId & PHY_MODEL_REV_ID_MASK; /* First we should check to see if we have link */ /* If we don't have a link no reason to print a speed and duplex */ if (!e100_update_link_state(bdp)) { bdp->cur_line_speed = 0; bdp->cur_dplx_mode = 0; return; } /* On the 82559 and later controllers, speed/duplex is part of the * * SCB. So, we save an mdi_read and get these from the SCB. * */ if (bdp->rev_id >= D101MA_REV_ID) { /* Read speed */ if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_1) bdp->cur_line_speed = 100; else bdp->cur_line_speed = 10; /* Read duplex */ if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_2) bdp->cur_dplx_mode = FULL_DUPLEX; else bdp->cur_dplx_mode = HALF_DUPLEX; return; } /* If this is a Phy 100, 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_82555_TX)) { /* Read Phy 100 extended register 0 */ e100_mdi_read(bdp, EXTENDED_REG_0, bdp->phy_addr, &misc_reg); /* Get current speed setting */ if (misc_reg & PHY_100_ER0_SPEED_INDIC) bdp->cur_line_speed = 100; else bdp->cur_line_speed = 10; /* Get current duplex setting -- FDX enabled if bit is set */ if (misc_reg & PHY_100_ER0_FDX_INDIC) bdp->cur_dplx_mode = FULL_DUPLEX; else bdp->cur_dplx_mode = HALF_DUPLEX; return; } /* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */ e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &misc_reg); /* See if Auto-Negotiation was complete (bit 5, reg 1) */ e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); /* If a True NWAY connection was made, then we can detect speed/dplx * by ANDing our adapter's advertised abilities with our link partner's * advertised ablilities, and then assuming that the highest common * denominator was chosed by NWAY. */ if ((misc_reg & EXPANSION_NWAY) && (stat_reg & BMSR_ANEGCOMPLETE)) { /* Read our advertisement register */ e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg); /* Read our link partner's advertisement register */ e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg); /* AND the two advertisement registers together, and get rid * of any extraneous bits. */ ad_reg &= (lp_ad_reg & NWAY_LP_ABILITY); /* Get speed setting */ if (ad_reg & (ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_100BASE4)) bdp->cur_line_speed = 100; else bdp->cur_line_speed = 10; /* Get duplex setting -- use priority resolution algorithm */ if (ad_reg & ADVERTISE_100BASE4) { bdp->cur_dplx_mode = HALF_DUPLEX; } else if (ad_reg & ADVERTISE_100FULL) { bdp->cur_dplx_mode = FULL_DUPLEX; } else if (ad_reg & ADVERTISE_100HALF) { bdp->cur_dplx_mode = HALF_DUPLEX; } else if (ad_reg & ADVERTISE_10FULL) { bdp->cur_dplx_mode = FULL_DUPLEX; } else { bdp->cur_dplx_mode = HALF_DUPLEX; } return; } /* If we are connected to a dumb (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. */ bdp->cur_dplx_mode = HALF_DUPLEX; if (PhyId == PHY_NSC_TX) { /* Read register 25 to get the SPEED_10 bit */ e100_mdi_read(bdp, NSC_SPEED_IND_REG, bdp->phy_addr, &misc_reg); /* If bit 6 was set then we're at 10Mbps */ if (misc_reg & NSC_TX_SPD_INDC_SPEED) bdp->cur_line_speed = 10; else bdp->cur_line_speed = 100; } else { /* If we don't know the line speed, default to 10Mbps */ bdp->cur_line_speed = 10; }}/* * Procedure: e100_force_speed_duplex * * Description: This routine forces line speed and duplex mode of the * adapter based on the values the user has set in e100.c. * * Arguments: bdp - Pointer to the e100_private structure for the board * * Returns: void * */voide100_force_speed_duplex(struct e100_private *bdp){ u16 control; unsigned long expires; bdp->flags |= DF_SPEED_FORCED; e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); control &= ~BMCR_ANENABLE; control &= ~BMCR_LOOPBACK; switch (bdp->params.e100_speed_duplex) { case E100_SPEED_10_HALF: control &= ~BMCR_SPEED100; control &= ~BMCR_FULLDPLX; bdp->cur_line_speed = 10; bdp->cur_dplx_mode = HALF_DUPLEX; break; case E100_SPEED_10_FULL: control &= ~BMCR_SPEED100; control |= BMCR_FULLDPLX; bdp->cur_line_speed = 10; bdp->cur_dplx_mode = FULL_DUPLEX; break; case E100_SPEED_100_HALF: control |= BMCR_SPEED100; control &= ~BMCR_FULLDPLX; bdp->cur_line_speed = 100; bdp->cur_dplx_mode = HALF_DUPLEX; break; case E100_SPEED_100_FULL: control |= BMCR_SPEED100; control |= BMCR_FULLDPLX; bdp->cur_line_speed = 100; bdp->cur_dplx_mode = FULL_DUPLEX; break; } e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control); /* loop must run at least once */ expires = jiffies + 2 * HZ; do { if (e100_update_link_state(bdp) || time_after(jiffies, expires)) { break; } else { yield(); } } while (true);}voide100_force_speed_duplex_to_phy(struct e100_private *bdp){ u16 control; e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); control &= ~BMCR_ANENABLE; control &= ~BMCR_LOOPBACK; switch (bdp->params.e100_speed_duplex) { case E100_SPEED_10_HALF: control &= ~BMCR_SPEED100; control &= ~BMCR_FULLDPLX; break; case E100_SPEED_10_FULL: control &= ~BMCR_SPEED100; control |= BMCR_FULLDPLX; break; case E100_SPEED_100_HALF: control |= BMCR_SPEED100; control &= ~BMCR_FULLDPLX; break; case E100_SPEED_100_FULL: control |= BMCR_SPEED100; control |= BMCR_FULLDPLX; break; } /* Send speed/duplex command to PHY layer. */ e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);}/* * Procedure: e100_set_fc * * Description: Checks the link's capability for flow control. * * Arguments: bdp - Pointer to the e100_private structure for the board * * Returns: void * */static voide100_set_fc(struct e100_private *bdp){ u16 ad_reg; u16 lp_ad_reg; u16 exp_reg; /* no flow control for 82557, forced links or half duplex */ if (!netif_carrier_ok(bdp->device) || (bdp->flags & DF_SPEED_FORCED) || (bdp->cur_dplx_mode == HALF_DUPLEX) || !(bdp->flags & IS_BACHELOR)) { bdp->flags &= ~DF_LINK_FC_CAP; return; } /* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */ e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &exp_reg); if (exp_reg & EXPANSION_NWAY) { /* Read our advertisement register */ e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg); /* Read our link partner's advertisement register */ e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg); ad_reg &= lp_ad_reg; /* AND the 2 ad registers */ if (ad_reg & NWAY_AD_FC_SUPPORTED) bdp->flags |= DF_LINK_FC_CAP; else /* If link partner is capable of autoneg, but */ /* not capable of flow control, Received PAUSE */ /* frames are still honored, i.e., */ /* transmitted frames would be paused */ /* by incoming PAUSE frames */ bdp->flags |= DF_LINK_FC_TX_ONLY; } else { bdp->flags &= ~DF_LINK_FC_CAP; }}/* * Procedure: e100_phy_check * * Arguments: bdp - Pointer to the e100_private structure for the board * * Returns: true if link state was changed * false otherwise
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -