qla3xxx.c
来自「linux 内核源代码」· C语言 代码 · 共 2,557 行 · 第 1/5 页
C
2,557 行
}static int ql_is_full_dup(struct ql3_adapter *qdev){ u16 reg; switch(qdev->phyType) { case PHY_AGERE_ET1011C: { if (ql_mii_read_reg(qdev, 0x1A, ®)) return 0; return ((reg & 0x0080) && (reg & 0x1000)) != 0; } case PHY_VITESSE_VSC8211: default: { if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) return 0; return (reg & PHY_AUX_DUPLEX_STAT) != 0; } }}static int ql_is_phy_neg_pause(struct ql3_adapter *qdev){ u16 reg; if (ql_mii_read_reg(qdev, PHY_NEG_PARTNER, ®) < 0) return 0; return (reg & PHY_NEG_PAUSE) != 0;}static int PHY_Setup(struct ql3_adapter *qdev){ u16 reg1; u16 reg2; bool agereAddrChangeNeeded = false; u32 miiAddr = 0; int err; /* Determine the PHY we are using by reading the ID's */ err = ql_mii_read_reg(qdev, PHY_ID_0_REG, ®1); if(err != 0) { printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n", qdev->ndev->name); return err; } err = ql_mii_read_reg(qdev, PHY_ID_1_REG, ®2); if(err != 0) { printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n", qdev->ndev->name); return err; } /* Check if we have a Agere PHY */ if ((reg1 == 0xffff) || (reg2 == 0xffff)) { /* Determine which MII address we should be using determined by the index of the card */ if (qdev->mac_index == 0) { miiAddr = MII_AGERE_ADDR_1; } else { miiAddr = MII_AGERE_ADDR_2; } err =ql_mii_read_reg_ex(qdev, PHY_ID_0_REG, ®1, miiAddr); if(err != 0) { printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n", qdev->ndev->name); return err; } err = ql_mii_read_reg_ex(qdev, PHY_ID_1_REG, ®2, miiAddr); if(err != 0) { printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n", qdev->ndev->name); return err; } /* We need to remember to initialize the Agere PHY */ agereAddrChangeNeeded = true; } /* Determine the particular PHY we have on board to apply PHY specific initializations */ qdev->phyType = getPhyType(qdev, reg1, reg2); if ((qdev->phyType == PHY_AGERE_ET1011C) && agereAddrChangeNeeded) { /* need this here so address gets changed */ phyAgereSpecificInit(qdev, miiAddr); } else if (qdev->phyType == PHY_TYPE_UNKNOWN) { printk(KERN_ERR "%s: PHY is unknown\n", qdev->ndev->name); return -EIO; } return 0;}/* * Caller holds hw_lock. */static void ql_mac_enable(struct ql3_adapter *qdev, u32 enable){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 value; if (enable) value = (MAC_CONFIG_REG_PE | (MAC_CONFIG_REG_PE << 16)); else value = (MAC_CONFIG_REG_PE << 16); if (qdev->mac_index) ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value); else ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static void ql_mac_cfg_soft_reset(struct ql3_adapter *qdev, u32 enable){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 value; if (enable) value = (MAC_CONFIG_REG_SR | (MAC_CONFIG_REG_SR << 16)); else value = (MAC_CONFIG_REG_SR << 16); if (qdev->mac_index) ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value); else ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static void ql_mac_cfg_gig(struct ql3_adapter *qdev, u32 enable){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 value; if (enable) value = (MAC_CONFIG_REG_GM | (MAC_CONFIG_REG_GM << 16)); else value = (MAC_CONFIG_REG_GM << 16); if (qdev->mac_index) ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value); else ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static void ql_mac_cfg_full_dup(struct ql3_adapter *qdev, u32 enable){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 value; if (enable) value = (MAC_CONFIG_REG_FD | (MAC_CONFIG_REG_FD << 16)); else value = (MAC_CONFIG_REG_FD << 16); if (qdev->mac_index) ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value); else ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static void ql_mac_cfg_pause(struct ql3_adapter *qdev, u32 enable){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 value; if (enable) value = ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) | ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) << 16)); else value = ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) << 16); if (qdev->mac_index) ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value); else ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static int ql_is_fiber(struct ql3_adapter *qdev){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; switch (qdev->mac_index) { case 0: bitToCheck = PORT_STATUS_SM0; break; case 1: bitToCheck = PORT_STATUS_SM1; break; } temp = ql_read_page0_reg(qdev, &port_regs->portStatus); return (temp & bitToCheck) != 0;}static int ql_is_auto_cfg(struct ql3_adapter *qdev){ u16 reg; ql_mii_read_reg(qdev, 0x00, ®); return (reg & 0x1000) != 0;}/* * Caller holds hw_lock. */static int ql_is_auto_neg_complete(struct ql3_adapter *qdev){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; switch (qdev->mac_index) { case 0: bitToCheck = PORT_STATUS_AC0; break; case 1: bitToCheck = PORT_STATUS_AC1; break; } temp = ql_read_page0_reg(qdev, &port_regs->portStatus); if (temp & bitToCheck) { if (netif_msg_link(qdev)) printk(KERN_INFO PFX "%s: Auto-Negotiate complete.\n", qdev->ndev->name); return 1; } else { if (netif_msg_link(qdev)) printk(KERN_WARNING PFX "%s: Auto-Negotiate incomplete.\n", qdev->ndev->name); return 0; }}/* * ql_is_neg_pause() returns 1 if pause was negotiated to be on */static int ql_is_neg_pause(struct ql3_adapter *qdev){ if (ql_is_fiber(qdev)) return ql_is_petbi_neg_pause(qdev); else return ql_is_phy_neg_pause(qdev);}static int ql_auto_neg_error(struct ql3_adapter *qdev){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; switch (qdev->mac_index) { case 0: bitToCheck = PORT_STATUS_AE0; break; case 1: bitToCheck = PORT_STATUS_AE1; break; } temp = ql_read_page0_reg(qdev, &port_regs->portStatus); return (temp & bitToCheck) != 0;}static u32 ql_get_link_speed(struct ql3_adapter *qdev){ if (ql_is_fiber(qdev)) return SPEED_1000; else return ql_phy_get_speed(qdev);}static int ql_is_link_full_dup(struct ql3_adapter *qdev){ if (ql_is_fiber(qdev)) return 1; else return ql_is_full_dup(qdev);}/* * Caller holds hw_lock. */static int ql_link_down_detect(struct ql3_adapter *qdev){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; switch (qdev->mac_index) { case 0: bitToCheck = ISP_CONTROL_LINK_DN_0; break; case 1: bitToCheck = ISP_CONTROL_LINK_DN_1; break; } temp = ql_read_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus); return (temp & bitToCheck) != 0;}/* * Caller holds hw_lock. */static int ql_link_down_detect_clear(struct ql3_adapter *qdev){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; switch (qdev->mac_index) { case 0: ql_write_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus, (ISP_CONTROL_LINK_DN_0) | (ISP_CONTROL_LINK_DN_0 << 16)); break; case 1: ql_write_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus, (ISP_CONTROL_LINK_DN_1) | (ISP_CONTROL_LINK_DN_1 << 16)); break; default: return 1; } return 0;}/* * Caller holds hw_lock. */static int ql_this_adapter_controls_port(struct ql3_adapter *qdev){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; switch (qdev->mac_index) { case 0: bitToCheck = PORT_STATUS_F1_ENABLED; break; case 1: bitToCheck = PORT_STATUS_F3_ENABLED; break; default: break; } temp = ql_read_page0_reg(qdev, &port_regs->portStatus); if (temp & bitToCheck) { if (netif_msg_link(qdev)) printk(KERN_DEBUG PFX "%s: is not link master.\n", qdev->ndev->name); return 0; } else { if (netif_msg_link(qdev)) printk(KERN_DEBUG PFX "%s: is link master.\n", qdev->ndev->name); return 1; }}static void ql_phy_reset_ex(struct ql3_adapter *qdev){ ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET, PHYAddr[qdev->mac_index]);}static void ql_phy_start_neg_ex(struct ql3_adapter *qdev){ u16 reg; u16 portConfiguration; if(qdev->phyType == PHY_AGERE_ET1011C) { /* turn off external loopback */ ql_mii_write_reg(qdev, 0x13, 0x0000); } if(qdev->mac_index == 0) portConfiguration = qdev->nvram_data.macCfg_port0.portConfiguration; else portConfiguration = qdev->nvram_data.macCfg_port1.portConfiguration; /* Some HBA's in the field are set to 0 and they need to be reinterpreted with a default value */ if(portConfiguration == 0) portConfiguration = PORT_CONFIG_DEFAULT; /* Set the 1000 advertisements */ ql_mii_read_reg_ex(qdev, PHY_GIG_CONTROL, ®, PHYAddr[qdev->mac_index]); reg &= ~PHY_GIG_ALL_PARAMS; if(portConfiguration & PORT_CONFIG_1000MB_SPEED) { if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) reg |= PHY_GIG_ADV_1000F; else reg |= PHY_GIG_ADV_1000H; } ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg, PHYAddr[qdev->mac_index]); /* Set the 10/100 & pause negotiation advertisements */ ql_mii_read_reg_ex(qdev, PHY_NEG_ADVER, ®, PHYAddr[qdev->mac_index]); reg &= ~PHY_NEG_ALL_PARAMS; if(portConfiguration & PORT_CONFIG_SYM_PAUSE_ENABLED) reg |= PHY_NEG_ASY_PAUSE | PHY_NEG_SYM_PAUSE; if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) { if(portConfiguration & PORT_CONFIG_100MB_SPEED) reg |= PHY_NEG_ADV_100F; if(portConfiguration & PORT_CONFIG_10MB_SPEED) reg |= PHY_NEG_ADV_10F; } if(portConfiguration & PORT_CONFIG_HALF_DUPLEX_ENABLED) { if(portConfiguration & PORT_CONFIG_100MB_SPEED) reg |= PHY_NEG_ADV_100H; if(portConfiguration & PORT_CONFIG_10MB_SPEED) reg |= PHY_NEG_ADV_10H; } if(portConfiguration & PORT_CONFIG_1000MB_SPEED) { reg |= 1; } ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, reg, PHYAddr[qdev->mac_index]); ql_mii_read_reg_ex(qdev, CONTROL_REG, ®, PHYAddr[qdev->mac_index]); ql_mii_write_reg_ex(qdev, CONTROL_REG, reg | PHY_CTRL_RESTART_NEG | PHY_CTRL_AUTO_NEG, PHYAddr[qdev->mac_index]);}static void ql_phy_init_ex(struct ql3_adapter *qdev){ ql_phy_reset_ex(qdev); PHY_Setup(qdev); ql_phy_start_neg_ex(qdev);}/* * Caller holds hw_lock. */static u32 ql_get_link_state(struct ql3_adapter *qdev){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp, linkState; switch (qdev->mac_index) { case 0: bitToCheck = PORT_STATUS_UP0; break; case 1: bitToCheck = PORT_STATUS_UP1; break; } temp = ql_read_page0_reg(qdev, &port_regs->portStatus); if (temp & bitToCheck) { linkState = LS_UP; } else {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?