qla3xxx.c
来自「linux 内核源代码」· C语言 代码 · 共 2,557 行 · 第 1/5 页
C
2,557 行
serialPortInterfaceReg, ISP_NVRAM_MASK | qdev->eeprom_cmd_data | AUBURN_EEPROM_CLK_RISE); ql_write_nvram_reg(qdev, &port_regs->CommonRegs. serialPortInterfaceReg, ISP_NVRAM_MASK | qdev->eeprom_cmd_data | AUBURN_EEPROM_CLK_FALL); dataBit = (ql_read_common_reg (qdev, &port_regs->CommonRegs. serialPortInterfaceReg) & AUBURN_EEPROM_DI_1) ? 1 : 0; data = (data << 1) | dataBit; } *value = (u16) data;}/* * Caller holds hw_lock. */static void eeprom_readword(struct ql3_adapter *qdev, u32 eepromAddr, unsigned short *value){ fm93c56a_select(qdev); fm93c56a_cmd(qdev, (int)FM93C56A_READ, eepromAddr); fm93c56a_datain(qdev, value); fm93c56a_deselect(qdev);}static void ql_swap_mac_addr(u8 * macAddress){#ifdef __BIG_ENDIAN u8 temp; temp = macAddress[0]; macAddress[0] = macAddress[1]; macAddress[1] = temp; temp = macAddress[2]; macAddress[2] = macAddress[3]; macAddress[3] = temp; temp = macAddress[4]; macAddress[4] = macAddress[5]; macAddress[5] = temp;#endif}static int ql_get_nvram_params(struct ql3_adapter *qdev){ u16 *pEEPROMData; u16 checksum = 0; u32 index; unsigned long hw_flags; spin_lock_irqsave(&qdev->hw_lock, hw_flags); pEEPROMData = (u16 *) & qdev->nvram_data; qdev->eeprom_cmd_data = 0; if(ql_sem_spinlock(qdev, QL_NVRAM_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * 2) << 10)) { printk(KERN_ERR PFX"%s: Failed ql_sem_spinlock().\n", __func__); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); return -1; } for (index = 0; index < EEPROM_SIZE; index++) { eeprom_readword(qdev, index, pEEPROMData); checksum += *pEEPROMData; pEEPROMData++; } ql_sem_unlock(qdev, QL_NVRAM_SEM_MASK); if (checksum != 0) { printk(KERN_ERR PFX "%s: checksum should be zero, is %x!!\n", qdev->ndev->name, checksum); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); return -1; } /* * We have a problem with endianness for the MAC addresses * and the two 8-bit values version, and numPorts. We * have to swap them on big endian systems. */ ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn0.macAddress); ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn1.macAddress); ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn2.macAddress); ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn3.macAddress); pEEPROMData = (u16 *) & qdev->nvram_data.version; *pEEPROMData = le16_to_cpu(*pEEPROMData); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); return checksum;}static const u32 PHYAddr[2] = { PORT0_PHY_ADDRESS, PORT1_PHY_ADDRESS};static int ql_wait_for_mii_ready(struct ql3_adapter *qdev){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 temp; int count = 1000; while (count) { temp = ql_read_page0_reg(qdev, &port_regs->macMIIStatusReg); if (!(temp & MAC_MII_STATUS_BSY)) return 0; udelay(10); count--; } return -1;}static void ql_mii_enable_scan_mode(struct ql3_adapter *qdev){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 scanControl; if (qdev->numPorts > 1) { /* Auto scan will cycle through multiple ports */ scanControl = MAC_MII_CONTROL_AS | MAC_MII_CONTROL_SC; } else { scanControl = MAC_MII_CONTROL_SC; } /* * Scan register 1 of PHY/PETBI, * Set up to scan both devices * The autoscan starts from the first register, completes * the last one before rolling over to the first */ ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, PHYAddr[0] | MII_SCAN_REGISTER); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg, (scanControl) | ((MAC_MII_CONTROL_SC | MAC_MII_CONTROL_AS) << 16));}static u8 ql_mii_disable_scan_mode(struct ql3_adapter *qdev){ u8 ret; struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; /* See if scan mode is enabled before we turn it off */ if (ql_read_page0_reg(qdev, &port_regs->macMIIMgmtControlReg) & (MAC_MII_CONTROL_AS | MAC_MII_CONTROL_SC)) { /* Scan is enabled */ ret = 1; } else { /* Scan is disabled */ ret = 0; } /* * When disabling scan mode you must first change the MII register * address */ ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, PHYAddr[0] | MII_SCAN_REGISTER); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg, ((MAC_MII_CONTROL_SC | MAC_MII_CONTROL_AS | MAC_MII_CONTROL_RC) << 16)); return ret;}static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, u16 regAddr, u16 value, u32 phyAddr){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u8 scanWasEnabled; scanWasEnabled = ql_mii_disable_scan_mode(qdev); if (ql_wait_for_mii_ready(qdev)) { if (netif_msg_link(qdev)) printk(KERN_WARNING PFX "%s Timed out waiting for management port to " "get free before issuing command.\n", qdev->ndev->name); return -1; } ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, phyAddr | regAddr); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value); /* Wait for write to complete 9/10/04 SJP */ if (ql_wait_for_mii_ready(qdev)) { if (netif_msg_link(qdev)) printk(KERN_WARNING PFX "%s: Timed out waiting for management port to" "get free before issuing command.\n", qdev->ndev->name); return -1; } if (scanWasEnabled) ql_mii_enable_scan_mode(qdev); return 0;}static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr, u16 * value, u32 phyAddr){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u8 scanWasEnabled; u32 temp; scanWasEnabled = ql_mii_disable_scan_mode(qdev); if (ql_wait_for_mii_ready(qdev)) { if (netif_msg_link(qdev)) printk(KERN_WARNING PFX "%s: Timed out waiting for management port to " "get free before issuing command.\n", qdev->ndev->name); return -1; } ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, phyAddr | regAddr); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg, (MAC_MII_CONTROL_RC << 16)); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg, (MAC_MII_CONTROL_RC << 16) | MAC_MII_CONTROL_RC); /* Wait for the read to complete */ if (ql_wait_for_mii_ready(qdev)) { if (netif_msg_link(qdev)) printk(KERN_WARNING PFX "%s: Timed out waiting for management port to " "get free after issuing command.\n", qdev->ndev->name); return -1; } temp = ql_read_page0_reg(qdev, &port_regs->macMIIMgmtDataReg); *value = (u16) temp; if (scanWasEnabled) ql_mii_enable_scan_mode(qdev); return 0;}static int ql_mii_write_reg(struct ql3_adapter *qdev, u16 regAddr, u16 value){ struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; ql_mii_disable_scan_mode(qdev); if (ql_wait_for_mii_ready(qdev)) { if (netif_msg_link(qdev)) printk(KERN_WARNING PFX "%s: Timed out waiting for management port to " "get free before issuing command.\n", qdev->ndev->name); return -1; } ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, qdev->PHYAddr | regAddr); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value); /* Wait for write to complete. */ if (ql_wait_for_mii_ready(qdev)) { if (netif_msg_link(qdev)) printk(KERN_WARNING PFX "%s: Timed out waiting for management port to " "get free before issuing command.\n", qdev->ndev->name); return -1; } ql_mii_enable_scan_mode(qdev); return 0;}static int ql_mii_read_reg(struct ql3_adapter *qdev, u16 regAddr, u16 *value){ u32 temp; struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; ql_mii_disable_scan_mode(qdev); if (ql_wait_for_mii_ready(qdev)) { if (netif_msg_link(qdev)) printk(KERN_WARNING PFX "%s: Timed out waiting for management port to " "get free before issuing command.\n", qdev->ndev->name); return -1; } ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, qdev->PHYAddr | regAddr); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg, (MAC_MII_CONTROL_RC << 16)); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg, (MAC_MII_CONTROL_RC << 16) | MAC_MII_CONTROL_RC); /* Wait for the read to complete */ if (ql_wait_for_mii_ready(qdev)) { if (netif_msg_link(qdev)) printk(KERN_WARNING PFX "%s: Timed out waiting for management port to " "get free before issuing command.\n", qdev->ndev->name); return -1; } temp = ql_read_page0_reg(qdev, &port_regs->macMIIMgmtDataReg); *value = (u16) temp; ql_mii_enable_scan_mode(qdev); return 0;}static void ql_petbi_reset(struct ql3_adapter *qdev){ ql_mii_write_reg(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET);}static void ql_petbi_start_neg(struct ql3_adapter *qdev){ u16 reg; /* Enable Auto-negotiation sense */ ql_mii_read_reg(qdev, PETBI_TBI_CTRL, ®); reg |= PETBI_TBI_AUTO_SENSE; ql_mii_write_reg(qdev, PETBI_TBI_CTRL, reg); ql_mii_write_reg(qdev, PETBI_NEG_ADVER, PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX); ql_mii_write_reg(qdev, PETBI_CONTROL_REG, PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG | PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000);}static void ql_petbi_reset_ex(struct ql3_adapter *qdev){ ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET, PHYAddr[qdev->mac_index]);}static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev){ u16 reg; /* Enable Auto-negotiation sense */ ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, ®, PHYAddr[qdev->mac_index]); reg |= PETBI_TBI_AUTO_SENSE; ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg, PHYAddr[qdev->mac_index]); ql_mii_write_reg_ex(qdev, PETBI_NEG_ADVER, PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX, PHYAddr[qdev->mac_index]); ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG | PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000, PHYAddr[qdev->mac_index]);}static void ql_petbi_init(struct ql3_adapter *qdev){ ql_petbi_reset(qdev); ql_petbi_start_neg(qdev);}static void ql_petbi_init_ex(struct ql3_adapter *qdev){ ql_petbi_reset_ex(qdev); ql_petbi_start_neg_ex(qdev);}static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev){ u16 reg; if (ql_mii_read_reg(qdev, PETBI_NEG_PARTNER, ®) < 0) return 0; return (reg & PETBI_NEG_PAUSE_MASK) == PETBI_NEG_PAUSE;}static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr){ printk(KERN_INFO "%s: enabling Agere specific PHY\n", qdev->ndev->name); /* power down device bit 11 = 1 */ ql_mii_write_reg_ex(qdev, 0x00, 0x1940, miiAddr); /* enable diagnostic mode bit 2 = 1 */ ql_mii_write_reg_ex(qdev, 0x12, 0x840e, miiAddr); /* 1000MB amplitude adjust (see Agere errata) */ ql_mii_write_reg_ex(qdev, 0x10, 0x8805, miiAddr); /* 1000MB amplitude adjust (see Agere errata) */ ql_mii_write_reg_ex(qdev, 0x11, 0xf03e, miiAddr); /* 100MB amplitude adjust (see Agere errata) */ ql_mii_write_reg_ex(qdev, 0x10, 0x8806, miiAddr); /* 100MB amplitude adjust (see Agere errata) */ ql_mii_write_reg_ex(qdev, 0x11, 0x003e, miiAddr); /* 10MB amplitude adjust (see Agere errata) */ ql_mii_write_reg_ex(qdev, 0x10, 0x8807, miiAddr); /* 10MB amplitude adjust (see Agere errata) */ ql_mii_write_reg_ex(qdev, 0x11, 0x1f00, miiAddr); /* point to hidden reg 0x2806 */ ql_mii_write_reg_ex(qdev, 0x10, 0x2806, miiAddr); /* Write new PHYAD w/bit 5 set */ ql_mii_write_reg_ex(qdev, 0x11, 0x0020 | (PHYAddr[qdev->mac_index] >> 8), miiAddr); /* * Disable diagnostic mode bit 2 = 0 * Power up device bit 11 = 0 * Link up (on) and activity (blink) */ ql_mii_write_reg(qdev, 0x12, 0x840a); ql_mii_write_reg(qdev, 0x00, 0x1140); ql_mii_write_reg(qdev, 0x1c, 0xfaf0);}static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev, u16 phyIdReg0, u16 phyIdReg1){ PHY_DEVICE_et result = PHY_TYPE_UNKNOWN; u32 oui; u16 model; int i; if (phyIdReg0 == 0xffff) { return result; } if (phyIdReg1 == 0xffff) { return result; } /* oui is split between two registers */ oui = (phyIdReg0 << 6) | ((phyIdReg1 & PHY_OUI_1_MASK) >> 10); model = (phyIdReg1 & PHY_MODEL_MASK) >> 4; /* Scan table for this PHY */ for(i = 0; i < MAX_PHY_DEV_TYPES; i++) { if ((oui == PHY_DEVICES[i].phyIdOUI) && (model == PHY_DEVICES[i].phyIdModel)) { result = PHY_DEVICES[i].phyDevice; printk(KERN_INFO "%s: Phy: %s\n", qdev->ndev->name, PHY_DEVICES[i].name); break; } } return result;}static int ql_phy_get_speed(struct ql3_adapter *qdev){ u16 reg; switch(qdev->phyType) { case PHY_AGERE_ET1011C: { if (ql_mii_read_reg(qdev, 0x1A, ®) < 0) return 0; reg = (reg >> 8) & 3; break; } default: if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) return 0; reg = (((reg & 0x18) >> 3) & 3); } switch(reg) { case 2: return SPEED_1000; case 1: return SPEED_100; case 0: return SPEED_10; default: return -1; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?