From acf860ad541ce9529aff0bf17061183badd98903 Mon Sep 17 00:00:00 2001 From: jfv Date: Wed, 26 Nov 2008 23:57:23 +0000 Subject: This delta is primarily a fix for es2lan devices that will sometimes fail to initialize problem due to a lock contention with management hardware. However, in order to deliver that fix it was necessary to take a shared code update as a whole, and this required scattered changes in the core code to be compatible. The em driver now has VLAN HW support added as the igb driver had previously. MFC after: ASAP - in time for 7.1 RELEASE --- sys/dev/e1000/e1000_80003es2lan.c | 368 +++++++++++++++++++++++++------------- sys/dev/e1000/e1000_82540.c | 85 ++++----- sys/dev/e1000/e1000_82541.c | 145 +++++---------- sys/dev/e1000/e1000_82542.c | 96 ++++------ sys/dev/e1000/e1000_82543.c | 142 +++++---------- sys/dev/e1000/e1000_82571.c | 183 +++++++++---------- sys/dev/e1000/e1000_82575.c | 262 ++++++++------------------- sys/dev/e1000/e1000_82575.h | 45 +++-- sys/dev/e1000/e1000_api.c | 26 ++- sys/dev/e1000/e1000_api.h | 2 +- sys/dev/e1000/e1000_defines.h | 131 ++++++++------ sys/dev/e1000/e1000_hw.h | 255 +++++++++++++++++--------- sys/dev/e1000/e1000_ich8lan.c | 335 +++++++++++++--------------------- sys/dev/e1000/e1000_ich8lan.h | 2 - sys/dev/e1000/e1000_mac.c | 263 +++++++++++++++------------ sys/dev/e1000/e1000_mac.h | 7 +- sys/dev/e1000/e1000_manage.c | 17 +- sys/dev/e1000/e1000_nvm.c | 14 +- sys/dev/e1000/e1000_osdep.c | 20 --- sys/dev/e1000/e1000_osdep.h | 4 + sys/dev/e1000/e1000_phy.c | 132 +++++++------- sys/dev/e1000/e1000_phy.h | 19 +- sys/dev/e1000/e1000_regs.h | 98 ++++++---- sys/dev/e1000/if_em.c | 94 ++++++++-- sys/dev/e1000/if_em.h | 3 + sys/dev/e1000/if_igb.c | 8 +- 26 files changed, 1368 insertions(+), 1388 deletions(-) (limited to 'sys/dev/e1000') diff --git a/sys/dev/e1000/e1000_80003es2lan.c b/sys/dev/e1000/e1000_80003es2lan.c index 39409bd..fa7272e 100644 --- a/sys/dev/e1000/e1000_80003es2lan.c +++ b/sys/dev/e1000/e1000_80003es2lan.c @@ -32,7 +32,9 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* e1000_80003es2lan +/* + * 80003ES2LAN Gigabit Ethernet Controller (Copper) + * 80003ES2LAN Gigabit Ethernet Controller (Serdes) */ #include "e1000_api.h" @@ -41,7 +43,9 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw); static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw); static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw); static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw); +static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw); static void e1000_release_phy_80003es2lan(struct e1000_hw *hw); +static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw); static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw); static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw); static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, @@ -64,6 +68,11 @@ static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw); static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); +static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw); +static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, + u16 *data); +static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, + u16 data); static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw); static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw); static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); @@ -84,8 +93,6 @@ static const u16 e1000_gg82563_cable_length_table[] = /** * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw) { @@ -122,6 +129,8 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw) phy->ops.read_reg = e1000_read_phy_reg_gg82563_80003es2lan; phy->ops.write_reg = e1000_write_phy_reg_gg82563_80003es2lan; + phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan; + /* This can only be done after all function pointers are setup. */ ret_val = e1000_get_phy_id(hw); @@ -138,8 +147,6 @@ out: /** * e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) { @@ -197,8 +204,6 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) /** * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw) { @@ -280,8 +285,6 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw) /* turn on/off LED */ mac->ops.led_on = e1000_led_on_generic; mac->ops.led_off = e1000_led_off_generic; - /* remove device */ - mac->ops.remove_device = e1000_remove_device_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan; /* link info */ @@ -295,8 +298,7 @@ out: * e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs. * @hw: pointer to the HW structure * - * The only function explicitly called by the api module to initialize - * all function pointers and parameters. + * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw) { @@ -305,14 +307,14 @@ void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw) hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan; hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan; hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan; + e1000_get_bus_info_pcie_generic(hw); } /** * e1000_acquire_phy_80003es2lan - Acquire rights to access PHY * @hw: pointer to the HW structure * - * A wrapper to acquire access rights to the correct PHY. This is a - * function pointer entry point called by the api module. + * A wrapper to acquire access rights to the correct PHY. **/ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) { @@ -321,8 +323,6 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) DEBUGFUNC("e1000_acquire_phy_80003es2lan"); mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; - mask |= E1000_SWFW_CSR_SM; - return e1000_acquire_swfw_sync_80003es2lan(hw, mask); } @@ -330,8 +330,7 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) * e1000_release_phy_80003es2lan - Release rights to access PHY * @hw: pointer to the HW structure * - * A wrapper to release access rights to the correct PHY. This is a - * function pointer entry point called by the api module. + * A wrapper to release access rights to the correct PHY. **/ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) { @@ -340,7 +339,41 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) DEBUGFUNC("e1000_release_phy_80003es2lan"); mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; - mask |= E1000_SWFW_CSR_SM; + e1000_release_swfw_sync_80003es2lan(hw, mask); +} + + +/** + * e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register + * @hw: pointer to the HW structure + * + * Acquire the semaphore to access the Kumeran interface. + * + **/ +static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw) +{ + u16 mask; + + DEBUGFUNC("e1000_acquire_mac_csr_80003es2lan"); + + mask = E1000_SWFW_CSR_SM; + + return e1000_acquire_swfw_sync_80003es2lan(hw, mask); +} + +/** + * e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran Register + * @hw: pointer to the HW structure + * + * Release the semaphore used to access the Kumeran interface + **/ +static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw) +{ + u16 mask; + + DEBUGFUNC("e1000_release_mac_csr_80003es2lan"); + + mask = E1000_SWFW_CSR_SM; e1000_release_swfw_sync_80003es2lan(hw, mask); } @@ -349,8 +382,7 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) * e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM * @hw: pointer to the HW structure * - * Acquire the semaphore to access the EEPROM. This is a function - * pointer entry point called by the api module. + * Acquire the semaphore to access the EEPROM. **/ static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw) { @@ -375,8 +407,7 @@ out: * e1000_release_nvm_80003es2lan - Relinquish rights to access NVM * @hw: pointer to the HW structure * - * Release the semaphore used to access the EEPROM. This is a - * function pointer entry point called by the api module. + * Release the semaphore used to access the EEPROM. **/ static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw) { @@ -400,7 +431,7 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) u32 swmask = mask; u32 fwmask = mask << 16; s32 ret_val = E1000_SUCCESS; - s32 i = 0, timeout = 200; + s32 i = 0, timeout = 50; DEBUGFUNC("e1000_acquire_swfw_sync_80003es2lan"); @@ -452,8 +483,8 @@ static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) DEBUGFUNC("e1000_release_swfw_sync_80003es2lan"); - while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS); - /* Empty */ + while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) + ; /* Empty */ swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); swfw_sync &= ~mask; @@ -468,8 +499,7 @@ static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) * @offset: offset of the register to read * @data: pointer to the data returned from the operation * - * Read the GG82563 PHY register. This is a function pointer entry - * point called by the api module. + * Read the GG82563 PHY register. **/ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data) @@ -520,9 +550,8 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, usec_delay(200); - ret_val = e1000_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); + ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); usec_delay(200); e1000_release_phy_80003es2lan(hw); @@ -537,8 +566,7 @@ out: * @offset: offset of the register to read * @data: value to write to the register * - * Write to the GG82563 PHY register. This is a function pointer entry - * point called by the api module. + * Write to the GG82563 PHY register. **/ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data) @@ -590,8 +618,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, usec_delay(200); - ret_val = e1000_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, + ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); usec_delay(200); @@ -608,8 +635,7 @@ out: * @words: number of words to write * @data: buffer of data to write to the NVM * - * Write "words" of data to the ESB2 NVM. This is a function - * pointer entry point called by the api module. + * Write "words" of data to the ESB2 NVM. **/ static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) @@ -775,10 +801,17 @@ static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw) goto out; index = phy_data & GG82563_DSPD_CABLE_LENGTH; - phy->min_cable_length = e1000_gg82563_cable_length_table[index]; - phy->max_cable_length = e1000_gg82563_cable_length_table[index+5]; - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; + if (index < GG82563_CABLE_LENGTH_TABLE_SIZE + 5) { + phy->min_cable_length = e1000_gg82563_cable_length_table[index]; + phy->max_cable_length = + e1000_gg82563_cable_length_table[index+5]; + + phy->cable_length = (phy->min_cable_length + + phy->max_cable_length) / 2; + } else { + ret_val = E1000_ERR_PHY; + } out: return ret_val; @@ -791,7 +824,6 @@ out: * @duplex: pointer to duplex buffer * * Retrieve the current speed and duplex configuration. - * This is a function pointer entry point called by the api module. **/ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, u16 *duplex) @@ -804,20 +836,13 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); - if (ret_val) - goto out; - if (*speed == SPEED_1000) - ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw); - else - ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, - *duplex); + hw->phy.ops.cfg_on_link_up(hw); } else { ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw, speed, duplex); } -out: return ret_val; } @@ -826,7 +851,6 @@ out: * @hw: pointer to the HW structure * * Perform a global reset to the ESB2 controller. - * This is a function pointer entry point called by the api module. **/ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) { @@ -840,9 +864,8 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); - if (ret_val) { + if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); - } DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); @@ -855,8 +878,10 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) ctrl = E1000_READ_REG(hw, E1000_CTRL); + ret_val = e1000_acquire_phy_80003es2lan(hw); DEBUGOUT("Issuing a global reset to MAC\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); + e1000_release_phy_80003es2lan(hw); ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) @@ -878,7 +903,6 @@ out: * @hw: pointer to the HW structure * * Initialize the hw bits, LED, VFTA, MTA, link and hw counters. - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) { @@ -969,9 +993,6 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan"); - if (hw->mac.disable_hw_init_bits) - goto out; - /* Transmit Descriptor Control 0 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); reg |= (1 << 22); @@ -997,7 +1018,6 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) reg |= (1 << 28); E1000_WRITE_REG(hw, E1000_TARC(1), reg); -out: return; } @@ -1012,8 +1032,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u32 ctrl_ext; - u32 i = 0; - u16 data, data2; + u16 data; DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan"); @@ -1084,20 +1103,20 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) } /* Bypass Rx and Tx FIFO's */ - ret_val = e1000_write_kmrn_reg_generic(hw, + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL, E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); if (ret_val) goto out; - ret_val = e1000_read_kmrn_reg_generic(hw, + ret_val = e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, &data); if (ret_val) goto out; data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; - ret_val = e1000_write_kmrn_reg_generic(hw, + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, data); if (ret_val) @@ -1129,30 +1148,20 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) /* Enable Electrical Idle on the PHY */ data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; ret_val = hw->phy.ops.write_reg(hw, - GG82563_PHY_PWR_MGMT_CTRL, - data); + GG82563_PHY_PWR_MGMT_CTRL, + data); if (ret_val) goto out; - - do { - ret_val = hw->phy.ops.read_reg(hw, - GG82563_PHY_KMRN_MODE_CTRL, - &data); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.read_reg(hw, - GG82563_PHY_KMRN_MODE_CTRL, - &data2); + ret_val = hw->phy.ops.read_reg(hw, + GG82563_PHY_KMRN_MODE_CTRL, + &data); if (ret_val) goto out; - i++; - } while ((data != data2) && (i < GG82563_MAX_KMRN_RETRY)); data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; ret_val = hw->phy.ops.write_reg(hw, - GG82563_PHY_KMRN_MODE_CTRL, - data); + GG82563_PHY_KMRN_MODE_CTRL, + data); if (ret_val) goto out; @@ -1185,7 +1194,7 @@ out: static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) { u32 ctrl; - s32 ret_val; + s32 ret_val; u16 reg_data; DEBUGFUNC("e1000_setup_copper_link_80003es2lan"); @@ -1200,26 +1209,26 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) * iteration and increase the max iterations when * polling the phy; this fixes erroneous timeouts at 10Mbps. */ - ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 4), - 0xFFFF); + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4), + 0xFFFF); if (ret_val) goto out; - ret_val = e1000_read_kmrn_reg_generic(hw, GG82563_REG(0x34, 9), - ®_data); + ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), + ®_data); if (ret_val) goto out; reg_data |= 0x3F; - ret_val = e1000_write_kmrn_reg_generic(hw, GG82563_REG(0x34, 9), - reg_data); + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), + reg_data); if (ret_val) goto out; - ret_val = e1000_read_kmrn_reg_generic(hw, + ret_val = e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, ®_data); if (ret_val) goto out; reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; - ret_val = e1000_write_kmrn_reg_generic(hw, + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, reg_data); if (ret_val) @@ -1236,6 +1245,40 @@ out: } /** + * e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up + * @hw: pointer to the HW structure + * @duplex: current duplex setting + * + * Configure the KMRN interface by applying last minute quirks for + * 10/100 operation. + **/ +static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw) +{ + s32 ret_val = E1000_SUCCESS; + u16 speed; + u16 duplex; + + DEBUGFUNC("e1000_configure_on_link_up"); + + if (hw->phy.media_type == e1000_media_type_copper) { + + ret_val = e1000_get_speed_and_duplex_copper_generic(hw, + &speed, + &duplex); + if (ret_val) + goto out; + + if (speed == SPEED_1000) + ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw); + else + ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex); + } + +out: + return ret_val; +} + +/** * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation * @hw: pointer to the HW structure * @duplex: current duplex setting @@ -1253,7 +1296,7 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) DEBUGFUNC("e1000_configure_kmrn_for_10_100"); reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; - ret_val = e1000_write_kmrn_reg_generic(hw, + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, reg_data); if (ret_val) @@ -1268,12 +1311,12 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) do { ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data); + ®_data); if (ret_val) goto out; ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data2); + ®_data2); if (ret_val) goto out; i++; @@ -1307,7 +1350,7 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) DEBUGFUNC("e1000_configure_kmrn_for_1000"); reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; - ret_val = e1000_write_kmrn_reg_generic(hw, + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, reg_data); if (ret_val) @@ -1322,12 +1365,12 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) do { ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data); + ®_data); if (ret_val) goto out; ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data2); + ®_data2); if (ret_val) goto out; i++; @@ -1341,6 +1384,75 @@ out: } /** + * e1000_read_kmrn_reg_80003es2lan - Read kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquire semaphore, then read the PHY register at offset + * using the kumeran interface. The information retrieved is stored in data. + * Release the semaphore before exiting. + **/ +s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data) +{ + u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_read_kmrn_reg_80003es2lan"); + + ret_val = e1000_acquire_mac_csr_80003es2lan(hw); + if (ret_val) + goto out; + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & + E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; + E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); + + usec_delay(2); + + kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); + *data = (u16)kmrnctrlsta; + + e1000_release_mac_csr_80003es2lan(hw); + +out: + return ret_val; +} + +/** + * e1000_write_kmrn_reg_80003es2lan - Write kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquire semaphore, then write the data to PHY register + * at the offset using the kumeran interface. Release semaphore + * before exiting. + **/ +s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data) +{ + u32 kmrnctrlsta; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_write_kmrn_reg_80003es2lan"); + + ret_val = e1000_acquire_mac_csr_80003es2lan(hw); + if (ret_val) + goto out; + + kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & + E1000_KMRNCTRLSTA_OFFSET) | data; + E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); + + usec_delay(2); + + e1000_release_mac_csr_80003es2lan(hw); + +out: + return ret_val; +} + +/** * e1000_read_mac_addr_80003es2lan - Read device MAC address * @hw: pointer to the HW structure **/ @@ -1380,44 +1492,42 @@ static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw) **/ static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan"); e1000_clear_hw_cntrs_base_generic(hw); - temp = E1000_READ_REG(hw, E1000_PRC64); - temp = E1000_READ_REG(hw, E1000_PRC127); - temp = E1000_READ_REG(hw, E1000_PRC255); - temp = E1000_READ_REG(hw, E1000_PRC511); - temp = E1000_READ_REG(hw, E1000_PRC1023); - temp = E1000_READ_REG(hw, E1000_PRC1522); - temp = E1000_READ_REG(hw, E1000_PTC64); - temp = E1000_READ_REG(hw, E1000_PTC127); - temp = E1000_READ_REG(hw, E1000_PTC255); - temp = E1000_READ_REG(hw, E1000_PTC511); - temp = E1000_READ_REG(hw, E1000_PTC1023); - temp = E1000_READ_REG(hw, E1000_PTC1522); - - temp = E1000_READ_REG(hw, E1000_ALGNERRC); - temp = E1000_READ_REG(hw, E1000_RXERRC); - temp = E1000_READ_REG(hw, E1000_TNCRS); - temp = E1000_READ_REG(hw, E1000_CEXTERR); - temp = E1000_READ_REG(hw, E1000_TSCTC); - temp = E1000_READ_REG(hw, E1000_TSCTFC); - - temp = E1000_READ_REG(hw, E1000_MGTPRC); - temp = E1000_READ_REG(hw, E1000_MGTPDC); - temp = E1000_READ_REG(hw, E1000_MGTPTC); - - temp = E1000_READ_REG(hw, E1000_IAC); - temp = E1000_READ_REG(hw, E1000_ICRXOC); - - temp = E1000_READ_REG(hw, E1000_ICRXPTC); - temp = E1000_READ_REG(hw, E1000_ICRXATC); - temp = E1000_READ_REG(hw, E1000_ICTXPTC); - temp = E1000_READ_REG(hw, E1000_ICTXATC); - temp = E1000_READ_REG(hw, E1000_ICTXQEC); - temp = E1000_READ_REG(hw, E1000_ICTXQMTC); - temp = E1000_READ_REG(hw, E1000_ICRXDMTC); + E1000_READ_REG(hw, E1000_PRC64); + E1000_READ_REG(hw, E1000_PRC127); + E1000_READ_REG(hw, E1000_PRC255); + E1000_READ_REG(hw, E1000_PRC511); + E1000_READ_REG(hw, E1000_PRC1023); + E1000_READ_REG(hw, E1000_PRC1522); + E1000_READ_REG(hw, E1000_PTC64); + E1000_READ_REG(hw, E1000_PTC127); + E1000_READ_REG(hw, E1000_PTC255); + E1000_READ_REG(hw, E1000_PTC511); + E1000_READ_REG(hw, E1000_PTC1023); + E1000_READ_REG(hw, E1000_PTC1522); + + E1000_READ_REG(hw, E1000_ALGNERRC); + E1000_READ_REG(hw, E1000_RXERRC); + E1000_READ_REG(hw, E1000_TNCRS); + E1000_READ_REG(hw, E1000_CEXTERR); + E1000_READ_REG(hw, E1000_TSCTC); + E1000_READ_REG(hw, E1000_TSCTFC); + + E1000_READ_REG(hw, E1000_MGTPRC); + E1000_READ_REG(hw, E1000_MGTPDC); + E1000_READ_REG(hw, E1000_MGTPTC); + + E1000_READ_REG(hw, E1000_IAC); + E1000_READ_REG(hw, E1000_ICRXOC); + + E1000_READ_REG(hw, E1000_ICRXPTC); + E1000_READ_REG(hw, E1000_ICRXATC); + E1000_READ_REG(hw, E1000_ICTXPTC); + E1000_READ_REG(hw, E1000_ICTXATC); + E1000_READ_REG(hw, E1000_ICTXQEC); + E1000_READ_REG(hw, E1000_ICTXQMTC); + E1000_READ_REG(hw, E1000_ICRXDMTC); } diff --git a/sys/dev/e1000/e1000_82540.c b/sys/dev/e1000/e1000_82540.c index 0598075..6967261 100644 --- a/sys/dev/e1000/e1000_82540.c +++ b/sys/dev/e1000/e1000_82540.c @@ -32,11 +32,15 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* e1000_82540 - * e1000_82545 - * e1000_82546 - * e1000_82545_rev_3 - * e1000_82546_rev_3 +/* + * 82540EM Gigabit Ethernet Controller + * 82540EP Gigabit Ethernet Controller + * 82545EM Gigabit Ethernet Controller (Copper) + * 82545EM Gigabit Ethernet Controller (Fiber) + * 82545GM Gigabit Ethernet Controller + * 82546EB Gigabit Ethernet Controller (Copper) + * 82546EB Gigabit Ethernet Controller (Fiber) + * 82546GB Gigabit Ethernet Controller */ #include "e1000_api.h" @@ -57,8 +61,6 @@ static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw); /** * e1000_init_phy_params_82540 - Init PHY func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_phy_params_82540(struct e1000_hw *hw) { @@ -110,8 +112,6 @@ out: /** * e1000_init_nvm_params_82540 - Init NVM func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw) { @@ -153,8 +153,6 @@ static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw) /** * e1000_init_mac_params_82540 - Init MAC func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_mac_params_82540(struct e1000_hw *hw) { @@ -189,6 +187,8 @@ static s32 e1000_init_mac_params_82540(struct e1000_hw *hw) /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; + /* function id */ + mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; /* reset */ mac->ops.reset_hw = e1000_reset_hw_82540; /* hw initialization */ @@ -247,8 +247,7 @@ out: * e1000_init_function_pointers_82540 - Init func ptrs. * @hw: pointer to the HW structure * - * The only function explicitly called by the api module to initialize - * all function pointers and parameters. + * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82540(struct e1000_hw *hw) { @@ -263,8 +262,7 @@ void e1000_init_function_pointers_82540(struct e1000_hw *hw) * e1000_reset_hw_82540 - Reset hardware * @hw: pointer to the HW structure * - * This resets the hardware into a known state. This is a - * function pointer entry point called by the api module. + * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82540(struct e1000_hw *hw) { @@ -322,8 +320,7 @@ static s32 e1000_reset_hw_82540(struct e1000_hw *hw) * e1000_init_hw_82540 - Initialize hardware * @hw: pointer to the HW structure * - * This inits the hardware readying it for operation. This is a - * function pointer entry point called by the api module. + * This inits the hardware readying it for operation. **/ static s32 e1000_init_hw_82540(struct e1000_hw *hw) { @@ -406,8 +403,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw) * Calls the appropriate function to configure the link for auto-neg or forced * speed and duplex. Then we check for link, once link is established calls * to configure collision distance and flow control are called. If link is - * not established, we return -E1000_ERR_PHY (-2). This is a function - * pointer entry point called by the api module. + * not established, we return -E1000_ERR_PHY (-2). **/ static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw) { @@ -454,8 +450,7 @@ out: * Set the output amplitude to the value in the EEPROM and adjust the VCO * speed to improve Bit Error Rate (BER) performance. Configures collision * distance and flow control for fiber and serdes links. Upon successful - * setup, poll for link. This is a function pointer entry point called by - * the api module. + * setup, poll for link. **/ static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw) { @@ -650,34 +645,32 @@ static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw) **/ static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_82540"); e1000_clear_hw_cntrs_base_generic(hw); - temp = E1000_READ_REG(hw, E1000_PRC64); - temp = E1000_READ_REG(hw, E1000_PRC127); - temp = E1000_READ_REG(hw, E1000_PRC255); - temp = E1000_READ_REG(hw, E1000_PRC511); - temp = E1000_READ_REG(hw, E1000_PRC1023); - temp = E1000_READ_REG(hw, E1000_PRC1522); - temp = E1000_READ_REG(hw, E1000_PTC64); - temp = E1000_READ_REG(hw, E1000_PTC127); - temp = E1000_READ_REG(hw, E1000_PTC255); - temp = E1000_READ_REG(hw, E1000_PTC511); - temp = E1000_READ_REG(hw, E1000_PTC1023); - temp = E1000_READ_REG(hw, E1000_PTC1522); - - temp = E1000_READ_REG(hw, E1000_ALGNERRC); - temp = E1000_READ_REG(hw, E1000_RXERRC); - temp = E1000_READ_REG(hw, E1000_TNCRS); - temp = E1000_READ_REG(hw, E1000_CEXTERR); - temp = E1000_READ_REG(hw, E1000_TSCTC); - temp = E1000_READ_REG(hw, E1000_TSCTFC); - - temp = E1000_READ_REG(hw, E1000_MGTPRC); - temp = E1000_READ_REG(hw, E1000_MGTPDC); - temp = E1000_READ_REG(hw, E1000_MGTPTC); + E1000_READ_REG(hw, E1000_PRC64); + E1000_READ_REG(hw, E1000_PRC127); + E1000_READ_REG(hw, E1000_PRC255); + E1000_READ_REG(hw, E1000_PRC511); + E1000_READ_REG(hw, E1000_PRC1023); + E1000_READ_REG(hw, E1000_PRC1522); + E1000_READ_REG(hw, E1000_PTC64); + E1000_READ_REG(hw, E1000_PTC127); + E1000_READ_REG(hw, E1000_PTC255); + E1000_READ_REG(hw, E1000_PTC511); + E1000_READ_REG(hw, E1000_PTC1023); + E1000_READ_REG(hw, E1000_PTC1522); + + E1000_READ_REG(hw, E1000_ALGNERRC); + E1000_READ_REG(hw, E1000_RXERRC); + E1000_READ_REG(hw, E1000_TNCRS); + E1000_READ_REG(hw, E1000_CEXTERR); + E1000_READ_REG(hw, E1000_TSCTC); + E1000_READ_REG(hw, E1000_TSCTFC); + + E1000_READ_REG(hw, E1000_MGTPRC); + E1000_READ_REG(hw, E1000_MGTPDC); + E1000_READ_REG(hw, E1000_MGTPTC); } diff --git a/sys/dev/e1000/e1000_82541.c b/sys/dev/e1000/e1000_82541.c index 81e68cf..03d1103 100644 --- a/sys/dev/e1000/e1000_82541.c +++ b/sys/dev/e1000/e1000_82541.c @@ -32,10 +32,13 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* e1000_82541 - * e1000_82547 - * e1000_82541_rev_2 - * e1000_82547_rev_2 +/* + * 82541EI Gigabit Ethernet Controller + * 82541ER Gigabit Ethernet Controller + * 82541GI Gigabit Ethernet Controller + * 82541PI Gigabit Ethernet Controller + * 82547EI Gigabit Ethernet Controller + * 82547GI Gigabit Ethernet Controller */ #include "e1000_api.h" @@ -74,18 +77,9 @@ static const u16 e1000_igp_cable_length_table[] = (sizeof(e1000_igp_cable_length_table) / \ sizeof(e1000_igp_cable_length_table[0])) -struct e1000_dev_spec_82541 { - enum e1000_dsp_config dsp_config; - enum e1000_ffe_config ffe_config; - u16 spd_default; - bool phy_init_script; -}; - /** * e1000_init_phy_params_82541 - Init PHY func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_phy_params_82541(struct e1000_hw *hw) { @@ -129,8 +123,6 @@ out: /** * e1000_init_nvm_params_82541 - Init NVM func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw) { @@ -227,13 +219,10 @@ out: /** * e1000_init_mac_params_82541 - Init MAC func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_mac_params_82541(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; DEBUGFUNC("e1000_init_mac_params_82541"); @@ -250,6 +239,8 @@ static s32 e1000_init_mac_params_82541(struct e1000_hw *hw) /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; + /* function id */ + mac->ops.set_lan_id = e1000_set_lan_id_single_port; /* reset */ mac->ops.reset_hw = e1000_reset_hw_82541; /* hw initialization */ @@ -277,25 +268,17 @@ static s32 e1000_init_mac_params_82541(struct e1000_hw *hw) /* turn on/off LED */ mac->ops.led_on = e1000_led_on_generic; mac->ops.led_off = e1000_led_off_generic; - /* remove device */ - mac->ops.remove_device = e1000_remove_device_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541; - hw->dev_spec_size = sizeof(struct e1000_dev_spec_82541); - - /* Device-specific structure allocation */ - ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); - - return ret_val; + return E1000_SUCCESS; } /** * e1000_init_function_pointers_82541 - Init func ptrs. * @hw: pointer to the HW structure * - * The only function explicitly called by the api module to initialize - * all function pointers and parameters. + * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82541(struct e1000_hw *hw) { @@ -310,8 +293,7 @@ void e1000_init_function_pointers_82541(struct e1000_hw *hw) * e1000_reset_hw_82541 - Reset hardware * @hw: pointer to the HW structure * - * This resets the hardware into a known state. This is a - * function pointer entry point called by the api module. + * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82541(struct e1000_hw *hw) { @@ -388,8 +370,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw) * e1000_init_hw_82541 - Initialize hardware * @hw: pointer to the HW structure * - * This inits the hardware readying it for operation. This is a - * function pointer entry point called by the api module. + * This inits the hardware readying it for operation. **/ static s32 e1000_init_hw_82541(struct e1000_hw *hw) { @@ -452,7 +433,6 @@ static s32 e1000_init_hw_82541(struct e1000_hw *hw) * @duplex: pointer to duplex buffer * * Retrieve the current speed and duplex configuration. - * This is a function pointer entry point called by the api module. **/ static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, u16 *duplex) @@ -508,7 +488,6 @@ out: * semaphore (if necessary) and read/set/write the device control reset * bit in the PHY. Wait the appropriate delay time for the device to * reset and release the semaphore (if necessary). - * This is a function pointer entry point called by the api module. **/ static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw) { @@ -542,13 +521,12 @@ out: * Calls the appropriate function to configure the link for auto-neg or forced * speed and duplex. Then we check for link, once link is established calls * to configure collision distance and flow control are called. If link is - * not established, we return -E1000_ERR_PHY (-2). This is a function - * pointer entry point called by the api module. + * not established, we return -E1000_ERR_PHY (-2). **/ static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - struct e1000_dev_spec_82541 *dev_spec; + struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; s32 ret_val; u32 ctrl, ledctl; @@ -561,8 +539,6 @@ static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw) hw->phy.reset_disable = FALSE; - dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; - /* Earlier revs of the IGP phy require us to force MDI. */ if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) { dev_spec->dsp_config = e1000_dsp_config_disabled; @@ -597,8 +573,7 @@ out: * @hw: pointer to the HW structure * * This checks the link condition of the adapter and stores the - * results in the hw->mac structure. This is a function pointer entry - * point called by the api module. + * results in the hw->mac structure. **/ static s32 e1000_check_for_link_82541(struct e1000_hw *hw) { @@ -684,13 +659,12 @@ out: * * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a * gigabit link is achieved to improve link quality. - * This is a function pointer entry point called by the api module. **/ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, bool link_up) { struct e1000_phy_info *phy = &hw->phy; - struct e1000_dev_spec_82541 *dev_spec; + struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; s32 ret_val; u32 idle_errs = 0; u16 phy_data, phy_saved_data, speed, duplex, i; @@ -703,8 +677,6 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, DEBUGFUNC("e1000_config_dsp_after_link_change_82541"); - dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; - if (link_up) { ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex); if (ret_val) { @@ -898,8 +870,7 @@ out: * cable. By reading the AGC registers, which represent the * combination of coarse and fine gain value, the value can be put * into a lookup table to obtain the approximate cable length - * for each channel. This is a function pointer entry point called by the - * api module. + * for each channel. **/ static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw) { @@ -973,8 +944,7 @@ out: * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is - * maintained. This is a function pointer entry point called by the - * api module. + * maintained. **/ static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active) { @@ -1067,18 +1037,15 @@ out: * @hw: pointer to the HW structure * * This prepares the SW controllable LED for use and saves the current state - * of the LED so it can be later restored. This is a function pointer entry - * point called by the api module. + * of the LED so it can be later restored. **/ static s32 e1000_setup_led_82541(struct e1000_hw *hw) { - struct e1000_dev_spec_82541 *dev_spec; + struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; s32 ret_val; DEBUGFUNC("e1000_setup_led_82541"); - dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; - ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO, &dev_spec->spd_default); @@ -1103,18 +1070,15 @@ out: * @hw: pointer to the HW structure * * Remove the current LED configuration and set the LED configuration - * to the default value, saved from the EEPROM. This is a function pointer - * entry point called by the api module. + * to the default value, saved from the EEPROM. **/ static s32 e1000_cleanup_led_82541(struct e1000_hw *hw) { - struct e1000_dev_spec_82541 *dev_spec; + struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; s32 ret_val; DEBUGFUNC("e1000_cleanup_led_82541"); - dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; - ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO, dev_spec->spd_default); @@ -1135,14 +1099,12 @@ out: **/ static s32 e1000_phy_init_script_82541(struct e1000_hw *hw) { - struct e1000_dev_spec_82541 *dev_spec; + struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; u32 ret_val; u16 phy_saved_data; DEBUGFUNC("e1000_phy_init_script_82541"); - dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; - if (!dev_spec->phy_init_script) { ret_val = E1000_SUCCESS; goto out; @@ -1248,11 +1210,11 @@ out: * @state: boolean value used to enable/disable PHY init script * * Allows the driver to enable/disable the PHY init script, if the PHY is an - * IGP PHY. This is a function pointer entry point called by the api module. + * IGP PHY. **/ void e1000_init_script_state_82541(struct e1000_hw *hw, bool state) { - struct e1000_dev_spec_82541 *dev_spec; + struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; DEBUGFUNC("e1000_init_script_state_82541"); @@ -1261,13 +1223,6 @@ void e1000_init_script_state_82541(struct e1000_hw *hw, bool state) goto out; } - dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - goto out; - } - dev_spec->phy_init_script = state; out: @@ -1298,33 +1253,31 @@ static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw) **/ static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_82541"); e1000_clear_hw_cntrs_base_generic(hw); - temp = E1000_READ_REG(hw, E1000_PRC64); - temp = E1000_READ_REG(hw, E1000_PRC127); - temp = E1000_READ_REG(hw, E1000_PRC255); - temp = E1000_READ_REG(hw, E1000_PRC511); - temp = E1000_READ_REG(hw, E1000_PRC1023); - temp = E1000_READ_REG(hw, E1000_PRC1522); - temp = E1000_READ_REG(hw, E1000_PTC64); - temp = E1000_READ_REG(hw, E1000_PTC127); - temp = E1000_READ_REG(hw, E1000_PTC255); - temp = E1000_READ_REG(hw, E1000_PTC511); - temp = E1000_READ_REG(hw, E1000_PTC1023); - temp = E1000_READ_REG(hw, E1000_PTC1522); - - temp = E1000_READ_REG(hw, E1000_ALGNERRC); - temp = E1000_READ_REG(hw, E1000_RXERRC); - temp = E1000_READ_REG(hw, E1000_TNCRS); - temp = E1000_READ_REG(hw, E1000_CEXTERR); - temp = E1000_READ_REG(hw, E1000_TSCTC); - temp = E1000_READ_REG(hw, E1000_TSCTFC); - - temp = E1000_READ_REG(hw, E1000_MGTPRC); - temp = E1000_READ_REG(hw, E1000_MGTPDC); - temp = E1000_READ_REG(hw, E1000_MGTPTC); + E1000_READ_REG(hw, E1000_PRC64); + E1000_READ_REG(hw, E1000_PRC127); + E1000_READ_REG(hw, E1000_PRC255); + E1000_READ_REG(hw, E1000_PRC511); + E1000_READ_REG(hw, E1000_PRC1023); + E1000_READ_REG(hw, E1000_PRC1522); + E1000_READ_REG(hw, E1000_PTC64); + E1000_READ_REG(hw, E1000_PTC127); + E1000_READ_REG(hw, E1000_PTC255); + E1000_READ_REG(hw, E1000_PTC511); + E1000_READ_REG(hw, E1000_PTC1023); + E1000_READ_REG(hw, E1000_PTC1522); + + E1000_READ_REG(hw, E1000_ALGNERRC); + E1000_READ_REG(hw, E1000_RXERRC); + E1000_READ_REG(hw, E1000_TNCRS); + E1000_READ_REG(hw, E1000_CEXTERR); + E1000_READ_REG(hw, E1000_TSCTC); + E1000_READ_REG(hw, E1000_TSCTFC); + + E1000_READ_REG(hw, E1000_MGTPRC); + E1000_READ_REG(hw, E1000_MGTPDC); + E1000_READ_REG(hw, E1000_MGTPTC); } diff --git a/sys/dev/e1000/e1000_82542.c b/sys/dev/e1000/e1000_82542.c index 0f76202..3ce3657 100644 --- a/sys/dev/e1000/e1000_82542.c +++ b/sys/dev/e1000/e1000_82542.c @@ -32,7 +32,8 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* e1000_82542 (rev 1 & 2) +/* + * 82542 Gigabit Ethernet Controller */ #include "e1000_api.h" @@ -49,15 +50,9 @@ static s32 e1000_led_off_82542(struct e1000_hw *hw); static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index); static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw); -struct e1000_dev_spec_82542 { - bool dma_fairness; -}; - /** * e1000_init_phy_params_82542 - Init PHY func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_phy_params_82542(struct e1000_hw *hw) { @@ -74,8 +69,6 @@ static s32 e1000_init_phy_params_82542(struct e1000_hw *hw) /** * e1000_init_nvm_params_82542 - Init NVM func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_nvm_params_82542(struct e1000_hw *hw) { @@ -102,13 +95,10 @@ static s32 e1000_init_nvm_params_82542(struct e1000_hw *hw) /** * e1000_init_mac_params_82542 - Init MAC func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_mac_params_82542(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_mac_params_82542"); @@ -124,6 +114,8 @@ static s32 e1000_init_mac_params_82542(struct e1000_hw *hw) /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_82542; + /* function id */ + mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; /* reset */ mac->ops.reset_hw = e1000_reset_hw_82542; /* hw initialization */ @@ -147,27 +139,19 @@ static s32 e1000_init_mac_params_82542(struct e1000_hw *hw) /* turn on/off LED */ mac->ops.led_on = e1000_led_on_82542; mac->ops.led_off = e1000_led_off_82542; - /* remove device */ - mac->ops.remove_device = e1000_remove_device_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82542; /* link info */ mac->ops.get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes_generic; - hw->dev_spec_size = sizeof(struct e1000_dev_spec_82542); - - /* Device-specific structure allocation */ - ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); - - return ret_val; + return E1000_SUCCESS; } /** * e1000_init_function_pointers_82542 - Init func ptrs. * @hw: pointer to the HW structure * - * The only function explicitly called by the api module to initialize - * all function pointers and parameters. + * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82542(struct e1000_hw *hw) { @@ -183,8 +167,7 @@ void e1000_init_function_pointers_82542(struct e1000_hw *hw) * @hw: pointer to the HW structure * * This will obtain information about the HW bus for which the - * adapter is attached and stores it in the hw structure. This is a function - * pointer entry point called by the api module. + * adapter is attached and stores it in the hw structure. **/ static s32 e1000_get_bus_info_82542(struct e1000_hw *hw) { @@ -201,8 +184,7 @@ static s32 e1000_get_bus_info_82542(struct e1000_hw *hw) * e1000_reset_hw_82542 - Reset hardware * @hw: pointer to the HW structure * - * This resets the hardware into a known state. This is a - * function pointer entry point called by the api module. + * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82542(struct e1000_hw *hw) { @@ -253,21 +235,18 @@ static s32 e1000_reset_hw_82542(struct e1000_hw *hw) * e1000_init_hw_82542 - Initialize hardware * @hw: pointer to the HW structure * - * This inits the hardware readying it for operation. This is a - * function pointer entry point called by the api module. + * This inits the hardware readying it for operation. **/ static s32 e1000_init_hw_82542(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - struct e1000_dev_spec_82542 *dev_spec; + struct e1000_dev_spec_82542 *dev_spec = &hw->dev_spec._82542; s32 ret_val = E1000_SUCCESS; u32 ctrl; u16 i; DEBUGFUNC("e1000_init_hw_82542"); - dev_spec = (struct e1000_dev_spec_82542 *)hw->dev_spec; - /* Disabling VLAN filtering */ E1000_WRITE_REG(hw, E1000_VET, 0); mac->ops.clear_vfta(hw); @@ -330,8 +309,7 @@ static s32 e1000_init_hw_82542(struct e1000_hw *hw) * control. Calls the appropriate media-specific link configuration * function. Assuming the adapter has a valid link partner, a valid link * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. This is a function - * pointer entry point called by the api module. + * and the transmitter and receiver are not enabled. **/ static s32 e1000_setup_link_82542(struct e1000_hw *hw) { @@ -344,19 +322,19 @@ static s32 e1000_setup_link_82542(struct e1000_hw *hw) if (ret_val) goto out; - hw->fc.type &= ~e1000_fc_tx_pause; + hw->fc.requested_mode &= ~e1000_fc_tx_pause; if (mac->report_tx_early == 1) - hw->fc.type &= ~e1000_fc_rx_pause; + hw->fc.requested_mode &= ~e1000_fc_rx_pause; /* - * We want to save off the original Flow Control configuration just in - * case we get disconnected and then reconnected into a different hub - * or switch with different Flow Control capabilities. + * Save off the requested flow control mode for use later. Depending + * on the link partner's capabilities, we may or may not use this mode. */ - hw->fc.original_type = hw->fc.type; + hw->fc.current_mode = hw->fc.requested_mode; - DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.type); + DEBUGOUT1("After fix-ups FlowControl is now = %x\n", + hw->fc.current_mode); /* Call the necessary subroutine to configure the link. */ ret_val = mac->ops.setup_physical_interface(hw); @@ -387,8 +365,7 @@ out: * e1000_led_on_82542 - Turn on SW controllable LED * @hw: pointer to the HW structure * - * Turns the SW defined LED on. This is a function pointer entry point - * called by the api module. + * Turns the SW defined LED on. **/ static s32 e1000_led_on_82542(struct e1000_hw *hw) { @@ -407,8 +384,7 @@ static s32 e1000_led_on_82542(struct e1000_hw *hw) * e1000_led_off_82542 - Turn off SW controllable LED * @hw: pointer to the HW structure * - * Turns the SW defined LED off. This is a function pointer entry point - * called by the api module. + * Turns the SW defined LED off. **/ static s32 e1000_led_off_82542(struct e1000_hw *hw) { @@ -449,10 +425,8 @@ static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index) rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) { - if (!hw->mac.disable_av) - rar_high |= E1000_RAH_AV; - } + if (rar_low || rar_high) + rar_high |= E1000_RAH_AV; E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low); E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high); @@ -563,22 +537,20 @@ u32 e1000_translate_register_82542(u32 reg) **/ static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_82542"); e1000_clear_hw_cntrs_base_generic(hw); - temp = E1000_READ_REG(hw, E1000_PRC64); - temp = E1000_READ_REG(hw, E1000_PRC127); - temp = E1000_READ_REG(hw, E1000_PRC255); - temp = E1000_READ_REG(hw, E1000_PRC511); - temp = E1000_READ_REG(hw, E1000_PRC1023); - temp = E1000_READ_REG(hw, E1000_PRC1522); - temp = E1000_READ_REG(hw, E1000_PTC64); - temp = E1000_READ_REG(hw, E1000_PTC127); - temp = E1000_READ_REG(hw, E1000_PTC255); - temp = E1000_READ_REG(hw, E1000_PTC511); - temp = E1000_READ_REG(hw, E1000_PTC1023); - temp = E1000_READ_REG(hw, E1000_PTC1522); + E1000_READ_REG(hw, E1000_PRC64); + E1000_READ_REG(hw, E1000_PRC127); + E1000_READ_REG(hw, E1000_PRC255); + E1000_READ_REG(hw, E1000_PRC511); + E1000_READ_REG(hw, E1000_PRC1023); + E1000_READ_REG(hw, E1000_PRC1522); + E1000_READ_REG(hw, E1000_PTC64); + E1000_READ_REG(hw, E1000_PTC127); + E1000_READ_REG(hw, E1000_PTC255); + E1000_READ_REG(hw, E1000_PTC511); + E1000_READ_REG(hw, E1000_PTC1023); + E1000_READ_REG(hw, E1000_PTC1522); } diff --git a/sys/dev/e1000/e1000_82543.c b/sys/dev/e1000/e1000_82543.c index 80d850f..97c7f3b 100644 --- a/sys/dev/e1000/e1000_82543.c +++ b/sys/dev/e1000/e1000_82543.c @@ -32,8 +32,13 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* e1000_82543 - * e1000_82544 +/* + * 82543GC Gigabit Ethernet Controller (Fiber) + * 82543GC Gigabit Ethernet Controller (Copper) + * 82544EI Gigabit Ethernet Controller (Copper) + * 82544EI Gigabit Ethernet Controller (Fiber) + * 82544GC Gigabit Ethernet Controller (Copper) + * 82544GC Gigabit Ethernet Controller (LOM) */ #include "e1000_api.h" @@ -71,17 +76,9 @@ static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data, static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw); static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state); -struct e1000_dev_spec_82543 { - u32 tbi_compatibility; - bool dma_fairness; - bool init_phy_disabled; -}; - /** * e1000_init_phy_params_82543 - Init PHY func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_phy_params_82543(struct e1000_hw *hw) { @@ -165,8 +162,6 @@ out: /** * e1000_init_nvm_params_82543 - Init NVM func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw) { @@ -193,13 +188,10 @@ static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw) /** * e1000_init_mac_params_82543 - Init MAC func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_mac_params_82543(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; DEBUGFUNC("e1000_init_mac_params_82543"); @@ -223,6 +215,8 @@ static s32 e1000_init_mac_params_82543(struct e1000_hw *hw) /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; + /* function id */ + mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; /* reset */ mac->ops.reset_hw = e1000_reset_hw_82543; /* hw initialization */ @@ -255,33 +249,22 @@ static s32 e1000_init_mac_params_82543(struct e1000_hw *hw) /* turn on/off LED */ mac->ops.led_on = e1000_led_on_82543; mac->ops.led_off = e1000_led_off_82543; - /* remove device */ - mac->ops.remove_device = e1000_remove_device_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82543; - hw->dev_spec_size = sizeof(struct e1000_dev_spec_82543); - - /* Device-specific structure allocation */ - ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); - if (ret_val) - goto out; - /* Set tbi compatibility */ if ((hw->mac.type != e1000_82543) || (hw->phy.media_type == e1000_media_type_fiber)) e1000_set_tbi_compatibility_82543(hw, FALSE); -out: - return ret_val; + return E1000_SUCCESS; } /** * e1000_init_function_pointers_82543 - Init func ptrs. * @hw: pointer to the HW structure * - * The only function explicitly called by the api module to initialize - * all function pointers and parameters. + * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82543(struct e1000_hw *hw) { @@ -301,7 +284,7 @@ void e1000_init_function_pointers_82543(struct e1000_hw *hw) **/ static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw) { - struct e1000_dev_spec_82543 *dev_spec; + struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; bool state = FALSE; DEBUGFUNC("e1000_tbi_compatibility_enabled_82543"); @@ -311,13 +294,6 @@ static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw) goto out; } - dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - goto out; - } - state = (dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED) ? TRUE : FALSE; @@ -334,7 +310,7 @@ out: **/ void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state) { - struct e1000_dev_spec_82543 *dev_spec; + struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; DEBUGFUNC("e1000_set_tbi_compatibility_82543"); @@ -343,13 +319,6 @@ void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state) goto out; } - dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - goto out; - } - if (state) dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED; else @@ -368,7 +337,7 @@ out: **/ bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw) { - struct e1000_dev_spec_82543 *dev_spec; + struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; bool state = FALSE; DEBUGFUNC("e1000_tbi_sbp_enabled_82543"); @@ -378,13 +347,6 @@ bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw) goto out; } - dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - goto out; - } - state = (dev_spec->tbi_compatibility & TBI_SBP_ENABLED) ? TRUE : FALSE; @@ -401,12 +363,10 @@ out: **/ static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state) { - struct e1000_dev_spec_82543 *dev_spec; + struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; DEBUGFUNC("e1000_set_tbi_sbp_82543"); - dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec; - if (state && e1000_tbi_compatibility_enabled_82543(hw)) dev_spec->tbi_compatibility |= TBI_SBP_ENABLED; else @@ -424,7 +384,7 @@ static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state) **/ static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw) { - struct e1000_dev_spec_82543 *dev_spec; + struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; bool ret_val; DEBUGFUNC("e1000_init_phy_disabled_82543"); @@ -434,14 +394,6 @@ static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw) goto out; } - dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - ret_val = FALSE; - goto out; - } - ret_val = dev_spec->init_phy_disabled; out: @@ -904,7 +856,7 @@ out: * Sets the PHY_RESET_DIR bit in the extended device control register * to put the PHY into a reset and waits for completion. Once the reset * has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out - * of reset. This is a function pointer entry point called by the api module. + * of reset. **/ static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw) { @@ -944,8 +896,7 @@ static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw) * e1000_reset_hw_82543 - Reset hardware * @hw: pointer to the HW structure * - * This resets the hardware into a known state. This is a - * function pointer entry point called by the api module. + * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82543(struct e1000_hw *hw) { @@ -1005,21 +956,13 @@ static s32 e1000_reset_hw_82543(struct e1000_hw *hw) static s32 e1000_init_hw_82543(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - struct e1000_dev_spec_82543 *dev_spec; + struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; u32 ctrl; s32 ret_val; u16 i; DEBUGFUNC("e1000_init_hw_82543"); - dev_spec = (struct e1000_dev_spec_82543 *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - /* Disabling VLAN filtering */ E1000_WRITE_REG(hw, E1000_VET, 0); mac->ops.clear_vfta(hw); @@ -1057,7 +1000,6 @@ static s32 e1000_init_hw_82543(struct e1000_hw *hw) */ e1000_clear_hw_cntrs_82543(hw); -out: return ret_val; } @@ -1577,8 +1519,7 @@ static void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value) * e1000_led_on_82543 - Turn on SW controllable LED * @hw: pointer to the HW structure * - * Turns the SW defined LED on. This is a function pointer entry point - * called by the api module. + * Turns the SW defined LED on. **/ static s32 e1000_led_on_82543(struct e1000_hw *hw) { @@ -1605,8 +1546,7 @@ static s32 e1000_led_on_82543(struct e1000_hw *hw) * e1000_led_off_82543 - Turn off SW controllable LED * @hw: pointer to the HW structure * - * Turns the SW defined LED off. This is a function pointer entry point - * called by the api module. + * Turns the SW defined LED off. **/ static s32 e1000_led_off_82543(struct e1000_hw *hw) { @@ -1636,29 +1576,27 @@ static s32 e1000_led_off_82543(struct e1000_hw *hw) **/ static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_82543"); e1000_clear_hw_cntrs_base_generic(hw); - temp = E1000_READ_REG(hw, E1000_PRC64); - temp = E1000_READ_REG(hw, E1000_PRC127); - temp = E1000_READ_REG(hw, E1000_PRC255); - temp = E1000_READ_REG(hw, E1000_PRC511); - temp = E1000_READ_REG(hw, E1000_PRC1023); - temp = E1000_READ_REG(hw, E1000_PRC1522); - temp = E1000_READ_REG(hw, E1000_PTC64); - temp = E1000_READ_REG(hw, E1000_PTC127); - temp = E1000_READ_REG(hw, E1000_PTC255); - temp = E1000_READ_REG(hw, E1000_PTC511); - temp = E1000_READ_REG(hw, E1000_PTC1023); - temp = E1000_READ_REG(hw, E1000_PTC1522); - - temp = E1000_READ_REG(hw, E1000_ALGNERRC); - temp = E1000_READ_REG(hw, E1000_RXERRC); - temp = E1000_READ_REG(hw, E1000_TNCRS); - temp = E1000_READ_REG(hw, E1000_CEXTERR); - temp = E1000_READ_REG(hw, E1000_TSCTC); - temp = E1000_READ_REG(hw, E1000_TSCTFC); + E1000_READ_REG(hw, E1000_PRC64); + E1000_READ_REG(hw, E1000_PRC127); + E1000_READ_REG(hw, E1000_PRC255); + E1000_READ_REG(hw, E1000_PRC511); + E1000_READ_REG(hw, E1000_PRC1023); + E1000_READ_REG(hw, E1000_PRC1522); + E1000_READ_REG(hw, E1000_PTC64); + E1000_READ_REG(hw, E1000_PTC127); + E1000_READ_REG(hw, E1000_PTC255); + E1000_READ_REG(hw, E1000_PTC511); + E1000_READ_REG(hw, E1000_PTC1023); + E1000_READ_REG(hw, E1000_PTC1522); + + E1000_READ_REG(hw, E1000_ALGNERRC); + E1000_READ_REG(hw, E1000_RXERRC); + E1000_READ_REG(hw, E1000_TNCRS); + E1000_READ_REG(hw, E1000_CEXTERR); + E1000_READ_REG(hw, E1000_TSCTC); + E1000_READ_REG(hw, E1000_TSCTFC); } diff --git a/sys/dev/e1000/e1000_82571.c b/sys/dev/e1000/e1000_82571.c index f4f6485..db7852a 100644 --- a/sys/dev/e1000/e1000_82571.c +++ b/sys/dev/e1000/e1000_82571.c @@ -32,10 +32,20 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* e1000_82571 - * e1000_82572 - * e1000_82573 - * e1000_82574 +/* + * 82571EB Gigabit Ethernet Controller + * 82571EB Gigabit Ethernet Controller (Copper) + * 82571EB Gigabit Ethernet Controller (Fiber) + * 82571EB Dual Port Gigabit Mezzanine Adapter + * 82571EB Quad Port Gigabit Mezzanine Adapter + * 82571PT Gigabit PT Quad Port Server ExpressModule + * 82572EI Gigabit Ethernet Controller (Copper) + * 82572EI Gigabit Ethernet Controller (Fiber) + * 82572EI Gigabit Ethernet Controller + * 82573V Gigabit Ethernet Controller (Copper) + * 82573E Gigabit Ethernet Controller (Copper) + * 82573L Gigabit Ethernet Controller + * 82574L Gigabit Network Connection */ #include "e1000_api.h" @@ -75,15 +85,9 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw); static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw); -struct e1000_dev_spec_82571 { - bool laa_is_present; -}; - /** * e1000_init_phy_params_82571 - Init PHY func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) { @@ -93,7 +97,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) DEBUGFUNC("e1000_init_phy_params_82571"); if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; + phy->type = e1000_phy_none; goto out; } @@ -164,7 +168,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) /* This uses above function pointers */ ret_val = e1000_get_phy_id_82571(hw); /* Verify PHY ID */ - if (phy->id != BME1000_E_PHY_ID_R2) { + if (phy->id != BME1000_E_PHY_ID_R2) { ret_val = -E1000_ERR_PHY; DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id); goto out; @@ -183,8 +187,6 @@ out: /** * e1000_init_nvm_params_82571 - Init NVM func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) { @@ -194,19 +196,19 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) DEBUGFUNC("e1000_init_nvm_params_82571"); - nvm->opcode_bits = 8; - nvm->delay_usec = 1; + nvm->opcode_bits = 8; + nvm->delay_usec = 1; switch (nvm->override) { case e1000_nvm_override_spi_large: - nvm->page_size = 32; + nvm->page_size = 32; nvm->address_bits = 16; break; case e1000_nvm_override_spi_small: - nvm->page_size = 8; + nvm->page_size = 8; nvm->address_bits = 8; break; default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; + nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; break; } @@ -227,7 +229,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) } /* Fall Through */ default: - nvm->type = e1000_nvm_eeprom_spi; + nvm->type = e1000_nvm_eeprom_spi; size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); /* @@ -258,8 +260,6 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) /** * e1000_init_mac_params_82571 - Init MAC func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) { @@ -301,6 +301,15 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; + /* function id */ + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + mac->ops.set_lan_id = e1000_set_lan_id_single_port; + break; + default: + break; + } /* reset */ mac->ops.reset_hw = e1000_reset_hw_82571; /* hw initialization */ @@ -363,8 +372,6 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) break; } mac->ops.led_off = e1000_led_off_generic; - /* remove device */ - mac->ops.remove_device = e1000_remove_device_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82571; /* link info */ @@ -373,11 +380,6 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) ? e1000_get_speed_and_duplex_copper_generic : e1000_get_speed_and_duplex_fiber_serdes_generic; - hw->dev_spec_size = sizeof(struct e1000_dev_spec_82571); - - /* Device-specific structure allocation */ - ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); - out: return ret_val; } @@ -386,8 +388,7 @@ out: * e1000_init_function_pointers_82571 - Init func ptrs. * @hw: pointer to the HW structure * - * The only function explicitly called by the api module to initialize - * all function pointers and parameters. + * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82571(struct e1000_hw *hw) { @@ -844,8 +845,7 @@ out: * e1000_reset_hw_82571 - Reset hardware * @hw: pointer to the HW structure * - * This resets the hardware into a known state. This is a - * function pointer entry point called by the api module. + * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) { @@ -860,9 +860,8 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); - if (ret_val) { + if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); - } DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); @@ -1022,9 +1021,6 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) DEBUGFUNC("e1000_initialize_hw_bits_82571"); - if (hw->mac.disable_hw_init_bits) - goto out; - /* Transmit Descriptor Control 0 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); reg |= (1 << 22); @@ -1084,10 +1080,9 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) if (hw->mac.type == e1000_82574) { reg = E1000_READ_REG(hw, E1000_GCR); reg |= (1 << 22); - E1000_WRITE_REG(hw, E1000_GCR, reg); + E1000_WRITE_REG(hw, E1000_GCR, reg); } -out: return; } @@ -1149,13 +1144,13 @@ static bool e1000_check_mng_mode_82574(struct e1000_hw *hw) DEBUGFUNC("e1000_check_mng_mode_82574"); hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data); - return ((data & E1000_NVM_INIT_CTRL2_MNGM) != 0); + return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0; } /** * e1000_led_on_82574 - Turn LED on * @hw: pointer to the HW structure - * + * * Turn LED on. **/ static s32 e1000_led_on_82574(struct e1000_hw *hw) @@ -1167,8 +1162,8 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw) ctrl = hw->mac.ledctl_mode2; if (!(E1000_STATUS_LU & E1000_READ_REG(hw, E1000_STATUS))) { - /* - * If no link, then turn LED on by setting the invert bit + /* + * If no link, then turn LED on by setting the invert bit * for each LED that's "on" (0x0E) in ledctl_mode2. */ for (i = 0; i < 4; i++) @@ -1227,8 +1222,8 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw) * set it to full. */ if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) && - hw->fc.type == e1000_fc_default) - hw->fc.type = e1000_fc_full; + hw->fc.requested_mode == e1000_fc_default) + hw->fc.requested_mode = e1000_fc_full; return e1000_setup_link_generic(hw); } @@ -1347,20 +1342,12 @@ out: **/ bool e1000_get_laa_state_82571(struct e1000_hw *hw) { - struct e1000_dev_spec_82571 *dev_spec; - bool state = FALSE; - DEBUGFUNC("e1000_get_laa_state_82571"); if (hw->mac.type != e1000_82571) - goto out; + return FALSE; - dev_spec = (struct e1000_dev_spec_82571 *)hw->dev_spec; - - state = dev_spec->laa_is_present; - -out: - return state; + return hw->dev_spec._82571.laa_is_present; } /** @@ -1372,19 +1359,15 @@ out: **/ void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state) { - struct e1000_dev_spec_82571 *dev_spec; - DEBUGFUNC("e1000_set_laa_state_82571"); if (hw->mac.type != e1000_82571) - goto out; - - dev_spec = (struct e1000_dev_spec_82571 *)hw->dev_spec; + return; - dev_spec->laa_is_present = state; + hw->dev_spec._82571.laa_is_present = state; /* If workaround is activated... */ - if (state) { + if (state) /* * Hold a copy of the LAA in RAR[14] This is done so that * between the time RAR[0] gets clobbered and the time it @@ -1394,9 +1377,6 @@ void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state) */ e1000_rar_set_generic(hw, hw->mac.addr, hw->mac.rar_entry_count - 1); - } - -out: return; } @@ -1500,43 +1480,42 @@ static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw) **/ static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_82571"); e1000_clear_hw_cntrs_base_generic(hw); - temp = E1000_READ_REG(hw, E1000_PRC64); - temp = E1000_READ_REG(hw, E1000_PRC127); - temp = E1000_READ_REG(hw, E1000_PRC255); - temp = E1000_READ_REG(hw, E1000_PRC511); - temp = E1000_READ_REG(hw, E1000_PRC1023); - temp = E1000_READ_REG(hw, E1000_PRC1522); - temp = E1000_READ_REG(hw, E1000_PTC64); - temp = E1000_READ_REG(hw, E1000_PTC127); - temp = E1000_READ_REG(hw, E1000_PTC255); - temp = E1000_READ_REG(hw, E1000_PTC511); - temp = E1000_READ_REG(hw, E1000_PTC1023); - temp = E1000_READ_REG(hw, E1000_PTC1522); - - temp = E1000_READ_REG(hw, E1000_ALGNERRC); - temp = E1000_READ_REG(hw, E1000_RXERRC); - temp = E1000_READ_REG(hw, E1000_TNCRS); - temp = E1000_READ_REG(hw, E1000_CEXTERR); - temp = E1000_READ_REG(hw, E1000_TSCTC); - temp = E1000_READ_REG(hw, E1000_TSCTFC); - - temp = E1000_READ_REG(hw, E1000_MGTPRC); - temp = E1000_READ_REG(hw, E1000_MGTPDC); - temp = E1000_READ_REG(hw, E1000_MGTPTC); - - temp = E1000_READ_REG(hw, E1000_IAC); - temp = E1000_READ_REG(hw, E1000_ICRXOC); - - temp = E1000_READ_REG(hw, E1000_ICRXPTC); - temp = E1000_READ_REG(hw, E1000_ICRXATC); - temp = E1000_READ_REG(hw, E1000_ICTXPTC); - temp = E1000_READ_REG(hw, E1000_ICTXATC); - temp = E1000_READ_REG(hw, E1000_ICTXQEC); - temp = E1000_READ_REG(hw, E1000_ICTXQMTC); - temp = E1000_READ_REG(hw, E1000_ICRXDMTC); + + E1000_READ_REG(hw, E1000_PRC64); + E1000_READ_REG(hw, E1000_PRC127); + E1000_READ_REG(hw, E1000_PRC255); + E1000_READ_REG(hw, E1000_PRC511); + E1000_READ_REG(hw, E1000_PRC1023); + E1000_READ_REG(hw, E1000_PRC1522); + E1000_READ_REG(hw, E1000_PTC64); + E1000_READ_REG(hw, E1000_PTC127); + E1000_READ_REG(hw, E1000_PTC255); + E1000_READ_REG(hw, E1000_PTC511); + E1000_READ_REG(hw, E1000_PTC1023); + E1000_READ_REG(hw, E1000_PTC1522); + + E1000_READ_REG(hw, E1000_ALGNERRC); + E1000_READ_REG(hw, E1000_RXERRC); + E1000_READ_REG(hw, E1000_TNCRS); + E1000_READ_REG(hw, E1000_CEXTERR); + E1000_READ_REG(hw, E1000_TSCTC); + E1000_READ_REG(hw, E1000_TSCTFC); + + E1000_READ_REG(hw, E1000_MGTPRC); + E1000_READ_REG(hw, E1000_MGTPDC); + E1000_READ_REG(hw, E1000_MGTPTC); + + E1000_READ_REG(hw, E1000_IAC); + E1000_READ_REG(hw, E1000_ICRXOC); + + E1000_READ_REG(hw, E1000_ICRXPTC); + E1000_READ_REG(hw, E1000_ICRXATC); + E1000_READ_REG(hw, E1000_ICTXPTC); + E1000_READ_REG(hw, E1000_ICTXATC); + E1000_READ_REG(hw, E1000_ICTXQEC); + E1000_READ_REG(hw, E1000_ICTXQMTC); + E1000_READ_REG(hw, E1000_ICRXDMTC); } diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c index 2fbc0c3..3d16447 100644 --- a/sys/dev/e1000/e1000_82575.c +++ b/sys/dev/e1000/e1000_82575.c @@ -32,8 +32,11 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* e1000_82575 - * e1000_82576 +/* + * 82575EB Gigabit Network Connection + * 82575EB Gigabit Backplane Connection + * 82575GB Gigabit Network Connection + * 82576 Gigabit Network Connection */ #include "e1000_api.h" @@ -77,18 +80,11 @@ static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count); static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, u32 rar_used_count, u32 rar_count); -void e1000_remove_device_82575(struct e1000_hw *hw); void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw); -struct e1000_dev_spec_82575 { - bool sgmii_active; -}; - /** * e1000_init_phy_params_82575 - Init PHY func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) { @@ -158,8 +154,6 @@ out: /** * e1000_init_nvm_params_82575 - Init NVM func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) { @@ -217,27 +211,15 @@ static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) /** * e1000_init_mac_params_82575 - Init MAC func ptrs. * @hw: pointer to the HW structure - * - * This is a function pointer entry point called by the api module. **/ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - struct e1000_dev_spec_82575 *dev_spec; + struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; u32 ctrl_ext = 0; - s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_mac_params_82575"); - hw->dev_spec_size = sizeof(struct e1000_dev_spec_82575); - - /* Device-specific structure allocation */ - ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); - if (ret_val) - goto out; - - dev_spec = (struct e1000_dev_spec_82575 *)hw->dev_spec; - /* Set media type */ /* * The 82575 uses bits 22:23 for link mode. The mode can be changed @@ -315,23 +297,19 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) /* turn on/off LED */ mac->ops.led_on = e1000_led_on_generic; mac->ops.led_off = e1000_led_off_generic; - /* remove device */ - mac->ops.remove_device = e1000_remove_device_82575; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_82575; -out: - return ret_val; + return E1000_SUCCESS; } /** * e1000_init_function_pointers_82575 - Init func ptrs. * @hw: pointer to the HW structure * - * The only function explicitly called by the api module to initialize - * all function pointers and parameters. + * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82575(struct e1000_hw *hw) { @@ -346,8 +324,7 @@ void e1000_init_function_pointers_82575(struct e1000_hw *hw) * e1000_acquire_phy_82575 - Acquire rights to access PHY * @hw: pointer to the HW structure * - * Acquire access rights to the correct PHY. This is a - * function pointer entry point called by the api module. + * Acquire access rights to the correct PHY. **/ static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) { @@ -364,8 +341,7 @@ static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) * e1000_release_phy_82575 - Release rights to access PHY * @hw: pointer to the HW structure * - * A wrapper to release access rights to the correct PHY. This is a - * function pointer entry point called by the api module. + * A wrapper to release access rights to the correct PHY. **/ static void e1000_release_phy_82575(struct e1000_hw *hw) { @@ -1032,7 +1008,7 @@ static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw, /* Load any remaining multicast addresses into the hash table. */ for (; mc_addr_count > 0; mc_addr_count--) { - hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list); + hash_value = e1000_hash_mc_addr(hw, mc_addr_list); DEBUGOUT1("Hash value = 0x%03X\n", hash_value); hw->mac.ops.mta_set(hw, hash_value); mc_addr_list += ETH_ADDR_LEN; @@ -1049,14 +1025,22 @@ static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw, void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw) { u32 reg; + u16 eeprom_data = 0; if (hw->mac.type != e1000_82576 || (hw->phy.media_type != e1000_media_type_fiber && hw->phy.media_type != e1000_media_type_internal_serdes)) return; - /* if the management interface is not enabled, then power down */ - if (!e1000_enable_mng_pass_thru(hw)) { + if (hw->bus.func == 0) + hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); + + /* + * If APM is not enabled in the EEPROM and management interface is + * not enabled, then power down. + */ + if (!(eeprom_data & E1000_NVM_APME_82575) && + !e1000_enable_mng_pass_thru(hw)) { /* Disable PCS to turn off link */ reg = E1000_READ_REG(hw, E1000_PCS_CFG0); reg &= ~E1000_PCS_CFG_PCS_EN; @@ -1079,8 +1063,7 @@ void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw) * e1000_reset_hw_82575 - Reset hardware * @hw: pointer to the HW structure * - * This resets the hardware into a known state. This is a - * function pointer entry point called by the api module. + * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82575(struct e1000_hw *hw) { @@ -1462,86 +1445,14 @@ out: **/ static bool e1000_sgmii_active_82575(struct e1000_hw *hw) { - struct e1000_dev_spec_82575 *dev_spec; - bool ret_val; + struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; DEBUGFUNC("e1000_sgmii_active_82575"); - if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576) { - ret_val = FALSE; - goto out; - } - - dev_spec = (struct e1000_dev_spec_82575 *)hw->dev_spec; + if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576) + return FALSE; - ret_val = dev_spec->sgmii_active; - -out: - return ret_val; -} - -/** - * e1000_translate_register_82576 - Translate the proper register offset - * @reg: e1000 register to be read - * - * Registers in 82576 are located in different offsets than other adapters - * even though they function in the same manner. This function takes in - * the name of the register to read and returns the correct offset for - * 82576 silicon. - **/ -u32 e1000_translate_register_82576(u32 reg) -{ - /* - * Some of the 82576 registers are located at different - * offsets than they are in older adapters. - * Despite the difference in location, the registers - * function in the same manner. - */ - switch (reg) { - case E1000_TDBAL(0): - reg = 0x0E000; - break; - case E1000_TDBAH(0): - reg = 0x0E004; - break; - case E1000_TDLEN(0): - reg = 0x0E008; - break; - case E1000_TDH(0): - reg = 0x0E010; - break; - case E1000_TDT(0): - reg = 0x0E018; - break; - case E1000_TXDCTL(0): - reg = 0x0E028; - break; - case E1000_RDBAL(0): - reg = 0x0C000; - break; - case E1000_RDBAH(0): - reg = 0x0C004; - break; - case E1000_RDLEN(0): - reg = 0x0C008; - break; - case E1000_RDH(0): - reg = 0x0C010; - break; - case E1000_RDT(0): - reg = 0x0C018; - break; - case E1000_RXDCTL(0): - reg = 0x0C028; - break; - case E1000_SRRCTL(0): - reg = 0x0C00C; - break; - default: - break; - } - - return reg; + return dev_spec->sgmii_active; } /** @@ -1620,30 +1531,6 @@ static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw) } /** - * e1000_remove_device_82575 - Free device specific structure - * @hw: pointer to the HW structure - * - * If a device specific structure was allocated, this function will - * free it after shutting down the serdes interface if available. - **/ -void e1000_remove_device_82575(struct e1000_hw *hw) -{ - u16 eeprom_data = 0; - - /* - * If APM is enabled in the EEPROM then leave the port on for fiber - * serdes adapters. - */ - if (hw->bus.func == 0) - hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); - - if (!(eeprom_data & E1000_NVM_APME_82575)) - e1000_shutdown_fiber_serdes_link_82575(hw); - - e1000_remove_device_generic(hw); -} - -/** * e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters * @hw: pointer to the HW structure * @@ -1651,62 +1538,60 @@ void e1000_remove_device_82575(struct e1000_hw *hw) **/ static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_82575"); e1000_clear_hw_cntrs_base_generic(hw); - temp = E1000_READ_REG(hw, E1000_PRC64); - temp = E1000_READ_REG(hw, E1000_PRC127); - temp = E1000_READ_REG(hw, E1000_PRC255); - temp = E1000_READ_REG(hw, E1000_PRC511); - temp = E1000_READ_REG(hw, E1000_PRC1023); - temp = E1000_READ_REG(hw, E1000_PRC1522); - temp = E1000_READ_REG(hw, E1000_PTC64); - temp = E1000_READ_REG(hw, E1000_PTC127); - temp = E1000_READ_REG(hw, E1000_PTC255); - temp = E1000_READ_REG(hw, E1000_PTC511); - temp = E1000_READ_REG(hw, E1000_PTC1023); - temp = E1000_READ_REG(hw, E1000_PTC1522); - - temp = E1000_READ_REG(hw, E1000_ALGNERRC); - temp = E1000_READ_REG(hw, E1000_RXERRC); - temp = E1000_READ_REG(hw, E1000_TNCRS); - temp = E1000_READ_REG(hw, E1000_CEXTERR); - temp = E1000_READ_REG(hw, E1000_TSCTC); - temp = E1000_READ_REG(hw, E1000_TSCTFC); - - temp = E1000_READ_REG(hw, E1000_MGTPRC); - temp = E1000_READ_REG(hw, E1000_MGTPDC); - temp = E1000_READ_REG(hw, E1000_MGTPTC); - - temp = E1000_READ_REG(hw, E1000_IAC); - temp = E1000_READ_REG(hw, E1000_ICRXOC); - - temp = E1000_READ_REG(hw, E1000_ICRXPTC); - temp = E1000_READ_REG(hw, E1000_ICRXATC); - temp = E1000_READ_REG(hw, E1000_ICTXPTC); - temp = E1000_READ_REG(hw, E1000_ICTXATC); - temp = E1000_READ_REG(hw, E1000_ICTXQEC); - temp = E1000_READ_REG(hw, E1000_ICTXQMTC); - temp = E1000_READ_REG(hw, E1000_ICRXDMTC); - - temp = E1000_READ_REG(hw, E1000_CBTMPC); - temp = E1000_READ_REG(hw, E1000_HTDPMC); - temp = E1000_READ_REG(hw, E1000_CBRMPC); - temp = E1000_READ_REG(hw, E1000_RPTHC); - temp = E1000_READ_REG(hw, E1000_HGPTC); - temp = E1000_READ_REG(hw, E1000_HTCBDPC); - temp = E1000_READ_REG(hw, E1000_HGORCL); - temp = E1000_READ_REG(hw, E1000_HGORCH); - temp = E1000_READ_REG(hw, E1000_HGOTCL); - temp = E1000_READ_REG(hw, E1000_HGOTCH); - temp = E1000_READ_REG(hw, E1000_LENERRS); + E1000_READ_REG(hw, E1000_PRC64); + E1000_READ_REG(hw, E1000_PRC127); + E1000_READ_REG(hw, E1000_PRC255); + E1000_READ_REG(hw, E1000_PRC511); + E1000_READ_REG(hw, E1000_PRC1023); + E1000_READ_REG(hw, E1000_PRC1522); + E1000_READ_REG(hw, E1000_PTC64); + E1000_READ_REG(hw, E1000_PTC127); + E1000_READ_REG(hw, E1000_PTC255); + E1000_READ_REG(hw, E1000_PTC511); + E1000_READ_REG(hw, E1000_PTC1023); + E1000_READ_REG(hw, E1000_PTC1522); + + E1000_READ_REG(hw, E1000_ALGNERRC); + E1000_READ_REG(hw, E1000_RXERRC); + E1000_READ_REG(hw, E1000_TNCRS); + E1000_READ_REG(hw, E1000_CEXTERR); + E1000_READ_REG(hw, E1000_TSCTC); + E1000_READ_REG(hw, E1000_TSCTFC); + + E1000_READ_REG(hw, E1000_MGTPRC); + E1000_READ_REG(hw, E1000_MGTPDC); + E1000_READ_REG(hw, E1000_MGTPTC); + + E1000_READ_REG(hw, E1000_IAC); + E1000_READ_REG(hw, E1000_ICRXOC); + + E1000_READ_REG(hw, E1000_ICRXPTC); + E1000_READ_REG(hw, E1000_ICRXATC); + E1000_READ_REG(hw, E1000_ICTXPTC); + E1000_READ_REG(hw, E1000_ICTXATC); + E1000_READ_REG(hw, E1000_ICTXQEC); + E1000_READ_REG(hw, E1000_ICTXQMTC); + E1000_READ_REG(hw, E1000_ICRXDMTC); + + E1000_READ_REG(hw, E1000_CBTMPC); + E1000_READ_REG(hw, E1000_HTDPMC); + E1000_READ_REG(hw, E1000_CBRMPC); + E1000_READ_REG(hw, E1000_RPTHC); + E1000_READ_REG(hw, E1000_HGPTC); + E1000_READ_REG(hw, E1000_HTCBDPC); + E1000_READ_REG(hw, E1000_HGORCL); + E1000_READ_REG(hw, E1000_HGORCH); + E1000_READ_REG(hw, E1000_HGOTCL); + E1000_READ_REG(hw, E1000_HGOTCH); + E1000_READ_REG(hw, E1000_LENERRS); /* This register should not be read in copper configurations */ if (hw->phy.media_type == e1000_media_type_internal_serdes) - temp = E1000_READ_REG(hw, E1000_SCVPC); + E1000_READ_REG(hw, E1000_SCVPC); } /** * e1000_rx_fifo_flush_82575 - Clean rx fifo after RX enable @@ -1781,3 +1666,4 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) E1000_READ_REG(hw, E1000_RNBC); E1000_READ_REG(hw, E1000_MPC); } + diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h index c4bc39c..56321e4 100644 --- a/sys/dev/e1000/e1000_82575.h +++ b/sys/dev/e1000/e1000_82575.h @@ -45,7 +45,6 @@ * Registers) holds the directed and multicast addresses that we monitor. * These entries are also used for MAC-based filtering. */ - /* * For 82576, there are an additional set of RARs that begin at an offset * separate from the first set of RARs. @@ -351,11 +350,10 @@ struct e1000_adv_tx_context_desc { #define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ #define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ -/* Additional DCA related definitions, note change in position of CPUID */ #define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */ #define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */ -#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */ -#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */ +#define E1000_DCA_TXCTRL_CPUID_SHIFT_82576 24 /* Tx CPUID */ +#define E1000_DCA_RXCTRL_CPUID_SHIFT_82576 24 /* Rx CPUID */ /* Additional interrupt register bit definitions */ #define E1000_ICR_LSECPNS 0x00000020 /* PN threshold - server */ @@ -365,6 +363,8 @@ struct e1000_adv_tx_context_desc { /* ETQF register bit definitions */ #define E1000_ETQF_FILTER_ENABLE (1 << 26) #define E1000_ETQF_IMM_INT (1 << 29) +#define E1000_ETQF_1588 (1 << 30) +#define E1000_ETQF_QUEUE_ENABLE (1 << 31) /* * ETQF filter list: one static filter per filter consumer. This is * to avoid filter collisions later. Add new filters @@ -423,12 +423,28 @@ struct e1000_adv_tx_context_desc { * this are the ACK */ #define E1000_VT_MSGTYPE_NACK 0xFF000000 /* Messages below or'd with * this are the NACK */ -#define E1000_VF_MSGTYPE_REQ_MAC 1 /* VF needs to know its MAC */ -#define E1000_VF_MSGTYPE_VFLR 2 /* VF notifies VFLR to PF */ -#define E1000_PF_MSGTYPE_RESET 3 /* PF notifies global reset +#define E1000_VT_MSGINFO_SHIFT 16 +/* bits 23:16 are used for exra info for certain messages */ +#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT) + +#define E1000_VF_MSGTYPE_REQ_MAC 1 /* VF needs to know its MAC */ +#define E1000_VF_MSGTYPE_VFLR 2 /* VF notifies VFLR to PF */ +#define E1000_VF_SET_MULTICAST 3 /* VF requests PF to set MC addr */ +#define E1000_VF_SET_VLAN 4 /* VF requests PF to set VLAN */ + +/* Add 100h to all PF msgs, leaves room for up to 255 discrete message types + * from VF to PF - way more than we'll ever need */ +#define E1000_PF_MSGTYPE_RESET (1 + 0x100) /* PF notifies global reset * imminent to VF */ +#define E1000_PF_MSGTYPE_LSC (2 + 0x100) /* PF notifies VF of LSC... VF + * will see extra msg info for + * status */ + +#define E1000_PF_MSG_LSCDOWN (1 << E1000_VT_MSGINFO_SHIFT) +#define E1000_PF_MSG_LSCUP (2 << E1000_VT_MSGINFO_SHIFT) + +#define ALL_QUEUES 0xFFFF -u32 e1000_translate_register_82576(u32 reg); s32 e1000_send_mail_to_pf_vf(struct e1000_hw *hw, u32 *msg, s16 size); s32 e1000_receive_mail_from_pf_vf(struct e1000_hw *hw, @@ -441,9 +457,18 @@ void e1000_vmdq_loopback_enable_vf(struct e1000_hw *hw); void e1000_vmdq_loopback_disable_vf(struct e1000_hw *hw); void e1000_vmdq_replication_enable_vf(struct e1000_hw *hw, u32 enables); void e1000_vmdq_replication_disable_vf(struct e1000_hw *hw); -void e1000_init_vfnumber_index_vf(struct e1000_hw *hw, u32 vf_number); +void e1000_vmdq_enable_replication_mode_vf(struct e1000_hw *hw); +void e1000_vmdq_broadcast_replication_enable_vf(struct e1000_hw *hw, + u32 enables); +void e1000_vmdq_multicast_replication_enable_vf(struct e1000_hw *hw, + u32 enables); +void e1000_vmdq_broadcast_replication_disable_vf(struct e1000_hw *hw, + u32 disables); +void e1000_vmdq_multicast_replication_disable_vf(struct e1000_hw *hw, + u32 disables); bool e1000_check_for_pf_ack_vf(struct e1000_hw *hw); -bool e1000_check_for_pf_mail_vf(struct e1000_hw *hw); + +bool e1000_check_for_pf_mail_vf(struct e1000_hw *hw, u32*); #endif diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c index aaa70b1..47bffb5 100644 --- a/sys/dev/e1000/e1000_api.c +++ b/sys/dev/e1000/e1000_api.c @@ -72,7 +72,6 @@ s32 e1000_init_nvm_params(struct e1000_hw *hw) s32 ret_val = E1000_SUCCESS; if (hw->nvm.ops.init_params) { - hw->nvm.semaphore_delay = 10; ret_val = hw->nvm.ops.init_params(hw); if (ret_val) { DEBUGOUT("NVM Initialization Error\n"); @@ -379,19 +378,6 @@ out: } /** - * e1000_remove_device - Free device specific structure - * @hw: pointer to the HW structure - * - * If a device specific structure was allocated, this function will - * free it. This is a function pointer entry point called by drivers. - **/ -void e1000_remove_device(struct e1000_hw *hw) -{ - if (hw->mac.ops.remove_device) - hw->mac.ops.remove_device(hw); -} - -/** * e1000_get_bus_info - Obtain bus information for adapter * @hw: pointer to the HW structure * @@ -929,6 +915,18 @@ s32 e1000_acquire_phy(struct e1000_hw *hw) } /** + * e1000_cfg_on_link_up - Configure PHY upon link up + * @hw: pointer to the HW structure + **/ +s32 e1000_cfg_on_link_up(struct e1000_hw *hw) +{ + if (hw->phy.ops.cfg_on_link_up) + return hw->phy.ops.cfg_on_link_up(hw); + + return E1000_SUCCESS; +} + +/** * e1000_read_kmrn_reg - Reads register using Kumeran interface * @hw: pointer to the HW structure * @offset: the register to read diff --git a/sys/dev/e1000/e1000_api.h b/sys/dev/e1000/e1000_api.h index 2a901aa..4629ff0 100644 --- a/sys/dev/e1000/e1000_api.h +++ b/sys/dev/e1000/e1000_api.h @@ -54,7 +54,6 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device); s32 e1000_init_mac_params(struct e1000_hw *hw); s32 e1000_init_nvm_params(struct e1000_hw *hw); s32 e1000_init_phy_params(struct e1000_hw *hw); -void e1000_remove_device(struct e1000_hw *hw); s32 e1000_get_bus_info(struct e1000_hw *hw); void e1000_clear_vfta(struct e1000_hw *hw); void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); @@ -90,6 +89,7 @@ s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, s32 e1000_get_phy_info(struct e1000_hw *hw); void e1000_release_phy(struct e1000_hw *hw); s32 e1000_acquire_phy(struct e1000_hw *hw); +s32 e1000_cfg_on_link_up(struct e1000_hw *hw); s32 e1000_phy_hw_reset(struct e1000_hw *hw); s32 e1000_phy_commit(struct e1000_hw *hw); void e1000_power_up_phy(struct e1000_hw *hw); diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h index c017a30..81259a1 100644 --- a/sys/dev/e1000/e1000_defines.h +++ b/sys/dev/e1000/e1000_defines.h @@ -59,11 +59,11 @@ #define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ #define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ #define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ -#define E1000_WUFC_IGNORE_TCO_BM 0x00000800 /* Ignore WakeOn TCO packets */ -#define E1000_WUFC_FLX0_BM 0x00001000 /* Flexible Filter 0 Enable */ -#define E1000_WUFC_FLX1_BM 0x00002000 /* Flexible Filter 1 Enable */ -#define E1000_WUFC_FLX2_BM 0x00004000 /* Flexible Filter 2 Enable */ -#define E1000_WUFC_FLX3_BM 0x00008000 /* Flexible Filter 3 Enable */ +#define E1000_WUFC_IGNORE_TCO_PHY 0x00000800 /* Ignore WakeOn TCO packets */ +#define E1000_WUFC_FLX0_PHY 0x00001000 /* Flexible Filter 0 Enable */ +#define E1000_WUFC_FLX1_PHY 0x00002000 /* Flexible Filter 1 Enable */ +#define E1000_WUFC_FLX2_PHY 0x00004000 /* Flexible Filter 2 Enable */ +#define E1000_WUFC_FLX3_PHY 0x00008000 /* Flexible Filter 3 Enable */ #define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ #define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ #define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ @@ -71,12 +71,12 @@ #define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ #define E1000_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */ #define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ -#define E1000_WUFC_ALL_FILTERS_BM 0x0000F0FF /* Mask for all wakeup filters */ -#define E1000_WUFC_FLX_OFFSET_BM 12 /* Offset to the Flexible Filters bits */ -#define E1000_WUFC_FLX_FILTERS_BM 0x0000F000 /* Mask for the 4 flexible filters */ +#define E1000_WUFC_ALL_FILTERS_PHY_4 0x0000F0FF /*Mask for all wakeup filters*/ +#define E1000_WUFC_FLX_OFFSET_PHY 12 /* Offset to the Flexible Filters bits */ +#define E1000_WUFC_FLX_FILTERS_PHY_4 0x0000F000 /*Mask for 4 flexible filters*/ #define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ #define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ -#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ +#define E1000_WUFC_FLX_FILTERS 0x000F0000 /*Mask for the 4 flexible filters */ /* * For 82576 to utilize Extended filter masks in addition to * existing (filter) masks @@ -92,11 +92,11 @@ #define E1000_WUS_ARP E1000_WUFC_ARP #define E1000_WUS_IPV4 E1000_WUFC_IPV4 #define E1000_WUS_IPV6 E1000_WUFC_IPV6 -#define E1000_WUS_FLX0_BM E1000_WUFC_FLX0_BM -#define E1000_WUS_FLX1_BM E1000_WUFC_FLX1_BM -#define E1000_WUS_FLX2_BM E1000_WUFC_FLX2_BM -#define E1000_WUS_FLX3_BM E1000_WUFC_FLX3_BM -#define E1000_WUS_FLX_FILTERS_BM E1000_WUFC_FLX_FILTERS_BM +#define E1000_WUS_FLX0_PHY E1000_WUFC_FLX0_PHY +#define E1000_WUS_FLX1_PHY E1000_WUFC_FLX1_PHY +#define E1000_WUS_FLX2_PHY E1000_WUFC_FLX2_PHY +#define E1000_WUS_FLX3_PHY E1000_WUFC_FLX3_PHY +#define E1000_WUS_FLX_FILTERS_PHY_4 E1000_WUFC_FLX_FILTERS_PHY_4 #define E1000_WUS_FLX0 E1000_WUFC_FLX0 #define E1000_WUS_FLX1 E1000_WUFC_FLX1 #define E1000_WUS_FLX2 E1000_WUFC_FLX2 @@ -158,13 +158,16 @@ #define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 #define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 #define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 -#define E1000_CTRL_EXT_CANC 0x04000000 /* Interrupt delay cancellation */ +#define E1000_CTRL_EXT_CANC 0x04000000 /* Int delay cancellation */ #define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ /* IAME enable bit (27) was removed in >= 82575 */ -#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ -#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ -#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */ -#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ +#define E1000_CTRL_EXT_IAME 0x08000000 /* Int acknowledge Auto-mask */ +#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers + * after IMS clear */ +#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error + * detection enabled */ +#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity + * error detection enable */ #define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 #define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ #define E1000_CTRL_EXT_LSECCK 0x00001000 @@ -390,9 +393,12 @@ #define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ #define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ -#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ -#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */ -#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ +#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock + * indication in SDP[0] */ +#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through + * PHYRST_N pin */ +#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external + * LINK_0 and LINK_1 pins */ #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ #define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ @@ -407,10 +413,11 @@ #define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ #define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ #define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ -#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */ +#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to ME */ #define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */ -/* Bit definitions for the Management Data IO (MDIO) and Management Data +/* + * Bit definitions for the Management Data IO (MDIO) and Management Data * Clock (MDC) pins in the Device Control Register. */ #define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0 @@ -470,8 +477,9 @@ #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ #define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ -#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */ -#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ +#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. + * Clear on write '0'. */ +#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */ #define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ #define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ #define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ @@ -481,7 +489,8 @@ #define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */ #define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */ #define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */ -#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */ +#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution + * disabled */ #define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */ #define E1000_STATUS_FUSE_8 0x04000000 #define E1000_STATUS_FUSE_9 0x08000000 @@ -509,10 +518,10 @@ #define ADVERTISE_1000_FULL 0x0020 /* 1000/H is not supported, nor spec-compliant. */ -#define E1000_ALL_SPEED_DUPLEX ( ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ +#define E1000_ALL_SPEED_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ ADVERTISE_100_HALF | ADVERTISE_100_FULL | \ ADVERTISE_1000_FULL) -#define E1000_ALL_NOT_GIG ( ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ +#define E1000_ALL_NOT_GIG (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \ ADVERTISE_100_HALF | ADVERTISE_100_FULL) #define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) #define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) @@ -731,16 +740,20 @@ #define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ #define E1000_ICR_MNG 0x00040000 /* Manageability event */ #define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ -#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ -#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */ +#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver + * should claim the interrupt */ +#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* Q0 Rx desc FIFO parity error */ +#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* Q0 Tx desc FIFO parity error */ +#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity err */ #define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ -#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* Q1 Rx desc FIFO parity error */ +#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* Q1 Tx desc FIFO parity error */ #define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */ -#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */ -#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */ +#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW + * bit in the FWSM */ +#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates + * an interrupt */ +#define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ #define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */ #define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ #define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ @@ -811,14 +824,21 @@ #define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ -#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO + * parity error */ +#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO + * parity error */ +#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer + * parity error */ +#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity + * error */ +#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO + * parity error */ +#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO + * parity error */ #define E1000_IMS_DSW E1000_ICR_DSW #define E1000_IMS_PHYINT E1000_ICR_PHYINT +#define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ #define E1000_IMS_EPRST E1000_ICR_EPRST #define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ #define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ @@ -857,13 +877,20 @@ #define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ -#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO + * parity error */ +#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO + * parity error */ +#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer + * parity error */ +#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity + * error */ +#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO + * parity error */ +#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO + * parity error */ #define E1000_ICS_DSW E1000_ICR_DSW +#define E1000_ICS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ #define E1000_ICS_PHYINT E1000_ICR_PHYINT #define E1000_ICS_EPRST E1000_ICR_EPRST @@ -1121,7 +1148,7 @@ #define E1000_NVM_SWDPIN0 0x0001 /* SWDPIN 0 NVM Value */ #define E1000_NVM_LED_LOGIC 0x0020 /* Led Logic Word */ -#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write registers */ +#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write regs */ #define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ #define E1000_NVM_RW_REG_START 1 /* Start operation */ #define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ @@ -1133,7 +1160,7 @@ #define NVM_COMPAT 0x0003 #define NVM_ID_LED_SETTINGS 0x0004 #define NVM_VERSION 0x0005 -#define NVM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ +#define NVM_SERDES_AMPLITUDE 0x0006 /* SERDES output amplitude */ #define NVM_PHY_CLASS_WORD 0x0007 #define NVM_INIT_CONTROL1_REG 0x000A #define NVM_INIT_CONTROL2_REG 0x000F @@ -1489,4 +1516,4 @@ #define E1000_LSECRXCTRL_RP 0x00000080 #define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33 -#endif +#endif /* _E1000_DEFINES_H_ */ diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h index 0391e14..277d8d1 100644 --- a/sys/dev/e1000/e1000_hw.h +++ b/sys/dev/e1000/e1000_hw.h @@ -123,10 +123,10 @@ struct e1000_hw; #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 #define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 +#define E1000_DEV_ID_82576_VF 0x10CA #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 - #define E1000_REVISION_0 0 #define E1000_REVISION_1 1 #define E1000_REVISION_2 2 @@ -160,6 +160,7 @@ enum e1000_mac_type { e1000_ich10lan, e1000_82575, e1000_82576, + e1000_vfadapt, e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */ }; @@ -244,7 +245,7 @@ enum e1000_rev_polarity { e1000_rev_polarity_undefined = 0xFF }; -enum e1000_fc_type { +enum e1000_fc_mode { e1000_fc_none = 0, e1000_fc_rx_pause, e1000_fc_tx_pause, @@ -265,37 +266,50 @@ enum e1000_dsp_config { e1000_dsp_config_undefined = 0xFF }; +enum e1000_ms_type { + e1000_ms_hw_default = 0, + e1000_ms_force_master, + e1000_ms_force_slave, + e1000_ms_auto +}; + +enum e1000_smart_speed { + e1000_smart_speed_default = 0, + e1000_smart_speed_on, + e1000_smart_speed_off +}; + /* Receive Descriptor */ struct e1000_rx_desc { - u64 buffer_addr; /* Address of the descriptor's data buffer */ - u16 length; /* Length of data DMAed into data buffer */ - u16 csum; /* Packet checksum */ - u8 status; /* Descriptor status */ - u8 errors; /* Descriptor Errors */ - u16 special; + __le64 buffer_addr; /* Address of the descriptor's data buffer */ + __le16 length; /* Length of data DMAed into data buffer */ + __le16 csum; /* Packet checksum */ + u8 status; /* Descriptor status */ + u8 errors; /* Descriptor Errors */ + __le16 special; }; /* Receive Descriptor - Extended */ union e1000_rx_desc_extended { struct { - u64 buffer_addr; - u64 reserved; + __le64 buffer_addr; + __le64 reserved; } read; struct { struct { - u32 mrq; /* Multiple Rx Queues */ + __le32 mrq; /* Multiple Rx Queues */ union { - u32 rss; /* RSS Hash */ + __le32 rss; /* RSS Hash */ struct { - u16 ip_id; /* IP id */ - u16 csum; /* Packet Checksum */ + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { - u32 status_error; /* ext status/error */ - u16 length; - u16 vlan; /* VLAN tag */ + __le32 status_error; /* ext status/error */ + __le16 length; + __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; @@ -305,49 +319,49 @@ union e1000_rx_desc_extended { union e1000_rx_desc_packet_split { struct { /* one buffer for protocol header(s), three data buffers */ - u64 buffer_addr[MAX_PS_BUFFERS]; + __le64 buffer_addr[MAX_PS_BUFFERS]; } read; struct { struct { - u32 mrq; /* Multiple Rx Queues */ + __le32 mrq; /* Multiple Rx Queues */ union { - u32 rss; /* RSS Hash */ + __le32 rss; /* RSS Hash */ struct { - u16 ip_id; /* IP id */ - u16 csum; /* Packet Checksum */ + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { - u32 status_error; /* ext status/error */ - u16 length0; /* length of buffer 0 */ - u16 vlan; /* VLAN tag */ + __le32 status_error; /* ext status/error */ + __le16 length0; /* length of buffer 0 */ + __le16 vlan; /* VLAN tag */ } middle; struct { - u16 header_status; - u16 length[3]; /* length of buffers 1-3 */ + __le16 header_status; + __le16 length[3]; /* length of buffers 1-3 */ } upper; - u64 reserved; + __le64 reserved; } wb; /* writeback */ }; /* Transmit Descriptor */ struct e1000_tx_desc { - u64 buffer_addr; /* Address of the descriptor's data buffer */ + __le64 buffer_addr; /* Address of the descriptor's data buffer */ union { - u32 data; + __le32 data; struct { - u16 length; /* Data buffer length */ - u8 cso; /* Checksum offset */ - u8 cmd; /* Descriptor control */ + __le16 length; /* Data buffer length */ + u8 cso; /* Checksum offset */ + u8 cmd; /* Descriptor control */ } flags; } lower; union { - u32 data; + __le32 data; struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ - u16 special; + u8 status; /* Descriptor status */ + u8 css; /* Checksum start */ + __le16 special; } fields; } upper; }; @@ -355,49 +369,49 @@ struct e1000_tx_desc { /* Offload Context Descriptor */ struct e1000_context_desc { union { - u32 ip_config; + __le32 ip_config; struct { - u8 ipcss; /* IP checksum start */ - u8 ipcso; /* IP checksum offset */ - u16 ipcse; /* IP checksum end */ + u8 ipcss; /* IP checksum start */ + u8 ipcso; /* IP checksum offset */ + __le16 ipcse; /* IP checksum end */ } ip_fields; } lower_setup; union { - u32 tcp_config; + __le32 tcp_config; struct { - u8 tucss; /* TCP checksum start */ - u8 tucso; /* TCP checksum offset */ - u16 tucse; /* TCP checksum end */ + u8 tucss; /* TCP checksum start */ + u8 tucso; /* TCP checksum offset */ + __le16 tucse; /* TCP checksum end */ } tcp_fields; } upper_setup; - u32 cmd_and_length; + __le32 cmd_and_length; union { - u32 data; + __le32 data; struct { - u8 status; /* Descriptor status */ - u8 hdr_len; /* Header length */ - u16 mss; /* Maximum segment size */ + u8 status; /* Descriptor status */ + u8 hdr_len; /* Header length */ + __le16 mss; /* Maximum segment size */ } fields; } tcp_seg_setup; }; /* Offload data descriptor */ struct e1000_data_desc { - u64 buffer_addr; /* Address of the descriptor's buffer address */ + __le64 buffer_addr; /* Address of the descriptor's buffer address */ union { - u32 data; + __le32 data; struct { - u16 length; /* Data buffer length */ + __le16 length; /* Data buffer length */ u8 typ_len_ext; u8 cmd; } flags; } lower; union { - u32 data; + __le32 data; struct { - u8 status; /* Descriptor status */ - u8 popts; /* Packet Options */ - u16 special; + u8 status; /* Descriptor status */ + u8 popts; /* Packet Options */ + __le16 special; } fields; } upper; }; @@ -479,6 +493,39 @@ struct e1000_hw_stats { u64 lenerrs; u64 scvpc; u64 hrmpc; + u64 doosync; +}; + +struct e1000_vf_stats { + u64 base_gprc; + u64 base_gptc; + u64 base_gorc; + u64 base_gotc; + u64 base_mprc; + u64 base_gotlbc; + u64 base_gptlbc; + u64 base_gorlbc; + u64 base_gprlbc; + + u32 last_gprc; + u32 last_gptc; + u32 last_gorc; + u32 last_gotc; + u32 last_mprc; + u32 last_gotlbc; + u32 last_gptlbc; + u32 last_gorlbc; + u32 last_gprlbc; + + u64 gprc; + u64 gptc; + u64 gorc; + u64 gotc; + u64 mprc; + u64 gotlbc; + u64 gptlbc; + u64 gorlbc; + u64 gprlbc; }; struct e1000_phy_stats { @@ -541,12 +588,11 @@ struct e1000_mac_operations { void (*clear_hw_cntrs)(struct e1000_hw *); void (*clear_vfta)(struct e1000_hw *); s32 (*get_bus_info)(struct e1000_hw *); + void (*set_lan_id)(struct e1000_hw *); s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); s32 (*led_on)(struct e1000_hw *); s32 (*led_off)(struct e1000_hw *); - void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, - u32); - void (*remove_device)(struct e1000_hw *); + void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32); s32 (*reset_hw)(struct e1000_hw *); s32 (*init_hw)(struct e1000_hw *); void (*shutdown_serdes)(struct e1000_hw *); @@ -555,20 +601,21 @@ struct e1000_mac_operations { s32 (*setup_led)(struct e1000_hw *); void (*write_vfta)(struct e1000_hw *, u32, u32); void (*mta_set)(struct e1000_hw *, u32); - void (*config_collision_dist)(struct e1000_hw*); - void (*rar_set)(struct e1000_hw*, u8*, u32); - s32 (*read_mac_addr)(struct e1000_hw*); - s32 (*validate_mdi_setting)(struct e1000_hw*); - s32 (*mng_host_if_write)(struct e1000_hw*, u8*, u16, u16, u8*); + void (*config_collision_dist)(struct e1000_hw *); + void (*rar_set)(struct e1000_hw *, u8*, u32); + s32 (*read_mac_addr)(struct e1000_hw *); + s32 (*validate_mdi_setting)(struct e1000_hw *); + s32 (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*); s32 (*mng_write_cmd_header)(struct e1000_hw *hw, struct e1000_host_mng_command_header*); - s32 (*mng_enable_host_if)(struct e1000_hw*); - s32 (*wait_autoneg)(struct e1000_hw*); + s32 (*mng_enable_host_if)(struct e1000_hw *); + s32 (*wait_autoneg)(struct e1000_hw *); }; struct e1000_phy_operations { s32 (*init_params)(struct e1000_hw *); s32 (*acquire)(struct e1000_hw *); + s32 (*cfg_on_link_up)(struct e1000_hw *); s32 (*check_polarity)(struct e1000_hw *); s32 (*check_reset_block)(struct e1000_hw *); s32 (*commit)(struct e1000_hw *); @@ -628,10 +675,7 @@ struct e1000_mac_info { bool asf_firmware_present; bool autoneg; bool autoneg_failed; - bool disable_av; - bool disable_hw_init_bits; bool get_link_status; - bool ifs_params_forced; bool in_ifs_mode; bool report_tx_early; bool serdes_has_link; @@ -679,7 +723,6 @@ struct e1000_nvm_info { u32 flash_bank_size; u32 flash_base_addr; - u32 semaphore_delay; u16 word_size; u16 delay_usec; @@ -693,25 +736,63 @@ struct e1000_bus_info { enum e1000_bus_speed speed; enum e1000_bus_width width; - u32 snoop; - u16 func; u16 pci_cmd_word; }; struct e1000_fc_info { - u32 high_water; /* Flow control high-water mark */ - u32 low_water; /* Flow control low-water mark */ - u16 pause_time; /* Flow control pause timer */ - bool send_xon; /* Flow control send XON */ - bool strict_ieee; /* Strict IEEE mode */ - enum e1000_fc_type type; /* Type of flow control */ - enum e1000_fc_type original_type; + u32 high_water; /* Flow control high-water mark */ + u32 low_water; /* Flow control low-water mark */ + u16 pause_time; /* Flow control pause timer */ + bool send_xon; /* Flow control send XON */ + bool strict_ieee; /* Strict IEEE mode */ + enum e1000_fc_mode current_mode; /* FC mode in effect */ + enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ +}; + +struct e1000_dev_spec_82541 { + enum e1000_dsp_config dsp_config; + enum e1000_ffe_config ffe_config; + u16 spd_default; + bool phy_init_script; +}; + +struct e1000_dev_spec_82542 { + bool dma_fairness; +}; + +struct e1000_dev_spec_82543 { + u32 tbi_compatibility; + bool dma_fairness; + bool init_phy_disabled; +}; + +struct e1000_dev_spec_82571 { + bool laa_is_present; +}; + +struct e1000_shadow_ram { + u16 value; + bool modified; +}; + +#define E1000_SHADOW_RAM_WORDS 2048 + +struct e1000_dev_spec_ich8lan { + bool kmrn_lock_loss_workaround_enabled; + struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS]; +}; + +struct e1000_dev_spec_82575 { + bool sgmii_active; +}; + +struct e1000_dev_spec_vf { + u32 vf_number; }; struct e1000_hw { void *back; - void *dev_spec; u8 *hw_addr; u8 *flash_address; @@ -724,7 +805,15 @@ struct e1000_hw { struct e1000_bus_info bus; struct e1000_host_mng_dhcp_cookie mng_cookie; - u32 dev_spec_size; + union { + struct e1000_dev_spec_82541 _82541; + struct e1000_dev_spec_82542 _82542; + struct e1000_dev_spec_82543 _82543; + struct e1000_dev_spec_82571 _82571; + struct e1000_dev_spec_ich8lan ich8lan; + struct e1000_dev_spec_82575 _82575; + struct e1000_dev_spec_vf vf; + } dev_spec; u16 device_id; u16 subsystem_vendor_id; @@ -744,9 +833,7 @@ struct e1000_hw { /* These functions must be implemented by drivers */ void e1000_pci_clear_mwi(struct e1000_hw *hw); void e1000_pci_set_mwi(struct e1000_hw *hw); -s32 e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, u32 size); s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); -void e1000_free_dev_spec_struct(struct e1000_hw *hw); void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); void e1000_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c index c4b9a2b..f368998 100644 --- a/sys/dev/e1000/e1000_ich8lan.c +++ b/sys/dev/e1000/e1000_ich8lan.c @@ -32,8 +32,28 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* e1000_ich8lan - * e1000_ich9lan +/* + * 82562G 10/100 Network Connection + * 82562G-2 10/100 Network Connection + * 82562GT 10/100 Network Connection + * 82562GT-2 10/100 Network Connection + * 82562V 10/100 Network Connection + * 82562V-2 10/100 Network Connection + * 82566DC-2 Gigabit Network Connection + * 82566DC Gigabit Network Connection + * 82566DM-2 Gigabit Network Connection + * 82566DM Gigabit Network Connection + * 82566MC Gigabit Network Connection + * 82566MM Gigabit Network Connection + * 82567LM Gigabit Network Connection + * 82567LF Gigabit Network Connection + * 82567V Gigabit Network Connection + * 82567LM-2 Gigabit Network Connection + * 82567LF-2 Gigabit Network Connection + * 82567V-2 Gigabit Network Connection + * 82567LF-3 Gigabit Network Connection + * 82567LM-3 Gigabit Network Connection + * 82567LM-4 Gigabit Network Connection */ #include "e1000_api.h" @@ -79,9 +99,9 @@ static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw); static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8* data); + u32 offset, u8 *data); static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16* data); + u8 size, u16 *data); static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data); static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, @@ -134,16 +154,6 @@ union ich8_hws_flash_regacc { u16 regval; }; -struct e1000_shadow_ram { - u16 value; - bool modified; -}; - -struct e1000_dev_spec_ich8lan { - bool kmrn_lock_loss_workaround_enabled; - struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS]; -}; - /** * e1000_init_phy_params_ich8lan - Initialize PHY function pointers * @hw: pointer to the HW structure @@ -239,7 +249,7 @@ out: static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 gfpreg, sector_base_addr, sector_end_addr; s32 ret_val = E1000_SUCCESS; u16 i; @@ -253,7 +263,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) goto out; } - nvm->type = e1000_nvm_flash_sw; + nvm->type = e1000_nvm_flash_sw; gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); @@ -266,27 +276,19 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; /* flash_base_addr is byte-aligned */ - nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; + nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; /* * find total size of the NVM, then cut in half since the total * size represents two separate NVM banks. */ - nvm->flash_bank_size = (sector_end_addr - sector_base_addr) + nvm->flash_bank_size = (sector_end_addr - sector_base_addr) << FLASH_SECTOR_ADDR_SHIFT; - nvm->flash_bank_size /= 2; + nvm->flash_bank_size /= 2; /* Adjust to word count */ - nvm->flash_bank_size /= sizeof(u16); - - nvm->word_size = E1000_SHADOW_RAM_WORDS; - - dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; + nvm->flash_bank_size /= sizeof(u16); - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } + nvm->word_size = E1000_SHADOW_RAM_WORDS; /* Clear shadow ram */ for (i = 0; i < nvm->word_size; i++) { @@ -317,7 +319,6 @@ out: static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_mac_params_ich8lan"); @@ -339,6 +340,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_ich8lan; + /* function id */ + mac->ops.set_lan_id = e1000_set_lan_id_single_port; /* reset */ mac->ops.reset_hw = e1000_reset_hw_ich8lan; /* hw initialization */ @@ -366,25 +369,15 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) /* turn on/off LED */ mac->ops.led_on = e1000_led_on_ich8lan; mac->ops.led_off = e1000_led_off_ich8lan; - /* remove device */ - mac->ops.remove_device = e1000_remove_device_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan; - hw->dev_spec_size = sizeof(struct e1000_dev_spec_ich8lan); - - /* Device-specific structure allocation */ - ret_val = e1000_alloc_zeroed_dev_spec_struct(hw, hw->dev_spec_size); - if (ret_val) - goto out; - /* Enable PCS Lock-loss workaround for ICH8 */ if (mac->type == e1000_ich8lan) e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, TRUE); -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -478,8 +471,8 @@ static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) fwsm = E1000_READ_REG(hw, E1000_FWSM); - return ((fwsm & E1000_FWSM_MODE_MASK) == - (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); + return (fwsm & E1000_FWSM_MODE_MASK) == + (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); } /** @@ -560,9 +553,8 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw) if (ret_val) goto out; - if (!link) { + if (!link) DEBUGOUT("Link taking longer than expected.\n"); - } /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, @@ -588,7 +580,6 @@ out: static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - struct e1000_nvm_info *nvm = &hw->nvm; u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; s32 ret_val; u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT; @@ -631,9 +622,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) * count reaches 0, loading the configuration from NVM will * leave the PHY in a bad state possibly resulting in no link. */ - if (loop == 0) { + if (loop == 0) DEBUGOUT("LAN_INIT_DONE not set, increase timeout\n"); - } /* Clear the Init Done bit for the next init event */ data = E1000_READ_REG(hw, E1000_STATUS); @@ -657,26 +647,19 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - /* - * Configure LCD from extended configuration - * region. - */ + /* Configure LCD from extended configuration region. */ /* cnf_base_addr is in DWORD */ word_addr = (u16)(cnf_base_addr << 1); for (i = 0; i < cnf_size; i++) { - ret_val = nvm->ops.read(hw, - (word_addr + i * 2), - 1, - ®_data); + ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2), 1, + ®_data); if (ret_val) goto out; - ret_val = nvm->ops.read(hw, - (word_addr + i * 2 + 1), - 1, - ®_addr); + ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2 + 1), + 1, ®_addr); if (ret_val) goto out; @@ -688,9 +671,7 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) reg_addr |= phy_page; - ret_val = phy->ops.write_reg(hw, - (u32)reg_addr, - reg_data); + ret_val = phy->ops.write_reg(hw, (u32)reg_addr, reg_data); if (ret_val) goto out; } @@ -705,8 +686,6 @@ out: * @hw: pointer to the HW structure * * Wrapper for calling the get_phy_info routines for the appropriate phy type. - * This is a function pointer entry point called by drivers - * or other shared routines. **/ static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw) { @@ -805,8 +784,7 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_check_polarity_ife_ich8lan"); /* - * Polarity is determined based on the reversal feature - * being enabled. + * Polarity is determined based on the reversal feature being enabled. */ if (phy->polarity_correction) { offset = IFE_PHY_EXTENDED_STATUS_CONTROL; @@ -839,8 +817,7 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw) * This is a function pointer entry point only called by * PHY setup routines. **/ -static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, - bool active) +static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; u32 phy_ctrl; @@ -932,8 +909,7 @@ out: * This is a function pointer entry point only called by * PHY setup routines. **/ -static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, - bool active) +static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; u32 phy_ctrl; @@ -1032,7 +1008,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) *bank = 1; else *bank = 0; - } else if (hw->dev_spec != NULL) { + } else { /* * Make sure the signature for bank 0 is valid, * if not check for bank1 @@ -1048,7 +1024,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) e1000_read_flash_byte_ich8lan(hw, act_offset + bank1_offset, &bank_high_byte); - + /* bank1 has a valid signature equivalent to SEC1V */ if ((bank_high_byte & 0xC0) == 0x80) { *bank = 1; @@ -1057,11 +1033,8 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) ret_val = -E1000_ERR_NVM; } } - } else { - DEBUGOUT("DEV SPEC is NULL\n"); - ret_val = -E1000_ERR_NVM; } - + return ret_val; } @@ -1078,7 +1051,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 act_offset; s32 ret_val = E1000_SUCCESS; u32 bank = 0; @@ -1086,14 +1059,6 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, DEBUGFUNC("e1000_read_nvm_ich8lan"); - dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); @@ -1200,8 +1165,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) * now set the Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; - E1000_WRITE_FLASH_REG16(hw, - ICH_FLASH_HSFSTS, + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); } else { DEBUGOUT("Flash controller busy, cannot get access"); @@ -1286,7 +1250,7 @@ out: * Reads a single byte from the NVM using the flash access registers. **/ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, - u8* data) + u8 *data) { s32 ret_val = E1000_SUCCESS; u16 word = 0; @@ -1311,7 +1275,7 @@ out: * Reads a byte or word from the NVM using the flash access registers. **/ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16* data) + u8 size, u16 *data) { union ich8_hws_flash_status hsfsts; union ich8_hws_flash_ctrl hsflctl; @@ -1354,11 +1318,10 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, */ if (ret_val == E1000_SUCCESS) { flash_data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0); - if (size == 1) { + if (size == 1) *data = (u8)(flash_data & 0x000000FF); - } else if (size == 2) { + else if (size == 2) *data = (u16)(flash_data & 0x0000FFFF); - } break; } else { /* @@ -1397,20 +1360,12 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; s32 ret_val = E1000_SUCCESS; u16 i; DEBUGFUNC("e1000_write_nvm_ich8lan"); - dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); @@ -1447,15 +1402,13 @@ out: static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 i, act_offset, new_bank_offset, old_bank_offset, bank; s32 ret_val; u16 data; DEBUGFUNC("e1000_update_nvm_checksum_ich8lan"); - dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; - ret_val = e1000_update_nvm_checksum_generic(hw); if (ret_val) goto out; @@ -1594,9 +1547,8 @@ out: * @hw: pointer to the HW structure * * Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. - * If the bit is 0, that the EEPROM had been modified, but the checksum was - * not calculated, in which case we need to calculate the checksum and set - * bit 6. + * If the bit is 0, that the EEPROM had been modified, but the checksum was not + * calculated, in which case we need to calculate the checksum and set bit 6. **/ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) { @@ -1668,7 +1620,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = size -1; + hsflctl.hsf_ctrl.fldbcount = size - 1; hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); @@ -1687,25 +1639,23 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, */ ret_val = e1000_flash_cycle_ich8lan(hw, ICH_FLASH_WRITE_COMMAND_TIMEOUT); - if (ret_val == E1000_SUCCESS) { + if (ret_val == E1000_SUCCESS) + break; + + /* + * If we're here, then things are most likely + * completely hosed, but if the error condition + * is detected, it won't hurt to give it another + * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcerr == 1) { + /* Repeat for some time before giving up. */ + continue; + } else if (hsfsts.hsf_status.flcdone == 0) { + DEBUGOUT("Timeout error - flash cycle " + "did not complete."); break; - } else { - /* - * If we're here, then things are most likely - * completely hosed, but if the error condition - * is detected, it won't hurt to give it another - * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. - */ - hsfsts.regval = E1000_READ_FLASH_REG16(hw, - ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr == 1) { - /* Repeat for some time before giving up. */ - continue; - } else if (hsfsts.hsf_status.flcdone == 0) { - DEBUGOUT("Timeout error - flash cycle " - "did not complete."); - break; - } } } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); @@ -1784,9 +1734,9 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) u32 flash_linear_addr; /* bank size is in 16bit words - adjust to bytes */ u32 flash_bank_size = nvm->flash_bank_size * 2; - s32 ret_val = E1000_SUCCESS; - s32 count = 0; - s32 j, iteration, sector_size; + s32 ret_val = E1000_SUCCESS; + s32 count = 0; + s32 j, iteration, sector_size; DEBUGFUNC("e1000_erase_flash_bank_ich8lan"); @@ -1851,8 +1801,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; - E1000_WRITE_FLASH_REG16(hw, - ICH_FLASH_HSFCTL, + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* @@ -1861,31 +1810,26 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) * Address. */ flash_linear_addr += (j * sector_size); - E1000_WRITE_FLASH_REG(hw, - ICH_FLASH_FADDR, + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); ret_val = e1000_flash_cycle_ich8lan(hw, ICH_FLASH_ERASE_COMMAND_TIMEOUT); - if (ret_val == E1000_SUCCESS) { + if (ret_val == E1000_SUCCESS) break; - } else { - /* - * Check if FCERR is set to 1. If 1, - * clear it and try the whole sequence - * a few more times else Done - */ - hsfsts.regval = E1000_READ_FLASH_REG16(hw, - ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr == 1) { - /* - * repeat for some time before - * giving up - */ - continue; - } else if (hsfsts.hsf_status.flcdone == 0) - goto out; - } + + /* + * Check if FCERR is set to 1. If 1, + * clear it and try the whole sequence + * a few more times else Done + */ + hsfsts.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcerr == 1) + /* repeat for some time before giving up */ + continue; + else if (hsfsts.hsf_status.flcdone == 0) + goto out; } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); } @@ -1969,9 +1913,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); - if (ret_val) { + if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); - } DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); @@ -2006,7 +1949,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ctrl |= E1000_CTRL_PHY_RST; } ret_val = e1000_acquire_swflag_ich8lan(hw); - DEBUGOUT("Issuing a global reset to ich8lan"); + DEBUGOUT("Issuing a global reset to ich8lan\n"); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_RST)); msec_delay(20); @@ -2122,9 +2065,6 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_initialize_hw_bits_ich8lan"); - if (hw->mac.disable_hw_init_bits) - goto out; - /* Extended Device Control */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg |= (1 << 22); @@ -2163,7 +2103,6 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_STATUS, reg); } -out: return; } @@ -2191,12 +2130,17 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) * the default flow control setting, so we explicitly * set it to full. */ - if (hw->fc.type == e1000_fc_default) - hw->fc.type = e1000_fc_full; + if (hw->fc.requested_mode == e1000_fc_default) + hw->fc.requested_mode = e1000_fc_full; - hw->fc.original_type = hw->fc.type; + /* + * Save off the requested flow control mode for use later. Depending + * on the link partner's capabilities, we may or may not use this mode. + */ + hw->fc.current_mode = hw->fc.requested_mode; - DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.type); + DEBUGOUT1("After fix-ups FlowControl is now = %x\n", + hw->fc.current_mode); /* Continue to configure the copper link. */ ret_val = hw->mac.ops.setup_physical_interface(hw); @@ -2340,7 +2284,7 @@ out: **/ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) { - struct e1000_dev_spec_ich8lan *dev_spec; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 phy_ctrl; s32 ret_val = E1000_SUCCESS; u16 i, data; @@ -2348,14 +2292,6 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan"); - dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - if (!(dev_spec->kmrn_lock_loss_workaround_enabled)) goto out; @@ -2420,25 +2356,17 @@ out: void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, bool state) { - struct e1000_dev_spec_ich8lan *dev_spec; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; DEBUGFUNC("e1000_set_kmrn_lock_loss_workaround_ich8lan"); if (hw->mac.type != e1000_ich8lan) { DEBUGOUT("Workaround applies to ICH8 only.\n"); - goto out; - } - - dev_spec = (struct e1000_dev_spec_ich8lan *)hw->dev_spec; - - if (!dev_spec) { - DEBUGOUT("dev_spec pointer is set to NULL.\n"); - goto out; + return; } dev_spec->kmrn_lock_loss_workaround_enabled = state; -out: return; } @@ -2481,8 +2409,7 @@ void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) /* Write VR power-down enable */ hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data); data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; - hw->phy.ops.write_reg(hw, - IGP3_VR_CTRL, + hw->phy.ops.write_reg(hw, IGP3_VR_CTRL, data | IGP3_VR_CTRL_MODE_SHUTDOWN); /* Read it back and test */ @@ -2579,8 +2506,7 @@ static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_cleanup_led_ich8lan"); if (hw->phy.type == e1000_phy_ife) - ret_val = hw->phy.ops.write_reg(hw, - IFE_PHY_SPECIAL_CONTROL_LED, + ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); else E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); @@ -2601,8 +2527,7 @@ static s32 e1000_led_on_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_led_on_ich8lan"); if (hw->phy.type == e1000_phy_ife) - ret_val = hw->phy.ops.write_reg(hw, - IFE_PHY_SPECIAL_CONTROL_LED, + ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON)); else E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); @@ -2652,12 +2577,12 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) /* If EEPROM is not marked present, init the IGP 3 PHY manually */ if (hw->mac.type != e1000_ich10lan) { if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && - (hw->phy.type == e1000_phy_igp_3)) { + (hw->phy.type == e1000_phy_igp_3)) { e1000_phy_init_script_igp3(hw); } } else { if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) { - /* Maybe we should do a basic Boazman config */ + /* Maybe we should do a basic PHY config */ DEBUGOUT("EEPROM not present\n"); ret_val = -E1000_ERR_CONFIG; } @@ -2675,11 +2600,9 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) **/ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) { - struct e1000_phy_info *phy = &hw->phy; - struct e1000_mac_info *mac = &hw->mac; - /* If the management interface is not enabled, then power down */ - if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) + if (!(hw->mac.ops.check_mng_mode(hw) || + hw->phy.ops.check_reset_block(hw))) e1000_power_down_phy_copper(hw); return; @@ -2694,24 +2617,22 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) **/ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan"); e1000_clear_hw_cntrs_base_generic(hw); - temp = E1000_READ_REG(hw, E1000_ALGNERRC); - temp = E1000_READ_REG(hw, E1000_RXERRC); - temp = E1000_READ_REG(hw, E1000_TNCRS); - temp = E1000_READ_REG(hw, E1000_CEXTERR); - temp = E1000_READ_REG(hw, E1000_TSCTC); - temp = E1000_READ_REG(hw, E1000_TSCTFC); + E1000_READ_REG(hw, E1000_ALGNERRC); + E1000_READ_REG(hw, E1000_RXERRC); + E1000_READ_REG(hw, E1000_TNCRS); + E1000_READ_REG(hw, E1000_CEXTERR); + E1000_READ_REG(hw, E1000_TSCTC); + E1000_READ_REG(hw, E1000_TSCTFC); - temp = E1000_READ_REG(hw, E1000_MGTPRC); - temp = E1000_READ_REG(hw, E1000_MGTPDC); - temp = E1000_READ_REG(hw, E1000_MGTPTC); + E1000_READ_REG(hw, E1000_MGTPRC); + E1000_READ_REG(hw, E1000_MGTPDC); + E1000_READ_REG(hw, E1000_MGTPTC); - temp = E1000_READ_REG(hw, E1000_IAC); - temp = E1000_READ_REG(hw, E1000_ICRXOC); + E1000_READ_REG(hw, E1000_IAC); + E1000_READ_REG(hw, E1000_ICRXOC); } diff --git a/sys/dev/e1000/e1000_ich8lan.h b/sys/dev/e1000/e1000_ich8lan.h index f43c1aa..79dffcd 100644 --- a/sys/dev/e1000/e1000_ich8lan.h +++ b/sys/dev/e1000/e1000_ich8lan.h @@ -54,8 +54,6 @@ #define FLASH_GFPREG_BASE_MASK 0x1FFF #define FLASH_SECTOR_ADDR_SHIFT 12 -#define E1000_SHADOW_RAM_WORDS 2048 - #define ICH_FLASH_SEG_SIZE_256 256 #define ICH_FLASH_SEG_SIZE_4K 4096 #define ICH_FLASH_SEG_SIZE_8K 8192 diff --git a/sys/dev/e1000/e1000_mac.c b/sys/dev/e1000/e1000_mac.c index fdf72c0..fcec342 100644 --- a/sys/dev/e1000/e1000_mac.c +++ b/sys/dev/e1000/e1000_mac.c @@ -34,6 +34,8 @@ #include "e1000_api.h" +static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); + /** * e1000_init_mac_ops_generic - Initialize MAC function pointers * @hw: pointer to the HW structure @@ -51,8 +53,8 @@ void e1000_init_mac_ops_generic(struct e1000_hw *hw) mac->ops.reset_hw = e1000_null_ops_generic; mac->ops.setup_physical_interface = e1000_null_ops_generic; mac->ops.get_bus_info = e1000_null_ops_generic; + mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie; mac->ops.read_mac_addr = e1000_read_mac_addr_generic; - mac->ops.remove_device = e1000_remove_device_generic; mac->ops.config_collision_dist = e1000_config_collision_dist_generic; mac->ops.clear_hw_cntrs = e1000_null_mac_generic; /* LED */ @@ -161,21 +163,6 @@ void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a) } /** - * e1000_remove_device_generic - Free device specific structure - * @hw: pointer to the HW structure - * - * If a device specific structure was allocated, this function will - * free it. - **/ -void e1000_remove_device_generic(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_remove_device_generic"); - - /* Freeing the dev_spec member of e1000_hw structure */ - e1000_free_dev_spec_struct(hw); -} - -/** * e1000_get_bus_info_pci_generic - Get PCI(x) bus information * @hw: pointer to the HW structure * @@ -185,10 +172,10 @@ void e1000_remove_device_generic(struct e1000_hw *hw) **/ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw) { + struct e1000_mac_info *mac = &hw->mac; struct e1000_bus_info *bus = &hw->bus; u32 status = E1000_READ_REG(hw, E1000_STATUS); s32 ret_val = E1000_SUCCESS; - u16 pci_header_type; DEBUGFUNC("e1000_get_bus_info_pci_generic"); @@ -225,12 +212,7 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw) : e1000_bus_width_32; /* Which PCI(-X) function? */ - e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type); - if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) - bus->func = (status & E1000_STATUS_FUNC_MASK) - >> E1000_STATUS_FUNC_SHIFT; - else - bus->func = 0; + mac->ops.set_lan_id(hw); return ret_val; } @@ -245,10 +227,11 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw) **/ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) { + struct e1000_mac_info *mac = &hw->mac; struct e1000_bus_info *bus = &hw->bus; + s32 ret_val; - u32 status; - u16 pcie_link_status, pci_header_type; + u16 pcie_link_status; DEBUGFUNC("e1000_get_bus_info_pcie_generic"); @@ -265,6 +248,45 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) PCIE_LINK_WIDTH_MASK) >> PCIE_LINK_WIDTH_SHIFT); + mac->ops.set_lan_id(hw); + + return E1000_SUCCESS; +} + +/** + * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices + * + * @hw: pointer to the HW structure + * + * Determines the LAN function id by reading memory-mapped registers + * and swaps the port value if requested. + **/ +void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) +{ + struct e1000_bus_info *bus = &hw->bus; + u32 reg; + + reg = E1000_READ_REG(hw, E1000_STATUS); + bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; + + /* check for a port swap */ + reg = E1000_READ_REG(hw, E1000_FACTPS); + if (reg & E1000_FACTPS_LFS) + bus->func ^= 0x1; +} + +/** + * e1000_set_lan_id_multi_port_pci - Set LAN id for PCI multiple port devices + * @hw: pointer to the HW structure + * + * Determines the LAN function id by reading PCI config space. + **/ +void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw) +{ + struct e1000_bus_info *bus = &hw->bus; + u16 pci_header_type; + u32 status; + e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type); if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) { status = E1000_READ_REG(hw, E1000_STATUS); @@ -273,8 +295,19 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) } else { bus->func = 0; } +} - return E1000_SUCCESS; +/** + * e1000_set_lan_id_single_port - Set LAN id for a single port device + * @hw: pointer to the HW structure + * + * Sets the LAN function id to zero for a single port device. + **/ +void e1000_set_lan_id_single_port(struct e1000_hw *hw) +{ + struct e1000_bus_info *bus = &hw->bus; + + bus->func = 0; } /** @@ -431,10 +464,8 @@ void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) { - if (!hw->mac.disable_av) - rar_high |= E1000_RAH_AV; - } + if (rar_low || rar_high) + rar_high |= E1000_RAH_AV; E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); @@ -585,18 +616,18 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 */ switch (hw->mac.mc_filter_type) { - default: - case 0: - break; - case 1: - bit_shift += 1; - break; - case 2: - bit_shift += 2; - break; - case 3: - bit_shift += 4; - break; + default: + case 0: + break; + case 1: + bit_shift += 1; + break; + case 2: + bit_shift += 2; + break; + case 3: + bit_shift += 4; + break; } hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | @@ -650,47 +681,45 @@ void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw) **/ void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw) { - volatile u32 temp; - DEBUGFUNC("e1000_clear_hw_cntrs_base_generic"); - temp = E1000_READ_REG(hw, E1000_CRCERRS); - temp = E1000_READ_REG(hw, E1000_SYMERRS); - temp = E1000_READ_REG(hw, E1000_MPC); - temp = E1000_READ_REG(hw, E1000_SCC); - temp = E1000_READ_REG(hw, E1000_ECOL); - temp = E1000_READ_REG(hw, E1000_MCC); - temp = E1000_READ_REG(hw, E1000_LATECOL); - temp = E1000_READ_REG(hw, E1000_COLC); - temp = E1000_READ_REG(hw, E1000_DC); - temp = E1000_READ_REG(hw, E1000_SEC); - temp = E1000_READ_REG(hw, E1000_RLEC); - temp = E1000_READ_REG(hw, E1000_XONRXC); - temp = E1000_READ_REG(hw, E1000_XONTXC); - temp = E1000_READ_REG(hw, E1000_XOFFRXC); - temp = E1000_READ_REG(hw, E1000_XOFFTXC); - temp = E1000_READ_REG(hw, E1000_FCRUC); - temp = E1000_READ_REG(hw, E1000_GPRC); - temp = E1000_READ_REG(hw, E1000_BPRC); - temp = E1000_READ_REG(hw, E1000_MPRC); - temp = E1000_READ_REG(hw, E1000_GPTC); - temp = E1000_READ_REG(hw, E1000_GORCL); - temp = E1000_READ_REG(hw, E1000_GORCH); - temp = E1000_READ_REG(hw, E1000_GOTCL); - temp = E1000_READ_REG(hw, E1000_GOTCH); - temp = E1000_READ_REG(hw, E1000_RNBC); - temp = E1000_READ_REG(hw, E1000_RUC); - temp = E1000_READ_REG(hw, E1000_RFC); - temp = E1000_READ_REG(hw, E1000_ROC); - temp = E1000_READ_REG(hw, E1000_RJC); - temp = E1000_READ_REG(hw, E1000_TORL); - temp = E1000_READ_REG(hw, E1000_TORH); - temp = E1000_READ_REG(hw, E1000_TOTL); - temp = E1000_READ_REG(hw, E1000_TOTH); - temp = E1000_READ_REG(hw, E1000_TPR); - temp = E1000_READ_REG(hw, E1000_TPT); - temp = E1000_READ_REG(hw, E1000_MPTC); - temp = E1000_READ_REG(hw, E1000_BPTC); + E1000_READ_REG(hw, E1000_CRCERRS); + E1000_READ_REG(hw, E1000_SYMERRS); + E1000_READ_REG(hw, E1000_MPC); + E1000_READ_REG(hw, E1000_SCC); + E1000_READ_REG(hw, E1000_ECOL); + E1000_READ_REG(hw, E1000_MCC); + E1000_READ_REG(hw, E1000_LATECOL); + E1000_READ_REG(hw, E1000_COLC); + E1000_READ_REG(hw, E1000_DC); + E1000_READ_REG(hw, E1000_SEC); + E1000_READ_REG(hw, E1000_RLEC); + E1000_READ_REG(hw, E1000_XONRXC); + E1000_READ_REG(hw, E1000_XONTXC); + E1000_READ_REG(hw, E1000_XOFFRXC); + E1000_READ_REG(hw, E1000_XOFFTXC); + E1000_READ_REG(hw, E1000_FCRUC); + E1000_READ_REG(hw, E1000_GPRC); + E1000_READ_REG(hw, E1000_BPRC); + E1000_READ_REG(hw, E1000_MPRC); + E1000_READ_REG(hw, E1000_GPTC); + E1000_READ_REG(hw, E1000_GORCL); + E1000_READ_REG(hw, E1000_GORCH); + E1000_READ_REG(hw, E1000_GOTCL); + E1000_READ_REG(hw, E1000_GOTCH); + E1000_READ_REG(hw, E1000_RNBC); + E1000_READ_REG(hw, E1000_RUC); + E1000_READ_REG(hw, E1000_RFC); + E1000_READ_REG(hw, E1000_ROC); + E1000_READ_REG(hw, E1000_RJC); + E1000_READ_REG(hw, E1000_TORL); + E1000_READ_REG(hw, E1000_TORH); + E1000_READ_REG(hw, E1000_TOTL); + E1000_READ_REG(hw, E1000_TOTH); + E1000_READ_REG(hw, E1000_TPR); + E1000_READ_REG(hw, E1000_TPT); + E1000_READ_REG(hw, E1000_MPTC); + E1000_READ_REG(hw, E1000_BPTC); } /** @@ -763,9 +792,8 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); - if (ret_val) { + if (ret_val) DEBUGOUT("Error configuring flow control\n"); - } out: return ret_val; @@ -978,23 +1006,23 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw) goto out; /* - * If flow control is set to default, set flow control based on - * the EEPROM flow control settings. + * If requested flow control is set to default, set flow control + * based on the EEPROM flow control settings. */ - if (hw->fc.type == e1000_fc_default) { + if (hw->fc.requested_mode == e1000_fc_default) { ret_val = e1000_set_default_fc_generic(hw); if (ret_val) goto out; } /* - * We want to save off the original Flow Control configuration just - * in case we get disconnected and then reconnected into a different - * hub or switch with different Flow Control capabilities. + * Save off the requested flow control mode for use later. Depending + * on the link partner's capabilities, we may or may not use this mode. */ - hw->fc.original_type = hw->fc.type; + hw->fc.current_mode = hw->fc.requested_mode; - DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.type); + DEBUGOUT1("After fix-ups FlowControl is now = %x\n", + hw->fc.current_mode); /* Call the necessary media_type subroutine to configure the link. */ ret_val = hw->mac.ops.setup_physical_interface(hw); @@ -1181,7 +1209,7 @@ s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) * do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. */ - switch (hw->fc.type) { + switch (hw->fc.current_mode) { case e1000_fc_none: /* Flow control completely disabled by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); @@ -1247,7 +1275,7 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) * ability to transmit pause frames is not enabled, then these * registers will be set to 0. */ - if (hw->fc.type & e1000_fc_tx_pause) { + if (hw->fc.current_mode & e1000_fc_tx_pause) { /* * We need to set up the Receive Threshold high and low water * marks as well as (optionally) enabling the transmission of @@ -1296,12 +1324,12 @@ s32 e1000_set_default_fc_generic(struct e1000_hw *hw) } if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) - hw->fc.type = e1000_fc_none; + hw->fc.requested_mode = e1000_fc_none; else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR) - hw->fc.type = e1000_fc_tx_pause; + hw->fc.requested_mode = e1000_fc_tx_pause; else - hw->fc.type = e1000_fc_full; + hw->fc.requested_mode = e1000_fc_full; out: return ret_val; @@ -1333,7 +1361,7 @@ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) * receive flow control. * * The "Case" statement below enables/disable flow control - * according to the "hw->fc.type" parameter. + * according to the "hw->fc.current_mode" parameter. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled @@ -1344,9 +1372,9 @@ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) * 3: Both Rx and Tx flow control (symmetric) is enabled. * other: No other values should be possible at this point. */ - DEBUGOUT1("hw->fc.type = %u\n", hw->fc.type); + DEBUGOUT1("hw->fc.current_mode = %u\n", hw->fc.current_mode); - switch (hw->fc.type) { + switch (hw->fc.current_mode) { case e1000_fc_none: ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); break; @@ -1386,7 +1414,6 @@ out: s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; u16 speed, duplex; @@ -1424,10 +1451,10 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ - ret_val = phy->ops.read_reg(hw, PHY_STATUS, &mii_status_reg); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) goto out; - ret_val = phy->ops.read_reg(hw, PHY_STATUS, &mii_status_reg); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) goto out; @@ -1444,11 +1471,11 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) * Page Ability Register (Address 5) to determine how * flow control was negotiated. */ - ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, + ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg); if (ret_val) goto out; - ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, + ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); if (ret_val) goto out; @@ -1496,11 +1523,11 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ - if (hw->fc.original_type == e1000_fc_full) { - hw->fc.type = e1000_fc_full; + if (hw->fc.requested_mode == e1000_fc_full) { + hw->fc.current_mode = e1000_fc_full; DEBUGOUT("Flow Control = FULL.\r\n"); } else { - hw->fc.type = e1000_fc_rx_pause; + hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = " "RX PAUSE frames only.\r\n"); } @@ -1517,7 +1544,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.type = e1000_fc_tx_pause; + hw->fc.current_mode = e1000_fc_tx_pause; DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); } /* @@ -1532,14 +1559,14 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.type = e1000_fc_rx_pause; + hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); } else { /* * Per the IEEE spec, at this point flow control * should be disabled. */ - hw->fc.type = e1000_fc_none; + hw->fc.current_mode = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\r\n"); } @@ -1555,7 +1582,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) } if (duplex == HALF_DUPLEX) - hw->fc.type = e1000_fc_none; + hw->fc.current_mode = e1000_fc_none; /* * Now we call a subroutine to actually force the MAC @@ -1767,7 +1794,7 @@ out: * @hw: pointer to the HW structure * **/ -s32 e1000_id_led_init_generic(struct e1000_hw * hw) +s32 e1000_id_led_init_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; @@ -2070,13 +2097,11 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw) goto out; } - if (!mac->ifs_params_forced) { - mac->current_ifs_val = 0; - mac->ifs_min_val = IFS_MIN; - mac->ifs_max_val = IFS_MAX; - mac->ifs_step_size = IFS_STEP; - mac->ifs_ratio = IFS_RATIO; - } + mac->current_ifs_val = 0; + mac->ifs_min_val = IFS_MIN; + mac->ifs_max_val = IFS_MAX; + mac->ifs_step_size = IFS_STEP; + mac->ifs_ratio = IFS_RATIO; mac->in_ifs_mode = FALSE; E1000_WRITE_REG(hw, E1000_AIT, 0); diff --git a/sys/dev/e1000/e1000_mac.h b/sys/dev/e1000/e1000_mac.h index 5992764..7f9baa9 100644 --- a/sys/dev/e1000/e1000_mac.h +++ b/sys/dev/e1000/e1000_mac.h @@ -54,12 +54,16 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw); s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw); s32 e1000_cleanup_led_generic(struct e1000_hw *hw); s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw); +s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw); s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw); s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw); s32 e1000_force_mac_fc_generic(struct e1000_hw *hw); s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw); s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw); s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw); +void e1000_set_lan_id_single_port(struct e1000_hw *hw); +void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw); +void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw); s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, u16 *duplex); @@ -71,13 +75,11 @@ s32 e1000_led_off_generic(struct e1000_hw *hw); void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, u32 rar_used_count, u32 rar_count); -s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw); s32 e1000_set_default_fc_generic(struct e1000_hw *hw); s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw); s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw); s32 e1000_setup_led_generic(struct e1000_hw *hw); s32 e1000_setup_link_generic(struct e1000_hw *hw); -s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, u32 offset, u8 data); @@ -92,7 +94,6 @@ void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw); void e1000_put_hw_semaphore_generic(struct e1000_hw *hw); void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); -void e1000_remove_device_generic(struct e1000_hw *hw); void e1000_reset_adaptive_generic(struct e1000_hw *hw); void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop); void e1000_update_adaptive_generic(struct e1000_hw *hw); diff --git a/sys/dev/e1000/e1000_manage.c b/sys/dev/e1000/e1000_manage.c index 88753ad..b1f6541 100644 --- a/sys/dev/e1000/e1000_manage.c +++ b/sys/dev/e1000/e1000_manage.c @@ -70,7 +70,7 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length) * and also checks whether the previous command is completed. It busy waits * in case of previous command is not completed. **/ -s32 e1000_mng_enable_host_if_generic(struct e1000_hw * hw) +s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) { u32 hicr; s32 ret_val = E1000_SUCCESS; @@ -118,8 +118,8 @@ bool e1000_check_mng_mode_generic(struct e1000_hw *hw) fwsm = E1000_READ_REG(hw, E1000_FWSM); - return ((fwsm & E1000_FWSM_MODE_MASK) == - (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); + return (fwsm & E1000_FWSM_MODE_MASK) == + (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); } /** @@ -195,7 +195,7 @@ out: * * Writes the DHCP information to the host interface. **/ -s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw * hw, u8 *buffer, +s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, u16 length) { struct e1000_host_mng_command_header hdr; @@ -241,8 +241,8 @@ out: * * Writes the command header after does the checksum calculation. **/ -s32 e1000_mng_write_cmd_header_generic(struct e1000_hw * hw, - struct e1000_host_mng_command_header * hdr) +s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, + struct e1000_host_mng_command_header *hdr) { u16 i, length = sizeof(struct e1000_host_mng_command_header); @@ -275,7 +275,7 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw * hw, * It also does alignment considerations to do the writes in most efficient * way. Also fills up the sum of the buffer in *buffer parameter. **/ -s32 e1000_mng_host_if_write_generic(struct e1000_hw * hw, u8 *buffer, +s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum) { u8 *tmp; @@ -324,7 +324,8 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw * hw, u8 *buffer, *sum += *(tmp + j); } - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); + E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, + data); } if (remaining) { for (j = 0; j < sizeof(u32); j++) { diff --git a/sys/dev/e1000/e1000_nvm.c b/sys/dev/e1000/e1000_nvm.c index 1a99cac..8492d80 100644 --- a/sys/dev/e1000/e1000_nvm.c +++ b/sys/dev/e1000/e1000_nvm.c @@ -148,7 +148,8 @@ static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) mask = 0x01 << (count - 1); if (nvm->type == e1000_nvm_eeprom_microwire) eecd &= ~E1000_EECD_DO; - else if (nvm->type == e1000_nvm_eeprom_spi) + else + if (nvm->type == e1000_nvm_eeprom_spi) eecd |= E1000_EECD_DO; do { @@ -310,7 +311,8 @@ static void e1000_standby_nvm(struct e1000_hw *hw) usec_delay(nvm->delay_usec); e1000_lower_eec_clk(hw, &eecd); - } else if (nvm->type == e1000_nvm_eeprom_spi) { + } else + if (nvm->type == e1000_nvm_eeprom_spi) { /* Toggle CS to flush commands */ eecd |= E1000_EECD_CS; E1000_WRITE_REG(hw, E1000_EECD, eecd); @@ -391,7 +393,8 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) /* Set CS */ eecd |= E1000_EECD_CS; E1000_WRITE_REG(hw, E1000_EECD, eecd); - } else if (nvm->type == e1000_nvm_eeprom_spi) { + } else + if (nvm->type == e1000_nvm_eeprom_spi) { /* Clear SK and CS */ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); E1000_WRITE_REG(hw, E1000_EECD, eecd); @@ -671,7 +674,7 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) } } - msec_delay(nvm->semaphore_delay); + msec_delay(10); release: nvm->ops.release(hw); @@ -899,9 +902,8 @@ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) } checksum = (u16) NVM_SUM - checksum; ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); - if (ret_val) { + if (ret_val) DEBUGOUT("NVM Write Error while updating checksum.\n"); - } out: return ret_val; diff --git a/sys/dev/e1000/e1000_osdep.c b/sys/dev/e1000/e1000_osdep.c index 60be867..b902685 100644 --- a/sys/dev/e1000/e1000_osdep.c +++ b/sys/dev/e1000/e1000_osdep.c @@ -79,23 +79,3 @@ e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) *value = (u16)result; return (E1000_SUCCESS); } - -int32_t -e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, uint32_t size) -{ - int32_t error = 0; - - hw->dev_spec = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); - if (hw->dev_spec == NULL) - error = ENOMEM; - - return (error); -} - -void -e1000_free_dev_spec_struct(struct e1000_hw *hw) -{ - if (hw->dev_spec != NULL) - free(hw->dev_spec, M_DEVBUF); - return; -} diff --git a/sys/dev/e1000/e1000_osdep.h b/sys/dev/e1000/e1000_osdep.h index 8a63950..b478f29 100644 --- a/sys/dev/e1000/e1000_osdep.h +++ b/sys/dev/e1000/e1000_osdep.h @@ -93,6 +93,10 @@ typedef int16_t s16; typedef int8_t s8; typedef boolean_t bool; +#define __le16 u16 +#define __le32 u32 +#define __le64 u64 + struct e1000_osdep { bus_space_tag_t mem_bus_space_tag; diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c index 5ef2643..2e4d046 100644 --- a/sys/dev/e1000/e1000_phy.c +++ b/sys/dev/e1000/e1000_phy.c @@ -35,6 +35,8 @@ #include "e1000_api.h" static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); +static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, + u16 *data, bool read); /* Cable length tables */ static const u16 e1000_m88_cable_length_table[] = { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; @@ -84,6 +86,7 @@ void e1000_init_phy_ops_generic(struct e1000_hw *hw) phy->ops.write_reg = e1000_null_write_reg; phy->ops.power_up = e1000_null_phy_generic; phy->ops.power_down = e1000_null_phy_generic; + phy->ops.cfg_on_link_up = e1000_null_ops_generic; } /** @@ -338,8 +341,7 @@ s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) if (ret_val) goto out; - ret_val = e1000_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, + ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); @@ -370,8 +372,7 @@ s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) if (ret_val) goto out; - ret_val = e1000_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, + ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); @@ -413,8 +414,7 @@ s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) } } - ret_val = e1000_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, + ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); @@ -455,8 +455,7 @@ s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) } } - ret_val = e1000_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, + ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); @@ -579,19 +578,19 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; switch (phy->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; + case 1: + phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; + break; + case 2: + phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; + break; + case 3: + phy_data |= M88E1000_PSCR_AUTO_X_1000T; + break; + case 0: + default: + phy_data |= M88E1000_PSCR_AUTO_X_MODE; + break; } /* @@ -620,8 +619,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) * Force TX_CLK in the Extended PHY Specific Control Register * to 25MHz clock. */ - ret_val = phy->ops.read_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; @@ -640,8 +638,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); } - ret_val = phy->ops.write_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, + ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; @@ -909,8 +906,7 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) if (phy->autoneg_mask & ADVERTISE_1000_FULL) { /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = phy->ops.read_reg(hw, - PHY_1000T_CTRL, + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); if (ret_val) goto out; @@ -962,9 +958,8 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) } /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if (phy->autoneg_advertised & ADVERTISE_1000_HALF) { + if (phy->autoneg_advertised & ADVERTISE_1000_HALF) DEBUGOUT("Advertise 1000mb Half duplex request denied!\n"); - } /* Do we want to advertise 1000 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { @@ -990,7 +985,7 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) * other: No software override. The flow control configuration * in the EEPROM is used. */ - switch (hw->fc.type) { + switch (hw->fc.current_mode) { case e1000_fc_none: /* * Flow control (Rx & Tx) is completely disabled by a @@ -1166,9 +1161,8 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) if (ret_val) goto out; - if (!link) { + if (!link) DEBUGOUT("Link taking longer than expected.\n"); - } /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, @@ -1235,10 +1229,8 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) if (phy->autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); - ret_val = e1000_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); + ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, + 100000, &link); if (ret_val) goto out; @@ -1258,10 +1250,8 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) } /* Try once more */ - ret_val = e1000_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); + ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, + 100000, &link); if (ret_val) goto out; } @@ -1315,7 +1305,7 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) DEBUGFUNC("e1000_phy_force_speed_duplex_setup"); /* Turn off flow control when forcing speed/duplex */ - hw->fc.type = e1000_fc_none; + hw->fc.current_mode = e1000_fc_none; /* Force speed/duplex on the mac */ ctrl = E1000_READ_REG(hw, E1000_CTRL); @@ -1388,8 +1378,7 @@ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) if (!active) { data &= ~IGP02E1000_PM_D3_LPLU; - ret_val = phy->ops.write_reg(hw, - IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; @@ -1430,22 +1419,19 @@ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { data |= IGP02E1000_PM_D3_LPLU; - ret_val = phy->ops.write_reg(hw, - IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); } @@ -1684,10 +1670,15 @@ s32 e1000_get_cable_length_m88(struct e1000_hw *hw) index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT; - phy->min_cable_length = e1000_m88_cable_length_table[index]; - phy->max_cable_length = e1000_m88_cable_length_table[index+1]; + if (index < M88E1000_CABLE_LENGTH_TABLE_SIZE + 1) { + phy->min_cable_length = e1000_m88_cable_length_table[index]; + phy->max_cable_length = e1000_m88_cable_length_table[index+1]; - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; + phy->cable_length = (phy->min_cable_length + + phy->max_cable_length) / 2; + } else { + ret_val = E1000_ERR_PHY; + } out: return ret_val; @@ -1807,8 +1798,7 @@ s32 e1000_get_phy_info_m88(struct e1000_hw *hw) goto out; phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) - ? TRUE - : FALSE; + ? TRUE : FALSE; ret_val = e1000_check_polarity_m88(hw); if (ret_val) @@ -2143,10 +2133,10 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) * addresses. It tests each by reading the PHY ID registers and * checking for a match. **/ -s32 e1000_determine_phy_address(struct e1000_hw* hw) +s32 e1000_determine_phy_address(struct e1000_hw *hw) { s32 ret_val = -E1000_ERR_PHY_TYPE; - u32 phy_addr= 0; + u32 phy_addr = 0; u32 i; enum e1000_phy_type phy_type = e1000_phy_unknown; @@ -2158,10 +2148,10 @@ s32 e1000_determine_phy_address(struct e1000_hw* hw) e1000_get_phy_id(hw); phy_type = e1000_get_phy_type_from_id(hw->phy.id); - /* - * If phy_type is valid, break - we found our - * PHY address - */ + /* + * If phy_type is valid, break - we found our + * PHY address + */ if (phy_type != e1000_phy_unknown) { ret_val = E1000_SUCCESS; goto out; @@ -2211,8 +2201,8 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, - offset, &data, FALSE); + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, + FALSE); goto out; } @@ -2245,8 +2235,7 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) } } - ret_val = e1000_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, + ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); @@ -2276,8 +2265,8 @@ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, - offset, data, TRUE); + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, + TRUE); goto out; } @@ -2310,9 +2299,8 @@ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) } } - ret_val = e1000_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); + ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); hw->phy.ops.release(hw); out: @@ -2361,7 +2349,7 @@ s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) } } - ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); @@ -2435,8 +2423,8 @@ out: * 4) Read or write the data using the data opcode (0x12) * 5) Restore 769_17.2 to its original value **/ -s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, - u32 offset, u16 *data, bool read) +static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, + u16 *data, bool read) { s32 ret_val; u16 reg = ((u16)offset); diff --git a/sys/dev/e1000/e1000_phy.h b/sys/dev/e1000/e1000_phy.h index 0aa03e6..06bcaf0 100644 --- a/sys/dev/e1000/e1000_phy.h +++ b/sys/dev/e1000/e1000_phy.h @@ -1,4 +1,4 @@ -/****************************************************************************** +/***************************************************************************** Copyright (c) 2001-2008, Intel Corporation All rights reserved. @@ -35,19 +35,6 @@ #ifndef _E1000_PHY_H_ #define _E1000_PHY_H_ -enum e1000_ms_type { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -}; - -enum e1000_smart_speed { - e1000_smart_speed_default = 0, - e1000_smart_speed_on, - e1000_smart_speed_off -}; - void e1000_init_phy_ops_generic(struct e1000_hw *hw); s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data); void e1000_null_phy_generic(struct e1000_hw *hw); @@ -87,11 +74,9 @@ s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, u32 usec_interval, bool *success); s32 e1000_phy_init_script_igp3(struct e1000_hw *hw); enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); -s32 e1000_determine_phy_address(struct e1000_hw* hw); +s32 e1000_determine_phy_address(struct e1000_hw *hw); s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, - bool read); s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); void e1000_power_up_phy_copper(struct e1000_hw *hw); diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h index 5edd502..1dbd56b 100644 --- a/sys/dev/e1000/e1000_regs.h +++ b/sys/dev/e1000/e1000_regs.h @@ -46,6 +46,7 @@ #define E1000_SCTL 0x00024 /* SerDes Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ +#define E1000_FEXT 0x0002C /* Future Extended - RW */ #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ #define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ @@ -120,6 +121,8 @@ #define E1000_RXCTL(_n) (0x0C014 + (0x40 * (_n))) #define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n))) #define E1000_TXCTL(_n) (0x0E014 + (0x40 * (_n))) +#define E1000_RXCTL(_n) (0x0C014 + (0x40 * (_n))) +#define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n))) #define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ #define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ /* @@ -130,31 +133,48 @@ * Example usage: * E1000_RDBAL_REG(current_rx_queue) */ -#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : (0x0C000 + ((_n) * 0x40))) -#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : (0x0C004 + ((_n) * 0x40))) -#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : (0x0C008 + ((_n) * 0x40))) -#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : (0x0C00C + ((_n) * 0x40))) -#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : (0x0C010 + ((_n) * 0x40))) -#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : (0x0C018 + ((_n) * 0x40))) -#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : (0x0C028 + ((_n) * 0x40))) -#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : (0x0E000 + ((_n) * 0x40))) -#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : (0x0E004 + ((_n) * 0x40))) -#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : (0x0E008 + ((_n) * 0x40))) -#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : (0x0E010 + ((_n) * 0x40))) -#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : (0x0E018 + ((_n) * 0x40))) -#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : (0x0E028 + ((_n) * 0x40))) -#define E1000_TARC(_n) (0x03840 + (_n << 8)) +#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \ + (0x0C000 + ((_n) * 0x40))) +#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \ + (0x0C004 + ((_n) * 0x40))) +#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \ + (0x0C008 + ((_n) * 0x40))) +#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \ + (0x0C00C + ((_n) * 0x40))) +#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \ + (0x0C010 + ((_n) * 0x40))) +#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \ + (0x0C018 + ((_n) * 0x40))) +#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \ + (0x0C028 + ((_n) * 0x40))) +#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \ + (0x0E000 + ((_n) * 0x40))) +#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \ + (0x0E004 + ((_n) * 0x40))) +#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \ + (0x0E008 + ((_n) * 0x40))) +#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \ + (0x0E010 + ((_n) * 0x40))) +#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \ + (0x0E018 + ((_n) * 0x40))) +#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \ + (0x0E028 + ((_n) * 0x40))) +#define E1000_TARC(_n) (0x03840 + (_n << 8)) #define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8)) #define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8)) -#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : (0x0E038 + ((_n) * 0x40))) -#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : (0x0E03C + ((_n) * 0x40))) +#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \ + (0x0E038 + ((_n) * 0x40))) +#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \ + (0x0E03C + ((_n) * 0x40))) #define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */ #define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ #define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */ #define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ #define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4)) -#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : (0x054E0 + ((_i - 16) * 8))) -#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : (0x054E4 + ((_i - 16) * 8))) +#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ + (0x054E0 + ((_i - 16) * 8))) +#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ + (0x054E4 + ((_i - 16) * 8))) #define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8)) #define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4)) #define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4)) @@ -240,15 +260,24 @@ #define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ #define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */ #define E1000_IAC 0x04100 /* Interrupt Assertion Count */ -#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */ -#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */ -#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */ -#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */ +#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */ +#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */ +#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */ +#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */ #define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ -#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */ -#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */ +#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */ +#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */ #define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ +#define E1000_VFGPRC 0x00F10 +#define E1000_VFGORC 0x00F18 +#define E1000_VFMPRC 0x00F3C +#define E1000_VFGPTC 0x00F14 +#define E1000_VFGOTC 0x00F34 +#define E1000_VFGOTLBC 0x00F50 +#define E1000_VFGPTLBC 0x00F44 +#define E1000_VFGORLBC 0x00F48 +#define E1000_VFGPRLBC 0x00F40 #define E1000_LSECTXUT 0x04300 /* LinkSec Tx Untagged Packet Count - OutPktsUntagged */ #define E1000_LSECTXPKTE 0x04304 /* LinkSec Encrypted Tx Packets Count - OutPktsEncrypted */ #define E1000_LSECTXPKTP 0x04308 /* LinkSec Protected Tx Packet Count - OutPktsProtected */ @@ -376,14 +405,19 @@ #define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */ #define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/ #define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */ -#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register (_i) - RW */ -#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr low reg 0 - RW */ -#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr upper reg 0 - RW */ -#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry message reg 0 - RW */ -#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry vector ctrl reg 0 - RW */ +#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register + * (_i) - RW */ +#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr + * low reg - RW */ +#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr + * upper reg - RW */ +#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry + * message reg - RW */ +#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry + * vector ctrl reg - RW */ #define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */ -#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW Array */ -#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */ +#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */ +#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */ #define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ #define E1000_RSSIR 0x05868 /* RSS Interrupt Request */ /* VT Registers */ @@ -419,7 +453,7 @@ #define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ #define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ #define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ -#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Message Type - RW */ +#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ #define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ /* Filtering Registers */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 74c1e62..c962358 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -34,7 +34,6 @@ #ifdef HAVE_KERNEL_OPTION_HEADERS #include "opt_device_polling.h" -#include "opt_inet.h" #endif #include @@ -51,6 +50,7 @@ #include #include #include +#include #ifdef EM_TIMESYNC #include #include @@ -92,7 +92,7 @@ int em_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char em_driver_version[] = "6.9.5"; +char em_driver_version[] = "6.9.6"; /********************************************************************* @@ -277,7 +277,10 @@ static void em_set_multi(struct adapter *); static void em_print_hw_stats(struct adapter *); static void em_update_link_status(struct adapter *); static int em_get_buf(struct adapter *, int); -static void em_enable_hw_vlans(struct adapter *); + +static void em_register_vlan(void *, struct ifnet *, u16); +static void em_unregister_vlan(void *, struct ifnet *, u16); + static int em_xmit(struct adapter *, struct mbuf **); static void em_smartspeed(struct adapter *); static int em_82547_fifo_workaround(struct adapter *, int); @@ -784,6 +787,12 @@ em_attach(device_t dev) else adapter->pcix_82544 = FALSE; + /* Register for VLAN events */ + adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, + em_register_vlan, 0, EVENTHANDLER_PRI_FIRST); + adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, + em_unregister_vlan, 0, EVENTHANDLER_PRI_FIRST); + /* Tell the stack that the interface is not active */ adapter->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); @@ -796,7 +805,6 @@ err_rx_struct: err_tx_struct: err_hw_init: em_release_hw_control(adapter); - e1000_remove_device(&adapter->hw); em_dma_free(adapter, &adapter->rxdma); err_rx_desc: em_dma_free(adapter, &adapter->txdma); @@ -867,6 +875,12 @@ em_detach(device_t dev) EM_TX_UNLOCK(adapter); EM_CORE_UNLOCK(adapter); + /* Unregister VLAN events */ + if (adapter->vlan_attach != NULL) + EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach); + if (adapter->vlan_detach != NULL) + EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); + ether_ifdetach(adapter->ifp); callout_drain(&adapter->timer); callout_drain(&adapter->tx_fifo_timer); @@ -875,7 +889,6 @@ em_detach(device_t dev) bus_generic_detach(dev); if_free(ifp); - e1000_remove_device(&adapter->hw); em_free_transmit_structures(adapter); em_free_receive_structures(adapter); @@ -1448,8 +1461,16 @@ em_init_locked(struct adapter *adapter) /* Setup VLAN support, basic and offload if available */ E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN); - if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) - em_enable_hw_vlans(adapter); + + /* New register interface replaces this but + waiting on kernel support to be added */ + if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) && + ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)) { + u32 ctrl; + ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); + ctrl |= E1000_CTRL_VME; + E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); + } /* Set hardware offload abilities */ ifp->if_hwassist = 0; @@ -2547,6 +2568,8 @@ em_update_link_status(struct adapter *adapter) /* Do the work to read phy */ e1000_check_for_link(hw); link_check = !hw->mac.get_link_status; + if (link_check) /* ESB2 fix */ + e1000_cfg_on_link_up(hw); } else link_check = TRUE; break; @@ -3060,7 +3083,7 @@ em_hardware_init(struct adapter *adapter) else adapter->hw.fc.pause_time = EM_FC_PAUSE_TIME; adapter->hw.fc.send_xon = TRUE; - adapter->hw.fc.type = e1000_fc_full; + adapter->hw.fc.requested_mode = e1000_fc_full; if (e1000_init_hw(&adapter->hw) < 0) { device_printf(dev, "Hardware Initialization Failed\n"); @@ -4622,17 +4645,64 @@ em_receive_checksum(struct adapter *adapter, } /* - * This turns on the hardware offload of the VLAN - * tag insertion and strip + * This routine is run via an vlan + * config EVENT */ static void -em_enable_hw_vlans(struct adapter *adapter) +em_register_vlan(void *unused, struct ifnet *ifp, u16 vtag) { - u32 ctrl; + struct adapter *adapter = ifp->if_softc; + u32 ctrl, rctl, index, vfta; ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); ctrl |= E1000_CTRL_VME; E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); + + /* Setup for Hardware Filter */ + rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); + rctl |= E1000_RCTL_VFE; + rctl &= ~E1000_RCTL_CFIEN; + E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); + + /* Make entry in the hardware filter table */ + index = ((vtag >> 5) & 0x7F); + vfta = E1000_READ_REG_ARRAY(&adapter->hw, E1000_VFTA, index); + vfta |= (1 << (vtag & 0x1F)); + E1000_WRITE_REG_ARRAY(&adapter->hw, E1000_VFTA, index, vfta); + + /* Update the frame size */ + E1000_WRITE_REG(&adapter->hw, E1000_RLPML, + adapter->max_frame_size + VLAN_TAG_SIZE); + +} + +/* + * This routine is run via an vlan + * unconfig EVENT + */ +static void +em_unregister_vlan(void *unused, struct ifnet *ifp, u16 vtag) +{ + struct adapter *adapter = ifp->if_softc; + u32 index, vfta; + + /* Remove entry in the hardware filter table */ + index = ((vtag >> 5) & 0x7F); + vfta = E1000_READ_REG_ARRAY(&adapter->hw, E1000_VFTA, index); + vfta &= ~(1 << (vtag & 0x1F)); + E1000_WRITE_REG_ARRAY(&adapter->hw, E1000_VFTA, index, vfta); + /* Have all vlans unregistered? */ + if (adapter->ifp->if_vlantrunk == NULL) { + u32 rctl; + /* Turn off the filter table */ + rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); + rctl &= ~E1000_RCTL_VFE; + rctl |= E1000_RCTL_CFIEN; + E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); + /* Reset the frame size */ + E1000_WRITE_REG(&adapter->hw, E1000_RLPML, + adapter->max_frame_size); + } } static void diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index 8fa2a43..889ceae 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -339,6 +339,9 @@ struct adapter { struct task tx_task; struct taskqueue *tq; /* private task queue */ + eventhandler_tag vlan_attach; + eventhandler_tag vlan_detach; + /* Management and WOL features */ int wol; int has_manage; diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 3beee5f..ac7ff21 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -95,7 +95,7 @@ int igb_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char igb_driver_version[] = "version - 1.4.0"; +char igb_driver_version[] = "version - 1.4.1"; /********************************************************************* @@ -2442,9 +2442,9 @@ igb_hardware_init(struct adapter *adapter) /* Set Flow control, use the tunable location if sane */ if ((igb_fc_setting >= 0) || (igb_fc_setting < 4)) - adapter->hw.fc.type = igb_fc_setting; + adapter->hw.fc.requested_mode = igb_fc_setting; else - adapter->hw.fc.type = e1000_fc_none; + adapter->hw.fc.requested_mode = e1000_fc_none; if (e1000_init_hw(&adapter->hw) < 0) { device_printf(dev, "Hardware Initialization Failed\n"); @@ -3483,7 +3483,7 @@ igb_setup_receive_ring(struct rx_ring *rxr) device_printf(dev,"LRO Initialization failed!\n"); goto fail; } - device_printf(dev,"RX LRO Initialized\n"); + INIT_DEBUGOUT("RX LRO Initialized\n"); lro->ifp = adapter->ifp; } -- cgit v1.1