diff options
author | chenlu chen - Sun Microsystems - Beijing China <Chenlu.Chen@Sun.COM> | 2009-01-20 09:31:31 +0800 |
---|---|---|
committer | chenlu chen - Sun Microsystems - Beijing China <Chenlu.Chen@Sun.COM> | 2009-01-20 09:31:31 +0800 |
commit | 80a11ad227f9c82cd6e7cf5c8913a37f00b7af0e (patch) | |
tree | de77136b4fdaad7ede944841dba5612ac26006b2 /usr/src | |
parent | 48794f22b496c8c5aaa74b67fdff1a4c0409a7a7 (diff) | |
download | illumos-joyent-80a11ad227f9c82cd6e7cf5c8913a37f00b7af0e.tar.gz |
6708291 igb needs to support the new chipset Kawela
6737111 panic in igb_main.c(line: 1872): assertion failed: tx_ring->tcb_free == tx_ring->free_list_size
6740801 igb's rx bind function does not set newly desballoc-ed mblk to be ip header aligned
Diffstat (limited to 'usr/src')
24 files changed, 2325 insertions, 1787 deletions
diff --git a/usr/src/uts/common/io/igb/igb_82575.c b/usr/src/uts/common/io/igb/igb_82575.c index beae6e9d87..e68973fb49 100644 --- a/usr/src/uts/common/io/igb/igb_82575.c +++ b/usr/src/uts/common/io/igb/igb_82575.c @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,21 +22,20 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.61 v2007-12-10_dragonlake5 */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* IntelVersion: 1.94 v2008-10-7 */ /* - * e1000_82575 - * e1000_82576 + * 82575EB Gigabit Network Connection + * 82575EB Gigabit Backplane Connection + * 82575GB Gigabit Network Connection + * 82576 Gigabit Network Connection */ #include "igb_api.h" -#include "igb_82575.h" static s32 e1000_init_phy_params_82575(struct e1000_hw *hw); static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw); @@ -53,12 +52,12 @@ static s32 e1000_init_hw_82575(struct e1000_hw *hw); static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw); static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 *data); -static void e1000_rar_set_82575(struct e1000_hw *hw, u8 *addr, u32 index); static s32 e1000_reset_hw_82575(struct e1000_hw *hw); static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active); static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw); static s32 e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw); +static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data); static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 data); static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw); @@ -72,23 +71,20 @@ static bool e1000_sgmii_active_82575(struct e1000_hw *hw); static s32 e1000_reset_init_script_82575(struct e1000_hw *hw); static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw); static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw); - - -struct e1000_dev_spec_82575 { - bool sgmii_active; -}; +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_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw); /* * 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) { struct e1000_phy_info *phy = &hw->phy; - struct e1000_functions *func = &hw->func; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_phy_params_82575"); @@ -97,27 +93,27 @@ e1000_init_phy_params_82575(struct e1000_hw *hw) phy->type = e1000_phy_none; goto out; } else { - func->power_up_phy = e1000_power_up_phy_copper; - func->power_down_phy = e1000_power_down_phy_copper_82575; + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_82575; } phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 100; - func->acquire_phy = e1000_acquire_phy_82575; - func->check_reset_block = e1000_check_reset_block_generic; - func->commit_phy = e1000_phy_sw_reset_generic; - func->get_cfg_done = e1000_get_cfg_done_82575; - func->release_phy = e1000_release_phy_82575; + phy->ops.acquire = e1000_acquire_phy_82575; + phy->ops.check_reset_block = e1000_check_reset_block_generic; + phy->ops.commit = e1000_phy_sw_reset_generic; + phy->ops.get_cfg_done = e1000_get_cfg_done_82575; + phy->ops.release = e1000_release_phy_82575; if (e1000_sgmii_active_82575(hw)) { - func->reset_phy = e1000_phy_hw_reset_sgmii_82575; - func->read_phy_reg = e1000_read_phy_reg_sgmii_82575; - func->write_phy_reg = e1000_write_phy_reg_sgmii_82575; + phy->ops.reset = e1000_phy_hw_reset_sgmii_82575; + phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575; + phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575; } else { - func->reset_phy = e1000_phy_hw_reset_generic; - func->read_phy_reg = e1000_read_phy_reg_igp; - func->write_phy_reg = e1000_write_phy_reg_igp; + phy->ops.reset = e1000_phy_hw_reset_generic; + phy->ops.read_reg = e1000_read_phy_reg_igp; + phy->ops.write_reg = e1000_write_phy_reg_igp; } /* Set phy->phy_addr and phy->id. */ @@ -127,19 +123,20 @@ e1000_init_phy_params_82575(struct e1000_hw *hw) switch (phy->id) { case M88E1111_I_PHY_ID: phy->type = e1000_phy_m88; - func->check_polarity = e1000_check_polarity_m88; - func->get_phy_info = e1000_get_phy_info_m88; - func->get_cable_length = e1000_get_cable_length_m88; - func->force_speed_duplex = e1000_phy_force_speed_duplex_m88; + phy->ops.check_polarity = e1000_check_polarity_m88; + phy->ops.get_info = e1000_get_phy_info_m88; + phy->ops.get_cable_length = e1000_get_cable_length_m88; + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; break; case IGP03E1000_E_PHY_ID: + case IGP04E1000_E_PHY_ID: phy->type = e1000_phy_igp_3; - func->check_polarity = e1000_check_polarity_igp; - func->get_phy_info = e1000_get_phy_info_igp; - func->get_cable_length = e1000_get_cable_length_igp_2; - func->force_speed_duplex = e1000_phy_force_speed_duplex_igp; - func->set_d0_lplu_state = e1000_set_d0_lplu_state_82575; - func->set_d3_lplu_state = e1000_set_d3_lplu_state_generic; + phy->ops.check_polarity = e1000_check_polarity_igp; + phy->ops.get_info = e1000_get_phy_info_igp; + phy->ops.get_cable_length = e1000_get_cable_length_igp_2; + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; + phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575; + phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; break; default: ret_val = -E1000_ERR_PHY; @@ -153,14 +150,11 @@ 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) { struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_functions *func = &hw->func; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u16 size; @@ -200,13 +194,13 @@ e1000_init_nvm_params_82575(struct e1000_hw *hw) nvm->word_size = 1 << size; /* Function Pointers */ - func->acquire_nvm = e1000_acquire_nvm_82575; - func->read_nvm = e1000_read_nvm_eerd; - func->release_nvm = e1000_release_nvm_82575; - func->update_nvm = e1000_update_nvm_checksum_generic; - func->valid_led_default = e1000_valid_led_default_generic; - func->validate_nvm = e1000_validate_nvm_checksum_generic; - func->write_nvm = e1000_write_nvm_spi; + nvm->ops.acquire = e1000_acquire_nvm_82575; + nvm->ops.read = e1000_read_nvm_eerd; + nvm->ops.release = e1000_release_nvm_82575; + nvm->ops.update = e1000_update_nvm_checksum_generic; + nvm->ops.valid_led_default = e1000_valid_led_default_82575; + nvm->ops.validate = e1000_validate_nvm_checksum_generic; + nvm->ops.write = e1000_write_nvm_spi; return (E1000_SUCCESS); } @@ -214,39 +208,26 @@ 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_functions *func = &hw->func; - 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 * based on the EEPROM. We cannot rely upon device ID. There * is no distinguishable difference between fiber and internal * SerDes mode on the 82575. There can be an external PHY attached - * on the SGMII interface. For this, we'll set sgmii_active to TRUE. + * on the SGMII interface. For this, we'll set sgmii_active to true. */ hw->phy.media_type = e1000_media_type_copper; - dev_spec->sgmii_active = FALSE; + dev_spec->sgmii_active = false; ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); if ((ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) == @@ -254,7 +235,7 @@ e1000_init_mac_params_82575(struct e1000_hw *hw) hw->phy.media_type = e1000_media_type_internal_serdes; ctrl_ext |= E1000_CTRL_I2C_ENA; } else if (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII) { - dev_spec->sgmii_active = TRUE; + dev_spec->sgmii_active = true; ctrl_ext |= E1000_CTRL_I2C_ENA; } else { ctrl_ext &= ~E1000_CTRL_I2C_ENA; @@ -265,85 +246,84 @@ e1000_init_mac_params_82575(struct e1000_hw *hw) mac->mta_reg_count = 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES_82575; + if (mac->type == e1000_82576) + mac->rar_entry_count = E1000_RAR_ENTRIES_82576; /* Set if part includes ASF firmware */ - mac->asf_firmware_present = TRUE; + mac->asf_firmware_present = true; /* Set if manageability features are enabled. */ mac->arc_subsystem_valid = (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK) - ? TRUE : FALSE; + ? true : false; /* Function pointers */ /* bus type/speed/width */ - func->get_bus_info = e1000_get_bus_info_pcie_generic; + mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; /* reset */ - func->reset_hw = e1000_reset_hw_82575; + mac->ops.reset_hw = e1000_reset_hw_82575; /* hw initialization */ - func->init_hw = e1000_init_hw_82575; + mac->ops.init_hw = e1000_init_hw_82575; /* link setup */ - func->setup_link = e1000_setup_link_generic; + mac->ops.setup_link = e1000_setup_link_generic; /* physical interface link setup */ - func->setup_physical_interface = + mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) ? e1000_setup_copper_link_82575 : e1000_setup_fiber_serdes_link_82575; + /* physical interface shutdown */ + mac->ops.shutdown_serdes = e1000_shutdown_fiber_serdes_link_82575; /* check for link */ - func->check_for_link = e1000_check_for_link_82575; + mac->ops.check_for_link = e1000_check_for_link_82575; /* receive address register setting */ - func->rar_set = e1000_rar_set_82575; + mac->ops.rar_set = e1000_rar_set_generic; /* read mac address */ - func->read_mac_addr = e1000_read_mac_addr_82575; + mac->ops.read_mac_addr = e1000_read_mac_addr_82575; /* multicast address update */ - func->update_mc_addr_list = e1000_update_mc_addr_list_generic; + mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82575; /* writing VFTA */ - func->write_vfta = e1000_write_vfta_generic; + mac->ops.write_vfta = e1000_write_vfta_generic; /* clearing VFTA */ - func->clear_vfta = e1000_clear_vfta_generic; + mac->ops.clear_vfta = e1000_clear_vfta_generic; /* setting MTA */ - func->mta_set = e1000_mta_set_generic; + mac->ops.mta_set = e1000_mta_set_generic; /* blink LED */ - func->blink_led = e1000_blink_led_generic; + mac->ops.blink_led = e1000_blink_led_generic; /* setup LED */ - func->setup_led = e1000_setup_led_generic; + mac->ops.setup_led = e1000_setup_led_generic; /* cleanup LED */ - func->cleanup_led = e1000_cleanup_led_generic; + mac->ops.cleanup_led = e1000_cleanup_led_generic; /* turn on/off LED */ - func->led_on = e1000_led_on_generic; - func->led_off = e1000_led_off_generic; - /* remove device */ - func->remove_device = e1000_remove_device_generic; + mac->ops.led_on = e1000_led_on_generic; + mac->ops.led_off = e1000_led_off_generic; /* clear hardware counters */ - func->clear_hw_cntrs = e1000_clear_hw_cntrs_82575; + mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575; /* link info */ - func->get_link_up_info = e1000_get_link_up_info_82575; + 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) { DEBUGFUNC("e1000_init_function_pointers_82575"); - hw->func.init_mac_params = e1000_init_mac_params_82575; - hw->func.init_nvm_params = e1000_init_nvm_params_82575; - hw->func.init_phy_params = e1000_init_phy_params_82575; + hw->mac.ops.init_params = e1000_init_mac_params_82575; + hw->nvm.ops.init_params = e1000_init_nvm_params_82575; + hw->phy.ops.init_params = e1000_init_phy_params_82575; } /* * 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) @@ -361,8 +341,7 @@ 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) @@ -488,10 +467,10 @@ e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 data) } /* - * e1000_get_phy_id_82575 - Retreive PHY addr and id + * e1000_get_phy_id_82575 - Retrieve PHY addr and id * @hw: pointer to the HW structure * - * Retreives the PHY address and ID for both PHY's which do and do not use + * Retrieves the PHY address and ID for both PHY's which do and do not use * sgmi interface. */ static s32 @@ -560,7 +539,7 @@ out: static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) { - s32 ret_val; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575"); @@ -571,15 +550,18 @@ e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) DEBUGOUT("Soft resetting SGMII attached PHY...\n"); + if (!(hw->phy.ops.write_reg)) + goto out; + /* * SFP documentation requires the following to configure the SPF module * to work on SGMII. No further documentation is given. */ - ret_val = e1000_write_phy_reg(hw, 0x1B, 0x8084); + ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); if (ret_val) goto out; - ret_val = e1000_phy_commit(hw); + ret_val = hw->phy.ops.commit(hw); out: return (ret_val); @@ -588,7 +570,7 @@ out: /* * e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state * @hw: pointer to the HW structure - * @active: TRUE to enable LPLU, FALSE to disable + * @active: true to enable LPLU, false to disable * * Sets the LPLU D0 state according to the active flag. When * activating LPLU this function also disables smart speed @@ -602,36 +584,39 @@ static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; + s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_set_d0_lplu_state_82575"); - ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); + if (!(hw->phy.ops.read_reg)) + goto out; + + ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) goto out; if (active) { data |= IGP02E1000_PM_D0_LPLU; - ret_val = e1000_write_phy_reg(hw, + 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 = e1000_read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else { data &= ~IGP02E1000_PM_D0_LPLU; - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); /* @@ -641,27 +626,27 @@ e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1000_read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1000_read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) @@ -677,7 +662,7 @@ out: * e1000_acquire_nvm_82575 - Request for access to EEPROM * @hw: pointer to the HW structure * - * Acquire the necessary semaphores for exclussive access to the EEPROM. + * Acquire the necessary semaphores for exclusive access to the EEPROM. * Set the EEPROM access request bit and wait for EEPROM access grant bit. * Return successful if access grant bit set, else clear the request for * EEPROM access and return -E1000_ERR_NVM (-1). @@ -844,7 +829,7 @@ e1000_get_cfg_done_82575(struct e1000_hw *hw) * @duplex: stores the current duplex * * This is a wrapper function, if using the serial gigabit media independent - * interface, use pcs to retreive the link speed and duplex information. + * interface, use PCS to retrieve the link speed and duplex information. * Otherwise, use the generic function to get the link speed and duplex info. */ static s32 @@ -898,7 +883,7 @@ e1000_check_for_link_82575(struct e1000_hw *hw) * @speed: stores the current speed * @duplex: stores the current duplex * - * Using the physical coding sub-layer (PCS), retreive the current speed and + * Using the physical coding sub-layer (PCS), retrieve the current speed and * duplex, then store the values in the pointers provided. */ static s32 @@ -911,7 +896,7 @@ e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575"); /* Set up defaults for the return values of this function */ - mac->serdes_has_link = FALSE; + mac->serdes_has_link = false; *speed = 0; *duplex = 0; @@ -928,7 +913,7 @@ e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, * can be determined by checking for both link up and link sync ok */ if ((pcs & E1000_PCS_LSTS_LINK_OK) && (pcs & E1000_PCS_LSTS_SYNK_OK)) { - mac->serdes_has_link = TRUE; + mac->serdes_has_link = true; /* Detect and store PCS speed */ if (pcs & E1000_PCS_LSTS_SPEED_1000) { @@ -946,25 +931,147 @@ e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, *duplex = HALF_DUPLEX; } } + return (E1000_SUCCESS); } /* - * e1000_rar_set_82575 - Set receive address register + * e1000_init_rx_addrs_82575 - Initialize receive address's * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register + * @rar_count: receive address registers * - * Sets the receive address array register at index to the address passed - * in by addr. + * Setups the receive address registers by setting the base receive address + * register to the devices MAC address and clearing all the other receive + * address registers to 0. */ static void -e1000_rar_set_82575(struct e1000_hw *hw, u8 *addr, u32 index) +e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count) { - DEBUGFUNC("e1000_rar_set_82575"); + u32 i; + u8 addr[6] = {0, 0, 0, 0, 0, 0}; + /* + * This function is essentially the same as that of + * e1000_init_rx_addrs_generic. However it also takes care + * of the special case where the register offset of the + * second set of RARs begins elsewhere. This is implicitly taken care by + * function e1000_rar_set_generic. + */ + + DEBUGFUNC("e1000_init_rx_addrs_82575"); + + /* Setup the receive address */ + DEBUGOUT("Programming MAC Address into RAR[0]\n"); + hw->mac.ops.rar_set(hw, hw->mac.addr, 0); - if (index < E1000_RAR_ENTRIES_82575) { - e1000_rar_set_generic(hw, addr, index); + /* Zero out the other (rar_entry_count - 1) receive addresses */ + DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count - 1); + for (i = 1; i < rar_count; i++) { + hw->mac.ops.rar_set(hw, addr, i); + } +} + +/* + * e1000_update_mc_addr_list_82575 - Update Multicast addresses + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program + * @rar_used_count: the first RAR register free to program + * @rar_count: total number of supported Receive Address Registers + * + * Updates the Receive Address Registers and Multicast Table Array. + * The caller must have a packed mc_addr_list of multicast addresses. + * The parameter rar_count will usually be hw->mac.rar_entry_count + * unless there are workarounds that change this. + */ +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) +{ + u32 hash_value; + u32 i; + u8 addr[6] = {0, 0, 0, 0, 0, 0}; + /* + * This function is essentially the same as that of + * e1000_update_mc_addr_list_generic. However it also takes care + * of the special case where the register offset of the + * second set of RARs begins elsewhere. This is implicitly taken care by + * function e1000_rar_set_generic. + */ + + DEBUGFUNC("e1000_update_mc_addr_list_82575"); + + /* + * Load the first set of multicast addresses into the exact + * filters (RAR). If there are not enough to fill the RAR + * array, clear the filters. + */ + for (i = rar_used_count; i < rar_count; i++) { + if (mc_addr_count) { + e1000_rar_set_generic(hw, mc_addr_list, i); + mc_addr_count--; + mc_addr_list += ETH_ADDR_LEN; + } else { + e1000_rar_set_generic(hw, addr, i); + } + } + + /* Clear the old settings from the MTA */ + DEBUGOUT("Clearing MTA\n"); + for (i = 0; i < hw->mac.mta_reg_count; i++) { + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + E1000_WRITE_FLUSH(hw); + } + + /* Load any remaining multicast addresses into the hash table. */ + for (; mc_addr_count > 0; mc_addr_count--) { + 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; + } +} + +/* + * e1000_shutdown_fiber_serdes_link_82575 - Remove link during power down + * @hw: pointer to the HW structure + * + * In the case of fiber serdes shut down optics and PCS on driver unload + * when management pass thru is not enabled. + */ +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 (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; + E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); + + /* shutdown the laser */ + reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + reg |= E1000_CTRL_EXT_SDP7_DATA; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); + + /* flush the write to verfiy completion */ + E1000_WRITE_FLUSH(hw); + msec_delay(1); } } @@ -972,8 +1079,7 @@ e1000_rar_set_82575(struct e1000_hw *hw, u8 *addr, u32 index) * 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) @@ -1053,17 +1159,17 @@ e1000_init_hw_82575(struct e1000_hw *hw) /* Disabling VLAN filtering */ DEBUGOUT("Initializing the IEEE VLAN\n"); - e1000_clear_vfta(hw); + mac->ops.clear_vfta(hw); /* Setup the receive address */ - e1000_init_rx_addrs_generic(hw, rar_count); + e1000_init_rx_addrs_82575(hw, rar_count); /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* Setup link and flow control */ - ret_val = e1000_setup_link(hw); + ret_val = mac->ops.setup_link(hw); /* * Clear all of the statistics registers (clear on read). It is @@ -1132,7 +1238,7 @@ e1000_setup_copper_link_82575(struct e1000_hw *hw) * depending on user settings. */ DEBUGOUT("Forcing Speed and Duplex\n"); - ret_val = e1000_phy_force_speed_duplex(hw); + ret_val = hw->phy.ops.force_speed_duplex(hw); if (ret_val) { DEBUGOUT("Error Forcing Speed and Duplex\n"); goto out; @@ -1197,6 +1303,13 @@ e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw) E1000_CTRL_SWDPIN1; E1000_WRITE_REG(hw, E1000_CTRL, reg); + /* Power on phy for 82576 fiber adapters */ + if (hw->mac.type == e1000_82576) { + reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + reg &= ~E1000_CTRL_EXT_SDP7_DATA; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); + } + /* Set switch control to serdes energy detect */ reg = E1000_READ_REG(hw, E1000_CONNSW); reg |= E1000_CONNSW_ENRGSRC; @@ -1229,12 +1342,55 @@ e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw) E1000_PCS_LCTL_FORCE_LINK; /* Force Link */ DEBUGOUT1("Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg); } + + if (hw->mac.type == e1000_82576) { + reg |= E1000_PCS_LCTL_FORCE_FCTRL; + e1000_force_mac_fc_generic(hw); + } + E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); return (E1000_SUCCESS); } /* + * e1000_valid_led_default_82575 - Verify a valid default LED config + * @hw: pointer to the HW structure + * @data: pointer to the NVM (EEPROM) + * + * Read the EEPROM for the current default LED configuration. If the + * LED configuration is not valid, set to a valid LED configuration. + */ +static s32 +e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data) +{ + s32 ret_val; + + DEBUGFUNC("e1000_valid_led_default_82575"); + + ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); + if (ret_val) { + DEBUGOUT("NVM Read Error\n"); + goto out; + } + + if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { + switch (hw->phy.media_type) { + case e1000_media_type_fiber: + case e1000_media_type_internal_serdes: + *data = ID_LED_DEFAULT_82575_SERDES; + break; + case e1000_media_type_copper: + default: + *data = ID_LED_DEFAULT; + break; + } + } +out: + return (ret_val); +} + +/* * e1000_configure_pcs_link_82575 - Configure PCS link * @hw: pointer to the HW structure * @@ -1271,7 +1427,7 @@ e1000_configure_pcs_link_82575(struct e1000_hw *hw) */ reg |= E1000_PCS_LCTL_AN_RESTART | E1000_PCS_LCTL_AN_ENABLE; } else { - /* Set PCS regiseter for forced speed */ + /* Set PCS register for forced speed */ /* Turn off bits for full duplex, speed, and autoneg */ reg &= ~(E1000_PCS_LCTL_FSV_1000 | @@ -1312,22 +1468,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) { - ret_val = FALSE; - goto out; - } - - dev_spec = (struct e1000_dev_spec_82575 *)hw->dev_spec; - - ret_val = dev_spec->sgmii_active; + if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576) + return (false); -out: - return (ret_val); + return (dev_spec->sgmii_active); } /* @@ -1345,25 +1493,38 @@ e1000_reset_init_script_82575(struct e1000_hw *hw) if (hw->mac.type == e1000_82575) { DEBUGOUT("Running reset init script for 82575\n"); /* SerDes configuration via SERDESCTRL */ - (void) e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x00, 0x0C); - (void) e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x01, 0x78); - (void) e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x1B, 0x23); - (void) e1000_write_8bit_ctrl_reg(hw, E1000_SCTL, 0x23, 0x15); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, + 0x00, 0x0C); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, + 0x01, 0x78); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, + 0x1B, 0x23); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, + 0x23, 0x15); /* CCM configuration via CCMCTL register */ - (void) e1000_write_8bit_ctrl_reg(hw, E1000_CCMCTL, 0x14, 0x00); - (void) e1000_write_8bit_ctrl_reg(hw, E1000_CCMCTL, 0x10, 0x00); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, + 0x14, 0x00); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, + 0x10, 0x00); /* PCIe lanes configuration */ - (void) e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x00, 0xEC); - (void) e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x61, 0xDF); - (void) e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x34, 0x05); - (void) e1000_write_8bit_ctrl_reg(hw, E1000_GIOCTL, 0x2F, 0x81); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, + 0x00, 0xEC); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, + 0x61, 0xDF); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, + 0x34, 0x05); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, + 0x2F, 0x81); /* PCIe PLL Configuration */ - (void) e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x02, 0x47); - (void) e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x14, 0x00); - (void) e1000_write_8bit_ctrl_reg(hw, E1000_SCCTL, 0x10, 0x00); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, + 0x02, 0x47); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, + 0x14, 0x00); + (void) e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, + 0x10, 0x00); } return (E1000_SUCCESS); @@ -1395,8 +1556,14 @@ e1000_read_mac_addr_82575(struct e1000_hw *hw) static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw) { + struct e1000_phy_info *phy = &hw->phy; + struct e1000_mac_info *mac = &hw->mac; + + if (!(phy->ops.check_reset_block)) + return; + /* If the management interface is not enabled, then power down */ - if (!(e1000_check_mng_mode(hw) || e1000_check_reset_block(hw))) + if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) e1000_power_down_phy_copper(hw); } @@ -1464,3 +1631,80 @@ e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) if (hw->phy.media_type == e1000_media_type_internal_serdes) (void) E1000_READ_REG(hw, E1000_SCVPC); } + +/* + * e1000_rx_fifo_flush_82575 - Clean rx fifo after RX enable + * @hw: pointer to the HW structure + * + * After rx enable if managability is enabled then there is likely some + * bad data at the start of the fifo and possibly in the DMA fifo. This + * function clears the fifos and flushes any packets that came in as rx was + * being enabled. + */ +void +e1000_rx_fifo_flush_82575(struct e1000_hw *hw) +{ + u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; + int i, ms_wait; + + DEBUGFUNC("e1000_rx_fifo_workaround_82575"); + if (hw->mac.type != e1000_82575 || + !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) + return; + + /* Disable all RX queues */ + for (i = 0; i < 4; i++) { + rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); + E1000_WRITE_REG(hw, E1000_RXDCTL(i), + rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); + } + /* Poll all queues to verify they have shut down */ + for (ms_wait = 0; ms_wait < 10; ms_wait++) { + msec_delay(1); + rx_enabled = 0; + for (i = 0; i < 4; i++) + rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i)); + if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) + break; + } + + if (ms_wait == 10) + DEBUGOUT("Queue disable timed out after 10ms\n"); + + /* + * Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all + * incoming packets are rejected. Set enable and wait 2ms so that + * any packet that was coming in as RCTL.EN was set is flushed + */ + rfctl = E1000_READ_REG(hw, E1000_RFCTL); + E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); + + rlpml = E1000_READ_REG(hw, E1000_RLPML); + E1000_WRITE_REG(hw, E1000_RLPML, 0); + + rctl = E1000_READ_REG(hw, E1000_RCTL); + temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); + temp_rctl |= E1000_RCTL_LPE; + + E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl); + E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN); + E1000_WRITE_FLUSH(hw); + msec_delay(2); + + /* + * Enable RX queues that were previously enabled and restore our + * previous state + */ + for (i = 0; i < 4; i++) + E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]); + E1000_WRITE_REG(hw, E1000_RCTL, rctl); + E1000_WRITE_FLUSH(hw); + + E1000_WRITE_REG(hw, E1000_RLPML, rlpml); + E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); + + /* Flush receive errors generated by workaround */ + (void) E1000_READ_REG(hw, E1000_ROC); + (void) E1000_READ_REG(hw, E1000_RNBC); + (void) E1000_READ_REG(hw, E1000_MPC); +} diff --git a/usr/src/uts/common/io/igb/igb_82575.h b/usr/src/uts/common/io/igb/igb_82575.h index 9bad509dcc..06bb5d064e 100644 --- a/usr/src/uts/common/io/igb/igb_82575.h +++ b/usr/src/uts/common/io/igb/igb_82575.h @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,28 +22,36 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.33 v2007-12-10_dragonlake5 */ +/* IntelVersion: 1.57 v2008-10-7 */ #ifndef _IGB_82575_H #define _IGB_82575_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif +#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ + (ID_LED_DEF1_DEF2 << 8) | \ + (ID_LED_DEF1_DEF2 << 4) | \ + (ID_LED_OFF1_ON2)) + /* * Receive Address Register Count * Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. * These entries are also used for MAC-based filtering. */ -#define E1000_RAR_ENTRIES_82575 16 +/* + * For 82576, there are an additional set of RARs that begin at an offset + * separate from the first set of RARs. + */ +#define E1000_RAR_ENTRIES_82575 16 +#define E1000_RAR_ENTRIES_82576 24 #ifdef E1000_BIT_FIELDS struct e1000_adv_data_desc { @@ -129,10 +137,17 @@ struct e1000_adv_context_desc { #define E1000_TX_SEQNUM_WB_ENABLE 0x2 #define E1000_MRQC_ENABLE_RSS_4Q 0x00000002 +#define E1000_MRQC_ENABLE_VMDQ 0x00000003 #define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000 +#define E1000_VMRCTL_MIRROR_PORT_SHIFT 8 +#define E1000_VMRCTL_MIRROR_DSTPORT_MASK (7 << E1000_VMRCTL_MIRROR_PORT_SHIFT) +#define E1000_VMRCTL_POOL_MIRROR_ENABLE (1 << 0) +#define E1000_VMRCTL_UPLINK_MIRROR_ENABLE (1 << 1) +#define E1000_VMRCTL_DOWNLINK_MIRROR_ENABLE (1 << 2) + #define E1000_EICR_TX_QUEUE ( \ E1000_EICR_TX_QUEUE0 | \ E1000_EICR_TX_QUEUE1 | \ @@ -174,11 +189,14 @@ union e1000_adv_rx_desc { } read; struct { struct { - struct { - /* RSS type, Packet type */ - u16 pkt_info; - /* Split Header, header buffer length */ - u16 hdr_info; + union { + u32 data; + struct { + /* RSS type, Packet type */ + u16 pkt_info; + /* Split Header, header buffer length */ + u16 hdr_info; + } hs_rss; } lo_dword; union { u32 rss; /* RSS Hash */ @@ -202,7 +220,7 @@ union e1000_adv_rx_desc { #define E1000_RXDADV_HDRBUFLEN_SHIFT 5 #define E1000_RXDADV_SPLITHEADER_EN 0x00001000 #define E1000_RXDADV_SPH 0x8000 -#define E1000_RXDADV_HBO 0x00800000 +#define E1000_RXDADV_ERR_HBO 0x00800000 /* RSS Hash results */ #define E1000_RXDADV_RSSTYPE_NONE 0x00000000 @@ -227,6 +245,27 @@ union e1000_adv_rx_desc { #define E1000_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */ #define E1000_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */ +#define E1000_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */ +#define E1000_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */ +#define E1000_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */ +#define E1000_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */ +#define E1000_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */ +#define E1000_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */ + +/* LinkSec results */ +/* Security Processing bit Indication */ +#define E1000_RXDADV_LNKSEC_STATUS_SECP 0x00020000 +#define E1000_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000 +#define E1000_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000 +#define E1000_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000 +#define E1000_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000 + +#define E1000_RXDADV_IPSEC_STATUS_SECP 0x00020000 +#define E1000_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000 +#define E1000_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000 +#define E1000_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000 +#define E1000_RXDADV_IPSEC_ERROR_AUTHENTICATION_FAILED 0x18000000 + /* Transmit Descriptor - Advanced */ union e1000_adv_tx_desc { struct { @@ -246,16 +285,15 @@ union e1000_adv_tx_desc { #define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ #define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */ #define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ -#define E1000_ADVTXD_DCMD_RDMA 0x04000000 /* RDMA */ #define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */ #define E1000_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */ #define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */ #define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */ #define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ +#define E1000_ADVTXD_MAC_LINKSEC 0x00040000 /* Apply LinkSec on packet */ #define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */ #define E1000_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED present in WB */ #define E1000_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */ -#define E1000_ADVTXD_POPTS_EOM 0x00000400 /* Enable L bit in RDMA DDP hdr */ #define E1000_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */ #define E1000_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */ #define E1000_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */ @@ -320,6 +358,128 @@ 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 */ + +/* Additional interrupt register bit definitions */ +#define E1000_ICR_LSECPNS 0x00000020 /* PN threshold - server */ +#define E1000_IMS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */ +#define E1000_ICS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */ + +/* 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 + * here!! + * + * Current filters: + * EAPOL 802.1x (0x888e): Filter 0 + */ +#define E1000_ETQF_FILTER_EAPOL 0 + +#define E1000_NVM_APME_82575 0x0400 +#define MAX_NUM_VFS 8 + +#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */ +#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */ +#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */ +#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */ + +/* Easy defines for setting default pool, would normally be left a zero */ +#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7 +#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT) + +/* Other useful VMD_CTL register defines */ +#define E1000_VT_CTL_IGNORE_MAC (1 << 28) +#define E1000_VT_CTL_DISABLE_DEF_POOL (1 << 29) +#define E1000_VT_CTL_VM_REPL_EN (1 << 30) + +/* Per VM Offload register setup */ +#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */ +#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */ +#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */ +#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */ +#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ + +#define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */ +#define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */ +#define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ +#define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ +#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */ +#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */ +#define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */ + +#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */ +#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ +#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ +#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ +#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ + +#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ + +/* + * If it's a E1000_VF_* msg then it originates in the VF and is sent to the + * PF. The reverse is true if it is E1000_PF_*. + * Message ACK's are the value or'd with 0xF0000000 + */ +/* Messages below or'd with this are the ACK */ +#define E1000_VT_MSGTYPE_ACK 0xF0000000 +/* Messages below or'd with this are the NACK */ +#define E1000_VT_MSGTYPE_NACK 0xFF000000 +#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 + */ +/* PF notifies global reset imminent to VF */ +#define E1000_PF_MSGTYPE_RESET (1 + 0x100) +/* PF notifies VF of LSC... VF will see extra msg info for status */ +#define E1000_PF_MSGTYPE_LSC (2 + 0x100) + +#define E1000_PF_MSG_LSCDOWN (1 << E1000_VT_MSGINFO_SHIFT) +#define E1000_PF_MSG_LSCUP (2 << E1000_VT_MSGINFO_SHIFT) + +#define ALL_QUEUES 0xFFFF + +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, + u32 *msg, s16 size); +s32 e1000_send_mail_to_vf(struct e1000_hw *hw, u32 *msg, + u32 vf_number, s16 size); +s32 e1000_receive_mail_from_vf(struct e1000_hw *hw, u32 *msg, + u32 vf_number, s16 size); +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_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, u32*); + #ifdef __cplusplus } diff --git a/usr/src/uts/common/io/igb/igb_api.c b/usr/src/uts/common/io/igb/igb_api.c index 3b2fc40a1b..76d8f60e77 100644 --- a/usr/src/uts/common/io/igb/igb_api.c +++ b/usr/src/uts/common/io/igb/igb_api.c @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,18 +22,13 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.73 v2007-12-10_dragonlake5 */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* IntelVersion: 1.107 v2008-10-7 */ #include "igb_api.h" -#include "igb_mac.h" -#include "igb_nvm.h" -#include "igb_phy.h" /* * e1000_init_mac_params - Initialize MAC function pointers @@ -47,8 +42,8 @@ e1000_init_mac_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; - if (hw->func.init_mac_params) { - ret_val = hw->func.init_mac_params(hw); + if (hw->mac.ops.init_params) { + ret_val = hw->mac.ops.init_params(hw); if (ret_val) { DEBUGOUT("MAC Initialization Error\n"); goto out; @@ -74,8 +69,8 @@ e1000_init_nvm_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; - if (hw->func.init_nvm_params) { - ret_val = hw->func.init_nvm_params(hw); + if (hw->nvm.ops.init_params) { + ret_val = hw->nvm.ops.init_params(hw); if (ret_val) { DEBUGOUT("NVM Initialization Error\n"); goto out; @@ -101,8 +96,8 @@ e1000_init_phy_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; - if (hw->func.init_phy_params) { - ret_val = hw->func.init_phy_params(hw); + if (hw->phy.ops.init_params) { + ret_val = hw->phy.ops.init_params(hw); if (ret_val) { DEBUGOUT("PHY Initialization Error\n"); goto out; @@ -139,6 +134,12 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82575GB_QUAD_COPPER: mac->type = e1000_82575; break; + case E1000_DEV_ID_82576: + case E1000_DEV_ID_82576_FIBER: + case E1000_DEV_ID_82576_SERDES: + case E1000_DEV_ID_82576_QUAD_COPPER: + mac->type = e1000_82576; + break; default: /* Should never have loaded on this device */ ret_val = -E1000_ERR_MAC_INIT; @@ -151,10 +152,10 @@ e1000_set_mac_type(struct e1000_hw *hw) /* * e1000_setup_init_funcs - Initializes function pointers * @hw: pointer to the HW structure - * @init_device: TRUE will initialize the rest of the function pointers - * getting the device ready for use. FALSE will only set + * @init_device: true will initialize the rest of the function pointers + * getting the device ready for use. false will only set * MAC type and the function pointers for the other init - * functions. Passing FALSE will not generate any hardware + * functions. Passing false will not generate any hardware * reads or writes. * * This function must be called by a driver in order to use the rest @@ -179,18 +180,12 @@ e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) } /* - * Init some generic function pointers that are currently all pointing - * to generic implementations. We do this first allowing a driver - * module to override it afterwards. + * Init function pointers to generic implementations. We do this first + * allowing a driver module to override it afterward. */ - hw->func.config_collision_dist = e1000_config_collision_dist_generic; - hw->func.rar_set = e1000_rar_set_generic; - hw->func.validate_mdi_setting = e1000_validate_mdi_setting_generic; - hw->func.mng_host_if_write = e1000_mng_host_if_write_generic; - hw->func.mng_write_cmd_header = e1000_mng_write_cmd_header_generic; - hw->func.mng_enable_host_if = e1000_mng_enable_host_if_generic; - hw->func.wait_autoneg = e1000_wait_autoneg_generic; - hw->func.reload_nvm = e1000_reload_nvm_generic; + e1000_init_mac_ops_generic(hw); + e1000_init_phy_ops_generic(hw); + e1000_init_nvm_ops_generic(hw); /* * Set up the init function pointers. These are functions within the @@ -199,6 +194,7 @@ e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) */ switch (hw->mac.type) { case e1000_82575: + case e1000_82576: e1000_init_function_pointers_82575(hw); break; default: @@ -231,32 +227,18 @@ 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->func.remove_device) - hw->func.remove_device(hw); -} - -/* * e1000_get_bus_info - Obtain bus information for adapter * @hw: pointer to the HW structure * * This will obtain information about the HW bus for which the - * adaper is attached and stores it in the hw structure. This is a + * adapter is attached and stores it in the hw structure. This is a * function pointer entry point called by drivers. */ s32 e1000_get_bus_info(struct e1000_hw *hw) { - if (hw->func.get_bus_info) - return (hw->func.get_bus_info(hw)); + if (hw->mac.ops.get_bus_info) + return (hw->mac.ops.get_bus_info(hw)); return (E1000_SUCCESS); } @@ -271,8 +253,8 @@ e1000_get_bus_info(struct e1000_hw *hw) void e1000_clear_vfta(struct e1000_hw *hw) { - if (hw->func.clear_vfta) - hw->func.clear_vfta(hw); + if (hw->mac.ops.clear_vfta) + hw->mac.ops.clear_vfta(hw); } /* @@ -287,8 +269,8 @@ e1000_clear_vfta(struct e1000_hw *hw) void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) { - if (hw->func.write_vfta) - hw->func.write_vfta(hw, offset, value); + if (hw->mac.ops.write_vfta) + hw->mac.ops.write_vfta(hw, offset, value); } /* @@ -310,8 +292,8 @@ void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, u32 rar_used_count, u32 rar_count) { - if (hw->func.update_mc_addr_list) - hw->func.update_mc_addr_list(hw, + if (hw->mac.ops.update_mc_addr_list) + hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count, rar_used_count, @@ -343,8 +325,8 @@ e1000_force_mac_fc(struct e1000_hw *hw) s32 e1000_check_for_link(struct e1000_hw *hw) { - if (hw->func.check_for_link) - return (hw->func.check_for_link(hw)); + if (hw->mac.ops.check_for_link) + return (hw->mac.ops.check_for_link(hw)); return (-E1000_ERR_CONFIG); } @@ -359,10 +341,10 @@ e1000_check_for_link(struct e1000_hw *hw) bool e1000_check_mng_mode(struct e1000_hw *hw) { - if (hw->func.check_mng_mode) - return (hw->func.check_mng_mode(hw)); + if (hw->mac.ops.check_mng_mode) + return (hw->mac.ops.check_mng_mode(hw)); - return (FALSE); + return (false); } /* @@ -389,8 +371,8 @@ e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) s32 e1000_reset_hw(struct e1000_hw *hw) { - if (hw->func.reset_hw) - return (hw->func.reset_hw(hw)); + if (hw->mac.ops.reset_hw) + return (hw->mac.ops.reset_hw(hw)); return (-E1000_ERR_CONFIG); } @@ -405,8 +387,8 @@ e1000_reset_hw(struct e1000_hw *hw) s32 e1000_init_hw(struct e1000_hw *hw) { - if (hw->func.init_hw) - return (hw->func.init_hw(hw)); + if (hw->mac.ops.init_hw) + return (hw->mac.ops.init_hw(hw)); return (-E1000_ERR_CONFIG); } @@ -422,8 +404,8 @@ e1000_init_hw(struct e1000_hw *hw) s32 e1000_setup_link(struct e1000_hw *hw) { - if (hw->func.setup_link) - return (hw->func.setup_link(hw)); + if (hw->mac.ops.setup_link) + return (hw->mac.ops.setup_link(hw)); return (-E1000_ERR_CONFIG); } @@ -441,8 +423,8 @@ e1000_setup_link(struct e1000_hw *hw) s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) { - if (hw->func.get_link_up_info) - return (hw->func.get_link_up_info(hw, speed, duplex)); + if (hw->mac.ops.get_link_up_info) + return (hw->mac.ops.get_link_up_info(hw, speed, duplex)); return (-E1000_ERR_CONFIG); } @@ -458,8 +440,8 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) s32 e1000_setup_led(struct e1000_hw *hw) { - if (hw->func.setup_led) - return (hw->func.setup_led(hw)); + if (hw->mac.ops.setup_led) + return (hw->mac.ops.setup_led(hw)); return (E1000_SUCCESS); } @@ -474,8 +456,8 @@ e1000_setup_led(struct e1000_hw *hw) s32 e1000_cleanup_led(struct e1000_hw *hw) { - if (hw->func.cleanup_led) - return (hw->func.cleanup_led(hw)); + if (hw->mac.ops.cleanup_led) + return (hw->mac.ops.cleanup_led(hw)); return (E1000_SUCCESS); } @@ -491,8 +473,8 @@ e1000_cleanup_led(struct e1000_hw *hw) s32 e1000_blink_led(struct e1000_hw *hw) { - if (hw->func.blink_led) - return (hw->func.blink_led(hw)); + if (hw->mac.ops.blink_led) + return (hw->mac.ops.blink_led(hw)); return (E1000_SUCCESS); } @@ -507,8 +489,8 @@ e1000_blink_led(struct e1000_hw *hw) s32 e1000_led_on(struct e1000_hw *hw) { - if (hw->func.led_on) - return (hw->func.led_on(hw)); + if (hw->mac.ops.led_on) + return (hw->mac.ops.led_on(hw)); return (E1000_SUCCESS); } @@ -523,8 +505,8 @@ e1000_led_on(struct e1000_hw *hw) s32 e1000_led_off(struct e1000_hw *hw) { - if (hw->func.led_off) - return (hw->func.led_off(hw)); + if (hw->mac.ops.led_off) + return (hw->mac.ops.led_off(hw)); return (E1000_SUCCESS); } @@ -579,8 +561,8 @@ e1000_disable_pcie_master(struct e1000_hw *hw) void e1000_config_collision_dist(struct e1000_hw *hw) { - if (hw->func.config_collision_dist) - hw->func.config_collision_dist(hw); + if (hw->mac.ops.config_collision_dist) + hw->mac.ops.config_collision_dist(hw); } /* @@ -594,8 +576,8 @@ e1000_config_collision_dist(struct e1000_hw *hw) void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) { - if (hw->func.rar_set) - hw->func.rar_set(hw, addr, index); + if (hw->mac.ops.rar_set) + hw->mac.ops.rar_set(hw, addr, index); } /* @@ -607,8 +589,8 @@ e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) s32 e1000_validate_mdi_setting(struct e1000_hw *hw) { - if (hw->func.validate_mdi_setting) - return (hw->func.validate_mdi_setting(hw)); + if (hw->mac.ops.validate_mdi_setting) + return (hw->mac.ops.validate_mdi_setting(hw)); return (E1000_SUCCESS); } @@ -624,8 +606,8 @@ e1000_validate_mdi_setting(struct e1000_hw *hw) void e1000_mta_set(struct e1000_hw *hw, u32 hash_value) { - if (hw->func.mta_set) - hw->func.mta_set(hw, hash_value); + if (hw->mac.ops.mta_set) + hw->mac.ops.mta_set(hw, hash_value); } /* @@ -674,9 +656,9 @@ s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum) { - if (hw->func.mng_host_if_write) - return (hw->func.mng_host_if_write(hw, buffer, length, offset, - sum)); + if (hw->mac.ops.mng_host_if_write) + return (hw->mac.ops.mng_host_if_write(hw, buffer, length, + offset, sum)); return (E1000_NOT_IMPLEMENTED); } @@ -692,8 +674,8 @@ s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr) { - if (hw->func.mng_write_cmd_header) - return (hw->func.mng_write_cmd_header(hw, hdr)); + if (hw->mac.ops.mng_write_cmd_header) + return (hw->mac.ops.mng_write_cmd_header(hw, hdr)); return (E1000_NOT_IMPLEMENTED); } @@ -704,15 +686,15 @@ e1000_mng_write_cmd_header(struct e1000_hw *hw, * * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND * - * This function checks whether the HOST IF is enabled for command operaton + * This function checks whether the HOST IF is enabled for command operation * 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(struct e1000_hw *hw) { - if (hw->func.mng_enable_host_if) - return (hw->func.mng_enable_host_if(hw)); + if (hw->mac.ops.mng_enable_host_if) + return (hw->mac.ops.mng_enable_host_if(hw)); return (E1000_NOT_IMPLEMENTED); } @@ -727,8 +709,8 @@ e1000_mng_enable_host_if(struct e1000_hw *hw) s32 e1000_wait_autoneg(struct e1000_hw *hw) { - if (hw->func.wait_autoneg) - return (hw->func.wait_autoneg(hw)); + if (hw->mac.ops.wait_autoneg) + return (hw->mac.ops.wait_autoneg(hw)); return (E1000_SUCCESS); } @@ -743,8 +725,8 @@ e1000_wait_autoneg(struct e1000_hw *hw) s32 e1000_check_reset_block(struct e1000_hw *hw) { - if (hw->func.check_reset_block) - return (hw->func.check_reset_block(hw)); + if (hw->phy.ops.check_reset_block) + return (hw->phy.ops.check_reset_block(hw)); return (E1000_SUCCESS); } @@ -761,8 +743,8 @@ e1000_check_reset_block(struct e1000_hw *hw) s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data) { - if (hw->func.read_phy_reg) - return (hw->func.read_phy_reg(hw, offset, data)); + if (hw->phy.ops.read_reg) + return (hw->phy.ops.read_reg(hw, offset, data)); return (E1000_SUCCESS); } @@ -779,8 +761,38 @@ e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data) s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data) { - if (hw->func.write_phy_reg) - return (hw->func.write_phy_reg(hw, offset, data)); + if (hw->phy.ops.write_reg) + return (hw->phy.ops.write_reg(hw, offset, data)); + + return (E1000_SUCCESS); +} + +/* + * e1000_release_phy - Generic release PHY + * @hw: pointer to the HW structure + * + * Return if silicon family does not require a semaphore when accessing the + * PHY. + */ +void +e1000_release_phy(struct e1000_hw *hw) +{ + if (hw->phy.ops.release) + hw->phy.ops.release(hw); +} + +/* + * e1000_acquire_phy - Generic acquire PHY + * @hw: pointer to the HW structure + * + * Return success if silicon family does not require a semaphore when + * accessing the PHY. + */ +s32 +e1000_acquire_phy(struct e1000_hw *hw) +{ + if (hw->phy.ops.acquire) + return (hw->phy.ops.acquire(hw)); return (E1000_SUCCESS); } @@ -828,8 +840,8 @@ e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) s32 e1000_get_cable_length(struct e1000_hw *hw) { - if (hw->func.get_cable_length) - return (hw->func.get_cable_length(hw)); + if (hw->phy.ops.get_cable_length) + return (hw->phy.ops.get_cable_length(hw)); return (E1000_SUCCESS); } @@ -845,8 +857,8 @@ e1000_get_cable_length(struct e1000_hw *hw) s32 e1000_get_phy_info(struct e1000_hw *hw) { - if (hw->func.get_phy_info) - return (hw->func.get_phy_info(hw)); + if (hw->phy.ops.get_info) + return (hw->phy.ops.get_info(hw)); return (E1000_SUCCESS); } @@ -861,8 +873,8 @@ e1000_get_phy_info(struct e1000_hw *hw) s32 e1000_phy_hw_reset(struct e1000_hw *hw) { - if (hw->func.reset_phy) - return (hw->func.reset_phy(hw)); + if (hw->phy.ops.reset) + return (hw->phy.ops.reset(hw)); return (E1000_SUCCESS); } @@ -877,14 +889,14 @@ e1000_phy_hw_reset(struct e1000_hw *hw) s32 e1000_phy_commit(struct e1000_hw *hw) { - if (hw->func.commit_phy) - return (hw->func.commit_phy(hw)); + if (hw->phy.ops.commit) + return (hw->phy.ops.commit(hw)); return (E1000_SUCCESS); } /* - * e1000_set_d3_lplu_state - Sets low power link up state for D0 + * e1000_set_d0_lplu_state - Sets low power link up state for D0 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * @@ -900,8 +912,8 @@ e1000_phy_commit(struct e1000_hw *hw) s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) { - if (hw->func.set_d0_lplu_state) - return (hw->func.set_d0_lplu_state(hw, active)); + if (hw->phy.ops.set_d0_lplu_state) + return (hw->phy.ops.set_d0_lplu_state(hw, active)); return (E1000_SUCCESS); } @@ -923,8 +935,8 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active) { - if (hw->func.set_d3_lplu_state) - return (hw->func.set_d3_lplu_state(hw, active)); + if (hw->phy.ops.set_d3_lplu_state) + return (hw->phy.ops.set_d3_lplu_state(hw, active)); return (E1000_SUCCESS); } @@ -940,8 +952,8 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active) s32 e1000_read_mac_addr(struct e1000_hw *hw) { - if (hw->func.read_mac_addr) - return (hw->func.read_mac_addr(hw)); + if (hw->mac.ops.read_mac_addr) + return (hw->mac.ops.read_mac_addr(hw)); return (e1000_read_mac_addr_generic(hw)); } @@ -972,8 +984,8 @@ e1000_read_pba_num(struct e1000_hw *hw, u32 *pba_num) s32 e1000_validate_nvm_checksum(struct e1000_hw *hw) { - if (hw->func.validate_nvm) - return (hw->func.validate_nvm(hw)); + if (hw->nvm.ops.validate) + return (hw->nvm.ops.validate(hw)); return (-E1000_ERR_CONFIG); } @@ -988,8 +1000,8 @@ e1000_validate_nvm_checksum(struct e1000_hw *hw) s32 e1000_update_nvm_checksum(struct e1000_hw *hw) { - if (hw->func.update_nvm) - return (hw->func.update_nvm(hw)); + if (hw->nvm.ops.update) + return (hw->nvm.ops.update(hw)); return (-E1000_ERR_CONFIG); } @@ -1004,8 +1016,8 @@ e1000_update_nvm_checksum(struct e1000_hw *hw) void e1000_reload_nvm(struct e1000_hw *hw) { - if (hw->func.reload_nvm) - hw->func.reload_nvm(hw); + if (hw->nvm.ops.reload) + hw->nvm.ops.reload(hw); } /* @@ -1021,8 +1033,8 @@ e1000_reload_nvm(struct e1000_hw *hw) s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { - if (hw->func.read_nvm) - return (hw->func.read_nvm(hw, offset, words, data)); + if (hw->nvm.ops.read) + return (hw->nvm.ops.read(hw, offset, words, data)); return (-E1000_ERR_CONFIG); } @@ -1040,8 +1052,8 @@ e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { - if (hw->func.write_nvm) - return (hw->func.write_nvm(hw, offset, words, data)); + if (hw->nvm.ops.write) + return (hw->nvm.ops.write(hw, offset, words, data)); return (E1000_SUCCESS); } @@ -1072,8 +1084,8 @@ e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset, u8 data) void e1000_power_up_phy(struct e1000_hw *hw) { - if (hw->func.power_up_phy) - hw->func.power_up_phy(hw); + if (hw->phy.ops.power_up) + hw->phy.ops.power_up(hw); (void) e1000_setup_link(hw); } @@ -1088,6 +1100,19 @@ e1000_power_up_phy(struct e1000_hw *hw) void e1000_power_down_phy(struct e1000_hw *hw) { - if (hw->func.power_down_phy) - hw->func.power_down_phy(hw); + if (hw->phy.ops.power_down) + hw->phy.ops.power_down(hw); +} + +/* + * e1000_shutdown_fiber_serdes_link - Remove link during power down + * @hw: pointer to the HW structure + * + * Shutdown the optics and PCS on driver unload. + */ +void +e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw) +{ + if (hw->mac.ops.shutdown_serdes) + hw->mac.ops.shutdown_serdes(hw); } diff --git a/usr/src/uts/common/io/igb/igb_api.h b/usr/src/uts/common/io/igb/igb_api.h index 2052d08242..f6a28170bb 100644 --- a/usr/src/uts/common/io/igb/igb_api.h +++ b/usr/src/uts/common/io/igb/igb_api.h @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,17 +22,15 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.39 v2007-12-10_dragonlake5 */ +/* IntelVersion: 1.50 v2008-10-7 */ #ifndef _IGB_API_H #define _IGB_API_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -40,13 +38,15 @@ extern "C" { #include "igb_hw.h" extern void e1000_init_function_pointers_82575(struct e1000_hw *hw); +extern void e1000_rx_fifo_flush_82575(struct e1000_hw *hw); +extern void e1000_init_function_pointers_vf(struct e1000_hw *hw); +extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw); s32 e1000_set_mac_type(struct e1000_hw *hw); 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); @@ -79,6 +79,8 @@ s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset, u8 data); 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_phy_hw_reset(struct e1000_hw *hw); s32 e1000_phy_commit(struct e1000_hw *hw); void e1000_power_up_phy(struct e1000_hw *hw); @@ -96,7 +98,6 @@ s32 e1000_wait_autoneg(struct e1000_hw *hw); s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active); s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active); bool e1000_check_mng_mode(struct e1000_hw *hw); -bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw); s32 e1000_mng_enable_host_if(struct e1000_hw *hw); s32 e1000_mng_host_if_write(struct e1000_hw *hw, @@ -105,14 +106,6 @@ s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr); s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); -#ifndef FIFO_WORKAROUND -s32 e1000_fifo_workaround_82547(struct e1000_hw *hw, u16 length); -void e1000_update_tx_fifo_head_82547(struct e1000_hw *hw, u32 length); -void e1000_set_ttl_workaround_state_82541(struct e1000_hw *hw, bool state); -bool e1000_ttl_workaround_enabled_82541(struct e1000_hw *hw); -s32 e1000_igp_ttl_workaround_82547(struct e1000_hw *hw); -#endif - /* * TBI_ACCEPT macro definition: @@ -133,11 +126,11 @@ s32 e1000_igp_ttl_workaround_82547(struct e1000_hw *hw); * Typical use: * ... * if (TBI_ACCEPT) { - * accept_frame = TRUE; + * accept_frame = true; * e1000_tbi_adjust_stats(adapter, MacAddress); * frame_length--; * } else { - * accept_frame = FALSE; + * accept_frame = false; * } * ... */ diff --git a/usr/src/uts/common/io/igb/igb_buf.c b/usr/src/uts/common/io/igb/igb_buf.c index dd1aca689c..06d795e3f4 100644 --- a/usr/src/uts/common/io/igb/igb_buf.c +++ b/usr/src/uts/common/io/igb/igb_buf.c @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,12 +22,10 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "igb_sw.h" static int igb_alloc_tbd_ring(igb_tx_ring_t *); @@ -807,14 +805,9 @@ igb_alloc_rcb_lists(igb_rx_ring_t *rx_ring) rcb->free_rtn.free_arg = (char *)rcb; rcb->mp = desballoc((unsigned char *) - rx_buf->address - IPHDR_ALIGN_ROOM, - rx_buf->size + IPHDR_ALIGN_ROOM, + rx_buf->address, + rx_buf->size, 0, &rcb->free_rtn); - - if (rcb->mp != NULL) { - rcb->mp->b_rptr += IPHDR_ALIGN_ROOM; - rcb->mp->b_wptr += IPHDR_ALIGN_ROOM; - } } return (IGB_SUCCESS); diff --git a/usr/src/uts/common/io/igb/igb_debug.c b/usr/src/uts/common/io/igb/igb_debug.c index 021656cbaa..889ff34997 100644 --- a/usr/src/uts/common/io/igb/igb_debug.c +++ b/usr/src/uts/common/io/igb/igb_debug.c @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,12 +22,10 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "igb_sw.h" #include "igb_debug.h" @@ -259,13 +257,14 @@ pci_dump(void *arg) pci_config_get16(handle, offset + PCIE_LINKSTS)); /* MSI-X Memory Space */ - if (ddi_dev_regsize(igb->dip, 4, &mem_size) != DDI_SUCCESS) { + if (ddi_dev_regsize(igb->dip, IGB_ADAPTER_MSIXTAB, &mem_size) != + DDI_SUCCESS) { igb_log(igb, "ddi_dev_regsize() failed"); return; } - if ((ddi_regs_map_setup(igb->dip, 4, (caddr_t *)&base, 0, mem_size, - &igb_regs_acc_attr, &acc_hdl)) != DDI_SUCCESS) { + if ((ddi_regs_map_setup(igb->dip, IGB_ADAPTER_MSIXTAB, (caddr_t *)&base, + 0, mem_size, &igb_regs_acc_attr, &acc_hdl)) != DDI_SUCCESS) { igb_log(igb, "ddi_regs_map_setup() failed"); return; } diff --git a/usr/src/uts/common/io/igb/igb_defines.h b/usr/src/uts/common/io/igb/igb_defines.h index d1c43fa5d6..5e2942628c 100644 --- a/usr/src/uts/common/io/igb/igb_defines.h +++ b/usr/src/uts/common/io/igb/igb_defines.h @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,17 +22,15 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.54 v2007-12-10_dragonlake5 */ +/* IntelVersion: 1.79 v2008-10-7 */ #ifndef _IGB_DEFINES_H #define _IGB_DEFINES_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -61,25 +59,21 @@ extern "C" { #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 0x00008000 /* Ignore WakeOn TCO packets */ #define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ #define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ #define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ #define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ -/* Mask for all wakeup filters */ -#define E1000_WUFC_ALL_FILTERS_BM 0x0000F0FF -/* Offset to the Flexible Filters bits */ -#define E1000_WUFC_FLX_OFFSET_BM 12 -/* Mask for the 4 flexible filters */ -#define E1000_WUFC_FLX_FILTERS_BM 0x0000F000 +#define E1000_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */ +#define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ #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 */ +/* + * For 82576 to utilize Extended filter masks in addition to + * existing (filter) masks + */ +#define E1000_WUFC_EXT_FLX_FILTERS 0x00300000 /* Ext. FLX filter mask */ /* Wake Up Status */ #define E1000_WUS_LNKC E1000_WUFC_LNKC @@ -90,11 +84,6 @@ extern "C" { #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 E1000_WUFC_FLX0 #define E1000_WUS_FLX1 E1000_WUFC_FLX1 #define E1000_WUS_FLX2 E1000_WUFC_FLX2 @@ -106,6 +95,10 @@ extern "C" { /* Four Flexible Filters are supported */ #define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 +/* Two Extended Flexible Filters are supported (82576) */ +#define E1000_EXT_FLEXIBLE_FILTER_COUNT_MAX 2 +#define E1000_FHFT_LENGTH_OFFSET 0xFC /* Length byte in FHFT */ +#define E1000_FHFT_LENGTH_MASK 0x0FF /* Length in lower byte */ /* Each Flexible Filter is at most 128 (0x80) bytes in length */ #define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 @@ -121,11 +114,11 @@ extern "C" { #define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */ #define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */ /* Reserved (bits 4,5) in >= 82575 */ -#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */ -#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */ +#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Definable Pin 4 */ +#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Definable Pin 5 */ #define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA -#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */ -#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ +#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Definable Pin 6 */ +#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ /* SDP 4/5 (bits 8,9) are reserved in >= 82575 */ #define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ #define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ @@ -134,6 +127,8 @@ extern "C" { #define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ #define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ +/* Physical Func Reset Done Indication */ +#define E1000_CTRL_EXT_PFRSTD 0x00004000 #define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 @@ -150,7 +145,7 @@ extern "C" { #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 */ /* Interrupt acknowledge Auto-mask */ @@ -175,13 +170,18 @@ extern "C" { #define E1000_I2CCMD_ERROR 0x80000000 #define E1000_MAX_SGMII_PHY_REG_ADDR 255 #define E1000_I2CCMD_PHY_TIMEOUT 200 +#define E1000_IVAR_VALID 0x80 +#define E1000_GPIE_NSICR 0x00000001 +#define E1000_GPIE_MSIX_MODE 0x00000010 +#define E1000_GPIE_EIAME 0x40000000 +#define E1000_GPIE_PBA 0x80000000 -/* Receive Decriptor bit definitions */ +/* Receive Descriptor bit definitions */ #define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ #define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ #define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ #define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ -#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */ +#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ #define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ #define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ @@ -265,7 +265,7 @@ extern "C" { #define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable IP address filtering */ #define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 -#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable cksum filtering */ +#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */ #define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */ #define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ #define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ @@ -350,6 +350,7 @@ extern "C" { #define E1000_SWFW_EEP_SM 0x1 #define E1000_SWFW_PHY0_SM 0x2 #define E1000_SWFW_PHY1_SM 0x4 +#define E1000_SWFW_CSR_SM 0x8 /* FACTPS Definitions */ #define E1000_FACTPS_LFS 0x40000000 /* LAN Function Select */ @@ -392,8 +393,7 @@ extern "C" { #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 */ -/* Initiate an interrupt to manageability engine */ -#define E1000_CTRL_SW2FW_INT 0x02000000 +#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to ME */ #define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */ /* @@ -410,6 +410,7 @@ extern "C" { #define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA #define E1000_CONNSW_ENRGSRC 0x4 +#define E1000_PCS_CFG_PCS_EN 8 #define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FSV_10 0 #define E1000_PCS_LCTL_FSV_100 2 @@ -418,6 +419,7 @@ extern "C" { #define E1000_PCS_LCTL_FSD 0x10 #define E1000_PCS_LCTL_FORCE_LINK 0x20 #define E1000_PCS_LCTL_LOW_LINK_LATCH 0x40 +#define E1000_PCS_LCTL_FORCE_FCTRL 0x80 #define E1000_PCS_LCTL_AN_ENABLE 0x10000 #define E1000_PCS_LCTL_AN_RESTART 0x20000 #define E1000_PCS_LCTL_AN_TIMEOUT 0x40000 @@ -457,8 +459,7 @@ extern "C" { #define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ /* Change in Dock/Undock state. Clear on write '0'. */ #define E1000_STATUS_DOCK_CI 0x00000800 -/* Status of Master requests. */ -#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 +#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 */ @@ -476,7 +477,7 @@ extern "C" { #define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */ #define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */ -/* Constants used to intrepret the masked PCI-X bus speed. */ +/* Constants used to interpret the masked PCI-X bus speed. */ #define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ #define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ #define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */ @@ -617,6 +618,7 @@ extern "C" { #define E1000_RFCTL_EXTEN 0x00008000 #define E1000_RFCTL_IPV6_EX_DIS 0x00010000 #define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 +#define E1000_RFCTL_LEF 0x00040000 /* Collision related configuration parameters */ #define E1000_COLLISION_THRESHOLD 15 @@ -663,9 +665,10 @@ extern "C" { #define E1000_KABGTXD_BGSQLBIAS 0x00050000 /* PBA constants */ -#define E1000_PBA_8K 0x0008 /* 8KB */ -#define E1000_PBA_12K 0x000C /* 12KB */ -#define E1000_PBA_16K 0x0010 /* 16KB */ +#define E1000_PBA_6K 0x0006 /* 6KB */ +#define E1000_PBA_8K 0x0008 /* 8KB */ +#define E1000_PBA_12K 0x000C /* 12KB */ +#define E1000_PBA_16K 0x0010 /* 16KB */ #define E1000_PBA_20K 0x0014 #define E1000_PBA_22K 0x0016 #define E1000_PBA_24K 0x0018 @@ -700,6 +703,7 @@ extern "C" { #define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ #define E1000_ICR_RXO 0x00000040 /* rx overrun */ #define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ +#define E1000_ICR_VMMB 0x00000100 /* VM MB event */ #define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ #define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */ #define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ @@ -713,28 +717,19 @@ extern "C" { #define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ /* If this bit asserted, the driver should claim the interrupt */ #define E1000_ICR_INT_ASSERTED 0x80000000 -/* queue 0 Rx descriptor FIFO parity error */ -#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 -/* queue 0 Tx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 -/* host arb read buffer parity error */ -#define E1000_ICR_HOST_ARB_PAR 0x00400000 +#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 */ -/* queue 1 Rx descriptor FIFO parity error */ -#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 -/* queue 1 Tx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 +#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 */ /* FW changed the status of DISSW bit in the FWSM */ #define E1000_ICR_DSW 0x00000020 /* LAN connected device generates an interrupt */ #define E1000_ICR_PHYINT 0x00001000 -#define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */ -#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ -#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ -#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */ -#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */ -#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */ +#define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ +#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */ /* Extended Interrupt Cause Read */ #define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ @@ -783,6 +778,7 @@ extern "C" { #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ #define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ #define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */ #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ #define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ @@ -812,12 +808,8 @@ extern "C" { #define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 #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 */ -#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ -#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */ -#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */ /* Extended Interrupt Mask Set */ #define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ @@ -863,6 +855,7 @@ extern "C" { /* queue 1 Tx descriptor FIFO parity error */ #define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 #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 @@ -1075,7 +1068,7 @@ extern "C" { /* PHY 1000 MII Register/Bit Definitions */ /* PHY Registers defined by IEEE */ #define PHY_CONTROL 0x00 /* Control Register */ -#define PHY_STATUS 0x01 /* Status Regiser */ +#define PHY_STATUS 0x01 /* Status Register */ #define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ #define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ #define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ @@ -1120,8 +1113,7 @@ extern "C" { #define E1000_NVM_SWDPIN0 0x0001 /* SWDPIN 0 NVM Value */ #define E1000_NVM_LED_LOGIC 0x0020 /* Led Logic Word */ -/* Offset to data in NVM read/write registers */ -#define E1000_NVM_RW_REG_DATA 16 +#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,8 +1125,7 @@ extern "C" { #define NVM_COMPAT 0x0003 #define NVM_ID_LED_SETTINGS 0x0004 #define NVM_VERSION 0x0005 -/* For SERDES output amplitude adjustment. */ -#define NVM_SERDES_AMPLITUDE 0x0006 +#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 @@ -1181,7 +1172,7 @@ extern "C" { #define NVM_WRITE_OPCODE_MICROWIRE 0x5 /* NVM write opcode */ #define NVM_ERASE_OPCODE_MICROWIRE 0x7 /* NVM erase opcode */ #define NVM_EWEN_OPCODE_MICROWIRE 0x13 /* NVM erase/write enable */ -#define NVM_EWDS_OPCODE_MICROWIRE 0x10 /* NVM erast/write disable */ +#define NVM_EWDS_OPCODE_MICROWIRE 0x10 /* NVM erase/write disable */ /* NVM Commands - SPI */ #define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ @@ -1263,8 +1254,7 @@ extern "C" { #define IFE_E_PHY_ID 0x02A80330 #define IFE_PLUS_E_PHY_ID 0x02A80320 #define IFE_C_E_PHY_ID 0x02A80310 -#define BME1000_E_PHY_ID 0x01410CB0 -#define BME1000_E_PHY_ID_R2 0x01410CB1 +#define IGP04E1000_E_PHY_ID 0x02A80391 #define M88_VENDOR 0x0141 /* M88E1000 Specific Registers */ @@ -1371,9 +1361,6 @@ extern "C" { #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00 -/* BME1000 PHY Specific Control Register */ -#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ - /* * Bits... * 15-5: page @@ -1465,9 +1452,29 @@ extern "C" { #define E1000_GEN_CTL_ADDRESS_SHIFT 8 #define E1000_GEN_POLL_TIMEOUT 640 -#ifndef UNREFERENCED_PARAMETER -#define UNREFERENCED_PARAMETER(_p) -#endif +/* LinkSec register fields */ +#define E1000_LSECTXCAP_SUM_MASK 0x00FF0000 +#define E1000_LSECTXCAP_SUM_SHIFT 16 +#define E1000_LSECRXCAP_SUM_MASK 0x00FF0000 +#define E1000_LSECRXCAP_SUM_SHIFT 16 + +#define E1000_LSECTXCTRL_EN_MASK 0x00000003 +#define E1000_LSECTXCTRL_DISABLE 0x0 +#define E1000_LSECTXCTRL_AUTH 0x1 +#define E1000_LSECTXCTRL_AUTH_ENCRYPT 0x2 +#define E1000_LSECTXCTRL_AISCI 0x00000020 +#define E1000_LSECTXCTRL_PNTHRSH_MASK 0xFFFFFF00 +#define E1000_LSECTXCTRL_RSV_MASK 0x000000D8 + +#define E1000_LSECRXCTRL_EN_MASK 0x0000000C +#define E1000_LSECRXCTRL_EN_SHIFT 2 +#define E1000_LSECRXCTRL_DISABLE 0x0 +#define E1000_LSECRXCTRL_CHECK 0x1 +#define E1000_LSECRXCTRL_STRICT 0x2 +#define E1000_LSECRXCTRL_DROP 0x3 +#define E1000_LSECRXCTRL_PLSH 0x00000040 +#define E1000_LSECRXCTRL_RP 0x00000080 +#define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33 #ifdef __cplusplus } diff --git a/usr/src/uts/common/io/igb/igb_hw.h b/usr/src/uts/common/io/igb/igb_hw.h index 04c410d7d1..3b6dc8dd2d 100644 --- a/usr/src/uts/common/io/igb/igb_hw.h +++ b/usr/src/uts/common/io/igb/igb_hw.h @@ -1,17 +1,19 @@ /* * CDDL HEADER START * + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. + * You can obtain a copy of the license at: + * http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * When using or redistributing this file, you may do so under the + * License only. No other modification of this header is permitted. + * * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] @@ -20,15 +22,11 @@ */ /* - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.357 v2007-12-10_dragonlake5 */ +/* IntelVersion: 1.398 v2008-10-7 */ #ifndef _IGB_HW_H #define _IGB_HW_H @@ -43,6 +41,10 @@ extern "C" { struct e1000_hw; +#define E1000_DEV_ID_82576 0x10C9 +#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_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 @@ -56,38 +58,39 @@ struct e1000_hw; #define E1000_FUNC_0 0 #define E1000_FUNC_1 1 -typedef enum { +enum e1000_mac_type { e1000_undefined = 0, e1000_82575, + e1000_82576, e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ -} e1000_mac_type; +}; -typedef enum { +enum e1000_media_type { e1000_media_type_unknown = 0, e1000_media_type_copper = 1, e1000_media_type_fiber = 2, e1000_media_type_internal_serdes = 3, e1000_num_media_types -} e1000_media_type; +}; -typedef enum { +enum e1000_nvm_type { e1000_nvm_unknown = 0, e1000_nvm_none, e1000_nvm_eeprom_spi, e1000_nvm_eeprom_microwire, e1000_nvm_flash_hw, e1000_nvm_flash_sw -} e1000_nvm_type; +}; -typedef enum { +enum e1000_nvm_override { e1000_nvm_override_none = 0, e1000_nvm_override_spi_small, e1000_nvm_override_spi_large, e1000_nvm_override_microwire_small, e1000_nvm_override_microwire_large -} e1000_nvm_override; +}; -typedef enum { +enum e1000_phy_type { e1000_phy_unknown = 0, e1000_phy_none, e1000_phy_m88, @@ -96,18 +99,18 @@ typedef enum { e1000_phy_gg82563, e1000_phy_igp_3, e1000_phy_ife, - e1000_phy_bm -} e1000_phy_type; + e1000_phy_vf +}; -typedef enum { +enum e1000_bus_type { e1000_bus_type_unknown = 0, e1000_bus_type_pci, e1000_bus_type_pcix, e1000_bus_type_pci_express, e1000_bus_type_reserved -} e1000_bus_type; +}; -typedef enum { +enum e1000_bus_speed { e1000_bus_speed_unknown = 0, e1000_bus_speed_33, e1000_bus_speed_66, @@ -117,9 +120,9 @@ typedef enum { e1000_bus_speed_2500, e1000_bus_speed_5000, e1000_bus_speed_reserved -} e1000_bus_speed; +}; -typedef enum { +enum e1000_bus_width { e1000_bus_width_unknown = 0, e1000_bus_width_pcie_x1, e1000_bus_width_pcie_x2, @@ -128,59 +131,72 @@ typedef enum { e1000_bus_width_32, e1000_bus_width_64, e1000_bus_width_reserved -} e1000_bus_width; +}; -typedef enum { +enum e1000_1000t_rx_status { e1000_1000t_rx_status_not_ok = 0, e1000_1000t_rx_status_ok, e1000_1000t_rx_status_undefined = 0xFF -} e1000_1000t_rx_status; +}; -typedef enum { +enum e1000_rev_polarity { e1000_rev_polarity_normal = 0, e1000_rev_polarity_reversed, e1000_rev_polarity_undefined = 0xFF -} e1000_rev_polarity; +}; -typedef enum { +enum e1000_fc_mode { e1000_fc_none = 0, e1000_fc_rx_pause, e1000_fc_tx_pause, e1000_fc_full, e1000_fc_default = 0xFF -} e1000_fc_type; +}; + +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 */ + __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 */ - u16 special; + __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 */ }; @@ -190,49 +206,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 */ + __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; + __le16 special; } fields; } upper; }; @@ -240,49 +256,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 */ + __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 */ + __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 */ + __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; + __le16 special; } fields; } upper; }; @@ -364,6 +380,7 @@ struct e1000_hw_stats { u64 lenerrs; u64 scvpc; u64 hrmpc; + u64 doosync; }; struct e1000_phy_stats { @@ -416,9 +433,9 @@ struct e1000_host_mng_command_info { #include "igb_nvm.h" #include "igb_manage.h" -struct e1000_functions { +struct e1000_mac_operations { /* Function pointers for the MAC. */ - s32 (*init_mac_params)(struct e1000_hw *); + s32 (*init_params)(struct e1000_hw *); s32 (*blink_led)(struct e1000_hw *); s32 (*check_for_link)(struct e1000_hw *); bool (*check_mng_mode)(struct e1000_hw *hw); @@ -430,9 +447,9 @@ struct e1000_functions { 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 *); s32 (*reset_hw)(struct e1000_hw *); s32 (*init_hw)(struct e1000_hw *); + void (*shutdown_serdes)(struct e1000_hw *); s32 (*setup_link)(struct e1000_hw *); s32 (*setup_physical_interface)(struct e1000_hw *); s32 (*setup_led)(struct e1000_hw *); @@ -447,43 +464,46 @@ struct e1000_functions { struct e1000_host_mng_command_header *); s32 (*mng_enable_host_if)(struct e1000_hw *); s32 (*wait_autoneg)(struct e1000_hw *); +}; - /* Function pointers for the PHY. */ - s32 (*init_phy_params)(struct e1000_hw *); - s32 (*acquire_phy)(struct e1000_hw *); +struct e1000_phy_operations { + s32 (*init_params)(struct e1000_hw *); + s32 (*acquire)(struct e1000_hw *); s32 (*check_polarity)(struct e1000_hw *); s32 (*check_reset_block)(struct e1000_hw *); - s32 (*commit_phy)(struct e1000_hw *); + s32 (*commit)(struct e1000_hw *); s32 (*force_speed_duplex)(struct e1000_hw *); s32 (*get_cfg_done)(struct e1000_hw *hw); s32 (*get_cable_length)(struct e1000_hw *); - s32 (*get_phy_info)(struct e1000_hw *); - s32 (*read_phy_reg)(struct e1000_hw *, u32, u16 *); - void (*release_phy)(struct e1000_hw *); - s32 (*reset_phy)(struct e1000_hw *); + s32 (*get_info)(struct e1000_hw *); + s32 (*read_reg)(struct e1000_hw *, u32, u16 *); + void (*release)(struct e1000_hw *); + s32 (*reset)(struct e1000_hw *); s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); - s32 (*write_phy_reg)(struct e1000_hw *, u32, u16); - void (*power_up_phy)(struct e1000_hw *); - void (*power_down_phy)(struct e1000_hw *); - - /* Function pointers for the NVM. */ - s32 (*init_nvm_params)(struct e1000_hw *); - s32 (*acquire_nvm)(struct e1000_hw *); - s32 (*read_nvm)(struct e1000_hw *, u16, u16, u16 *); - void (*release_nvm)(struct e1000_hw *); - void (*reload_nvm)(struct e1000_hw *); - s32 (*update_nvm)(struct e1000_hw *); + s32 (*write_reg)(struct e1000_hw *, u32, u16); + void (*power_up)(struct e1000_hw *); + void (*power_down)(struct e1000_hw *); +}; + +struct e1000_nvm_operations { + s32 (*init_params)(struct e1000_hw *); + s32 (*acquire)(struct e1000_hw *); + s32 (*read)(struct e1000_hw *, u16, u16, u16 *); + void (*release)(struct e1000_hw *); + void (*reload)(struct e1000_hw *); + s32 (*update)(struct e1000_hw *); s32 (*valid_led_default)(struct e1000_hw *, u16 *); - s32 (*validate_nvm)(struct e1000_hw *); - s32 (*write_nvm)(struct e1000_hw *, u16, u16, u16 *); + s32 (*validate)(struct e1000_hw *); + s32 (*write)(struct e1000_hw *, u16, u16, u16 *); }; struct e1000_mac_info { + struct e1000_mac_operations ops; u8 addr[6]; u8 perm_addr[6]; - e1000_mac_type type; + enum e1000_mac_type type; u32 collision_delta; u32 ledctl_default; @@ -508,32 +528,29 @@ 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; bool tx_pkt_filtering; }; struct e1000_phy_info { - e1000_phy_type type; + struct e1000_phy_operations ops; + enum e1000_phy_type type; - e1000_1000t_rx_status local_rx; - e1000_1000t_rx_status remote_rx; - e1000_ms_type ms_type; - e1000_ms_type original_ms_type; - e1000_rev_polarity cable_polarity; - e1000_smart_speed smart_speed; + enum e1000_1000t_rx_status local_rx; + enum e1000_1000t_rx_status remote_rx; + enum e1000_ms_type ms_type; + enum e1000_ms_type original_ms_type; + enum e1000_rev_polarity cable_polarity; + enum e1000_smart_speed smart_speed; u32 addr; u32 id; u32 reset_delay_us; /* in usec */ u32 revision; - e1000_media_type media_type; + enum e1000_media_type media_type; u16 autoneg_advertised; u16 autoneg_mask; @@ -552,8 +569,9 @@ struct e1000_phy_info { }; struct e1000_nvm_info { - e1000_nvm_type type; - e1000_nvm_override override; + struct e1000_nvm_operations ops; + enum e1000_nvm_type type; + enum e1000_nvm_override override; u32 flash_bank_size; u32 flash_base_addr; @@ -566,11 +584,9 @@ struct e1000_nvm_info { }; struct e1000_bus_info { - e1000_bus_type type; - e1000_bus_speed speed; - e1000_bus_width width; - - u32 snoop; + enum e1000_bus_type type; + enum e1000_bus_speed speed; + enum e1000_bus_width width; u16 func; u16 pci_cmd_word; @@ -582,19 +598,25 @@ struct e1000_fc_info { u16 pause_time; /* Flow control pause timer */ bool send_xon; /* Flow control send XON */ bool strict_ieee; /* Strict IEEE mode */ - e1000_fc_type type; /* Type of flow control */ - e1000_fc_type original_type; + 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_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; unsigned long io_base; - struct e1000_functions func; struct e1000_mac_info mac; struct e1000_fc_info fc; struct e1000_phy_info phy; @@ -602,7 +624,10 @@ 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_82575 _82575; + struct e1000_dev_spec_vf vf; + } dev_spec; u16 device_id; u16 subsystem_vendor_id; @@ -612,17 +637,12 @@ struct e1000_hw { u8 revision_id; }; +#include "igb_82575.h" + /* 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); -void e1000_rar_clear(struct e1000_hw *hw, uint32_t); -void e1000_rar_set_vmdq(struct e1000_hw *hw, const uint8_t *, uint32_t, - uint32_t, uint8_t); #ifdef __cplusplus } diff --git a/usr/src/uts/common/io/igb/igb_mac.c b/usr/src/uts/common/io/igb/igb_mac.c index 7705de0672..1854c657fc 100644 --- a/usr/src/uts/common/io/igb/igb_mac.c +++ b/usr/src/uts/common/io/igb/igb_mac.c @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,31 +22,154 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.62 v2007-12-10_dragonlake5 */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* IntelVersion: 1.92 v2008-10-7 */ #include "igb_api.h" -#include "igb_mac.h" + +static s32 e1000_set_default_fc_generic(struct e1000_hw *hw); +static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw); +static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw); +static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); /* - * e1000_remove_device_generic - Free device specific structure + * e1000_init_mac_ops_generic - Initialize MAC function pointers * @hw: pointer to the HW structure * - * If a device specific structure was allocated, this function will - * free it. + * Setups up the function pointers to no-op functions + */ +void +e1000_init_mac_ops_generic(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + DEBUGFUNC("e1000_init_mac_ops_generic"); + + /* General Setup */ + mac->ops.init_params = e1000_null_ops_generic; + mac->ops.init_hw = e1000_null_ops_generic; + 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.read_mac_addr = e1000_read_mac_addr_generic; + mac->ops.config_collision_dist = e1000_config_collision_dist_generic; + mac->ops.clear_hw_cntrs = e1000_null_mac_generic; + /* LED */ + mac->ops.cleanup_led = e1000_null_ops_generic; + mac->ops.setup_led = e1000_null_ops_generic; + mac->ops.blink_led = e1000_null_ops_generic; + mac->ops.led_on = e1000_null_ops_generic; + mac->ops.led_off = e1000_null_ops_generic; + /* LINK */ + mac->ops.setup_link = e1000_null_ops_generic; + mac->ops.get_link_up_info = e1000_null_link_info; + mac->ops.check_for_link = e1000_null_ops_generic; + mac->ops.wait_autoneg = e1000_wait_autoneg_generic; + /* Management */ + mac->ops.check_mng_mode = e1000_null_mng_mode; + mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic; + mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic; + mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic; + /* VLAN, MC, etc. */ + mac->ops.update_mc_addr_list = e1000_null_update_mc; + mac->ops.clear_vfta = e1000_null_mac_generic; + mac->ops.write_vfta = e1000_null_write_vfta; + mac->ops.mta_set = e1000_null_mta_set; + mac->ops.rar_set = e1000_rar_set_generic; + mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic; +} + +/* + * e1000_null_ops_generic - No-op function, returns 0 + * @hw: pointer to the HW structure + */ +s32 +e1000_null_ops_generic(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_null_ops_generic"); + UNREFERENCED_1PARAMETER(hw); + return (E1000_SUCCESS); +} + +/* + * e1000_null_mac_generic - No-op function, return void + * @hw: pointer to the HW structure + */ +void +e1000_null_mac_generic(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_null_mac_generic"); + UNREFERENCED_1PARAMETER(hw); +} + +/* + * e1000_null_link_info - No-op function, return 0 + * @hw: pointer to the HW structure + */ +s32 +e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d) +{ + DEBUGFUNC("e1000_null_link_info"); + UNREFERENCED_3PARAMETER(hw, s, d); + return (E1000_SUCCESS); +} + +/* + * e1000_null_mng_mode - No-op function, return false + * @hw: pointer to the HW structure + */ +bool +e1000_null_mng_mode(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_null_mng_mode"); + UNREFERENCED_1PARAMETER(hw); + return (false); +} + +/* + * e1000_null_update_mc - No-op function, return void + * @hw: pointer to the HW structure + */ +void +e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a, u32 b, u32 c) +{ + DEBUGFUNC("e1000_null_update_mc"); + UNREFERENCED_5PARAMETER(hw, h, a, b, c); +} + +/* + * e1000_null_write_vfta - No-op function, return void + * @hw: pointer to the HW structure */ void -e1000_remove_device_generic(struct e1000_hw *hw) +e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b) { - DEBUGFUNC("e1000_remove_device_generic"); + DEBUGFUNC("e1000_null_write_vfta"); + UNREFERENCED_3PARAMETER(hw, a, b); +} - /* Freeing the dev_spec member of e1000_hw structure */ - e1000_free_dev_spec_struct(hw); +/* + * e1000_null_set_mta - No-op function, return void + * @hw: pointer to the HW structure + */ +void +e1000_null_mta_set(struct e1000_hw *hw, u32 a) +{ + DEBUGFUNC("e1000_null_mta_set"); + UNREFERENCED_2PARAMETER(hw, a); +} + +/* + * e1000_null_rar_set - No-op function, return void + * @hw: pointer to the HW structure + */ +void +e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a) +{ + DEBUGFUNC("e1000_null_rar_set"); + UNREFERENCED_3PARAMETER(hw, h, a); } /* @@ -69,12 +192,14 @@ e1000_get_bus_info_pci_generic(struct e1000_hw *hw) /* PCI or PCI-X? */ bus->type = (status & E1000_STATUS_PCIX_MODE) - ? e1000_bus_type_pcix : e1000_bus_type_pci; + ? e1000_bus_type_pcix + : e1000_bus_type_pci; /* Bus speed */ if (bus->type == e1000_bus_type_pci) { bus->speed = (status & E1000_STATUS_PCI66) - ? e1000_bus_speed_66 : e1000_bus_speed_33; + ? e1000_bus_speed_66 + : e1000_bus_speed_33; } else { switch (status & E1000_STATUS_PCIX_SPEED) { case E1000_STATUS_PCIX_SPEED_66: @@ -94,7 +219,8 @@ e1000_get_bus_info_pci_generic(struct e1000_hw *hw) /* Bus width */ bus->width = (status & E1000_STATUS_BUS64) - ? e1000_bus_width_64 : e1000_bus_width_32; + ? e1000_bus_width_64 + : e1000_bus_width_32; /* Which PCI(-X) function? */ e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type); @@ -133,7 +259,7 @@ e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) if (ret_val) bus->width = e1000_bus_width_unknown; else - bus->width = (e1000_bus_width)((pcie_link_status & + bus->width = (enum e1000_bus_width)((pcie_link_status & PCIE_LINK_WIDTH_MASK) >> PCIE_LINK_WIDTH_SHIFT); e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type); @@ -205,7 +331,7 @@ e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count) /* Setup the receive address */ DEBUGOUT("Programming MAC Address into RAR[0]\n"); - e1000_rar_set_generic(hw, hw->mac.addr, 0); + hw->mac.ops.rar_set(hw, hw->mac.addr, 0); /* Zero out the other (rar_entry_count - 1) receive addresses */ DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1); @@ -238,7 +364,7 @@ e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_check_alt_mac_addr_generic"); - ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, + ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1, &nvm_alt_mac_addr_offset); if (ret_val) { DEBUGOUT("NVM Read Error\n"); @@ -255,7 +381,7 @@ e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) for (i = 0; i < ETH_ADDR_LEN; i += 2) { offset = nvm_alt_mac_addr_offset + (i >> 1); - ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; @@ -274,7 +400,7 @@ e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) for (i = 0; i < ETH_ADDR_LEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i] = alt_mac_addr[i]; - e1000_rar_set(hw, hw->mac.perm_addr, 0); + hw->mac.ops.rar_set(hw, hw->mac.perm_addr, 0); out: return (ret_val); @@ -307,13 +433,11 @@ 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_ARRAY(hw, E1000_RA, (index << 1), rar_low); - E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high); + E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); + E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); } /* @@ -383,7 +507,7 @@ e1000_update_mc_addr_list_generic(struct e1000_hw *hw, */ for (i = rar_used_count; i < rar_count; i++) { if (mc_addr_count) { - e1000_rar_set(hw, mc_addr_list, i); + hw->mac.ops.rar_set(hw, mc_addr_list, i); mc_addr_count--; mc_addr_list += ETH_ADDR_LEN; } else { @@ -403,9 +527,9 @@ e1000_update_mc_addr_list_generic(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(hw, mc_addr_list); + hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list); DEBUGOUT1("Hash value = 0x%03X\n", hash_value); - e1000_mta_set(hw, hash_value); + hw->mac.ops.mta_set(hw, hash_value); mc_addr_list += ETH_ADDR_LEN; } } @@ -490,8 +614,8 @@ e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) * * In certain situations, a system BIOS may report that the PCIx maximum * memory read byte count (MMRBC) value is higher than than the actual - * value. We check the PCIx command regsiter with the current PCIx status - * regsiter. + * value. We check the PCIx command register with the current PCIx status + * register. */ void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw) @@ -612,7 +736,7 @@ e1000_check_for_copper_link_generic(struct e1000_hw *hw) if (!link) goto out; /* No link detected */ - mac->get_link_status = FALSE; + mac->get_link_status = false; /* * Check if there was DownShift, must be checked @@ -643,9 +767,8 @@ 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); @@ -715,7 +838,7 @@ e1000_check_for_fiber_link_generic(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_has_link = TRUE; + mac->serdes_has_link = true; } out: @@ -784,7 +907,7 @@ e1000_check_for_serdes_link_generic(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_has_link = TRUE; + mac->serdes_has_link = true; } else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) { /* * If we force link for non-auto-negotiation switch, check @@ -793,21 +916,42 @@ e1000_check_for_serdes_link_generic(struct e1000_hw *hw) */ /* SYNCH bit and IV bit are sticky. */ usec_delay(10); - if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, E1000_RXCW)) { + rxcw = E1000_READ_REG(hw, E1000_RXCW); + if (rxcw & E1000_RXCW_SYNCH) { if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = TRUE; - DEBUGOUT("SERDES: Link is up.\n"); + mac->serdes_has_link = true; + DEBUGOUT("SERDES: Link up - forced.\n"); } } else { - mac->serdes_has_link = FALSE; - DEBUGOUT("SERDES: Link is down.\n"); + mac->serdes_has_link = false; + DEBUGOUT("SERDES: Link down - force failed.\n"); } } if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) { status = E1000_READ_REG(hw, E1000_STATUS); - mac->serdes_has_link = (status & E1000_STATUS_LU) - ? TRUE : FALSE; + if (status & E1000_STATUS_LU) { + /* SYNCH bit and IV bit are sticky, so reread rxcw. */ + usec_delay(10); + rxcw = E1000_READ_REG(hw, E1000_RXCW); + if (rxcw & E1000_RXCW_SYNCH) { + if (!(rxcw & E1000_RXCW_IV)) { + mac->serdes_has_link = true; + DEBUGOUT("SERDES: Link up - autoneg " + "completed sucessfully.\n"); + } else { + mac->serdes_has_link = false; + DEBUGOUT("SERDES: Link down - invalid" + "codewords detected in autoneg.\n"); + } + } else { + mac->serdes_has_link = false; + DEBUGOUT("SERDES: Link down - no sync.\n"); + } + } else { + mac->serdes_has_link = false; + DEBUGOUT("SERDES: Link down - autoneg failed\n"); + } } out: @@ -827,7 +971,6 @@ out: s32 e1000_setup_link_generic(struct e1000_hw *hw) { - struct e1000_functions *func = &hw->func; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_setup_link_generic"); @@ -836,30 +979,31 @@ e1000_setup_link_generic(struct e1000_hw *hw) * In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ - if (e1000_check_reset_block(hw)) - goto out; + if (hw->phy.ops.check_reset_block) + if (hw->phy.ops.check_reset_block(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 = func->setup_physical_interface(hw); + ret_val = hw->mac.ops.setup_physical_interface(hw); if (ret_val) goto out; @@ -922,7 +1066,7 @@ e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) msec_delay(1); /* - * For these adapters, the SW defineable pin 1 is set when the optics + * For these adapters, the SW definable pin 1 is set when the optics * detect a signal. If we have a signal, then poll for a "Link-Up" * indication. */ @@ -999,7 +1143,7 @@ e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) * link up if we detect a signal. This will allow us to * communicate with non-autonegotiating link partners. */ - ret_val = e1000_check_for_link(hw); + ret_val = hw->mac.ops.check_for_link(hw); if (ret_val) { DEBUGOUT("Error while checking for link\n"); goto out; @@ -1047,7 +1191,7 @@ 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); @@ -1096,7 +1240,7 @@ out: * * Sets the flow control high/low threshold (watermark) registers. If * flow control XON frame transmission is enabled, then set XON frame - * tansmission as well. + * transmission as well. */ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) @@ -1113,7 +1257,7 @@ 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 @@ -1155,7 +1299,7 @@ e1000_set_default_fc_generic(struct e1000_hw *hw) * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ - ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); @@ -1163,12 +1307,12 @@ 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); @@ -1201,7 +1345,7 @@ 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 @@ -1212,9 +1356,9 @@ 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; @@ -1292,10 +1436,10 @@ 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 = e1000_read_phy_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 = e1000_read_phy_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; @@ -1312,11 +1456,11 @@ 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 = e1000_read_phy_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 = e1000_read_phy_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; @@ -1364,11 +1508,11 @@ 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"); } @@ -1385,7 +1529,7 @@ 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"); } /* @@ -1400,14 +1544,14 @@ 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"); } @@ -1416,14 +1560,14 @@ e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) * negotiated to HALF DUPLEX, flow control should not be * enabled per IEEE 802.3 spec. */ - ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex); + ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); if (ret_val) { DEBUGOUT("Error getting link speed and duplex\n"); goto out; } 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 @@ -1441,7 +1585,7 @@ out: } /* - * e1000_get_speed_and_duplex_copper_generic - Retreive current speed/duplex + * e1000_get_speed_and_duplex_copper_generic - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex @@ -1481,7 +1625,7 @@ e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, } /* - * e1000_get_speed_and_duplex_fiber_generic - Retreive current speed/duplex + * e1000_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex @@ -1494,7 +1638,7 @@ e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, u16 *speed, u16 *duplex) { DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic"); - UNREFERENCED_PARAMETER(hw); + UNREFERENCED_1PARAMETER(hw); *speed = SPEED_1000; *duplex = FULL_DUPLEX; @@ -1624,7 +1768,7 @@ e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data) DEBUGFUNC("e1000_valid_led_default_generic"); - ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); + ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; @@ -1655,7 +1799,7 @@ e1000_id_led_init_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_id_led_init_generic"); - ret_val = hw->func.valid_led_default(hw, &data); + ret_val = hw->nvm.ops.valid_led_default(hw, &data); if (ret_val) goto out; @@ -1720,7 +1864,7 @@ e1000_setup_led_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_setup_led_generic"); - if (hw->func.setup_led != e1000_setup_led_generic) { + if (hw->mac.ops.setup_led != e1000_setup_led_generic) { ret_val = -E1000_ERR_CONFIG; goto out; } @@ -1757,7 +1901,7 @@ e1000_cleanup_led_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_cleanup_led_generic"); - if (hw->func.cleanup_led != e1000_cleanup_led_generic) { + if (hw->mac.ops.cleanup_led != e1000_cleanup_led_generic) { ret_val = -E1000_ERR_CONFIG; goto out; } @@ -1772,7 +1916,7 @@ out: * e1000_blink_led_generic - Blink LED * @hw: pointer to the HW structure * - * Blink the led's which are set to be on. + * Blink the LEDs which are set to be on. */ s32 e1000_blink_led_generic(struct e1000_hw *hw) @@ -1894,7 +2038,7 @@ e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop) * @hw: pointer to the HW structure * * Returns 0 (E1000_SUCCESS) if successful, else returns -10 - * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not casued + * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused * the master requests to be disabled. * * Disables PCI-Express master access and verifies there are no pending @@ -1952,15 +2096,13 @@ e1000_reset_adaptive_generic(struct e1000_hw *hw) return; } - 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; + mac->in_ifs_mode = false; E1000_WRITE_REG(hw, E1000_AIT, 0); } @@ -1985,7 +2127,7 @@ e1000_update_adaptive_generic(struct e1000_hw *hw) if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { if (mac->tx_packet_delta > MIN_NUM_XMITS) { - mac->in_ifs_mode = TRUE; + mac->in_ifs_mode = true; if (mac->current_ifs_val < mac->ifs_max_val) { if (!mac->current_ifs_val) mac->current_ifs_val = mac->ifs_min_val; @@ -2000,7 +2142,7 @@ e1000_update_adaptive_generic(struct e1000_hw *hw) if (mac->in_ifs_mode && (mac->tx_packet_delta <= MIN_NUM_XMITS)) { mac->current_ifs_val = 0; - mac->in_ifs_mode = FALSE; + mac->in_ifs_mode = false; E1000_WRITE_REG(hw, E1000_AIT, 0); } } @@ -2010,7 +2152,7 @@ e1000_update_adaptive_generic(struct e1000_hw *hw) * e1000_validate_mdi_setting_generic - Verify MDI/MDIx settings * @hw: pointer to the HW structure * - * Verify that when not using auto-negotitation that MDI/MDIx is correctly + * Verify that when not using auto-negotiation that MDI/MDIx is correctly * set, which is forced to MDI mode only. */ s32 diff --git a/usr/src/uts/common/io/igb/igb_mac.h b/usr/src/uts/common/io/igb/igb_mac.h index ca893d35b1..e79eab221f 100644 --- a/usr/src/uts/common/io/igb/igb_mac.h +++ b/usr/src/uts/common/io/igb/igb_mac.h @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,17 +22,15 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.22 v2007-12-10_dragonlake5 */ +/* IntelVersion: 1.29 v2008-10-7 */ #ifndef _IGB_MAC_H #define _IGB_MAC_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -41,12 +39,20 @@ extern "C" { * Functions that should not be called directly from drivers but can be used * by other files in this 'shared code' */ +void e1000_init_mac_ops_generic(struct e1000_hw *hw); +void e1000_null_mac_generic(struct e1000_hw *hw); +s32 e1000_null_ops_generic(struct e1000_hw *hw); +s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d); +bool e1000_null_mng_mode(struct e1000_hw *hw); +void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a, u32 b, u32 c); +void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b); +void e1000_null_mta_set(struct e1000_hw *hw, u32 a); +void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a); s32 e1000_blink_led_generic(struct e1000_hw *hw); s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw); 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_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); @@ -64,13 +70,10 @@ 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); @@ -85,7 +88,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/usr/src/uts/common/io/igb/igb_main.c b/usr/src/uts/common/io/igb/igb_main.c index ed475f0014..7a69a7bd6d 100644 --- a/usr/src/uts/common/io/igb/igb_main.c +++ b/usr/src/uts/common/io/igb/igb_main.c @@ -1,17 +1,19 @@ /* * CDDL HEADER START * + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. + * You can obtain a copy of the license at: + * http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * When using or redistributing this file, you may do so under the + * License only. No other modification of this header is permitted. + * * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] @@ -20,18 +22,14 @@ */ /* - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms of the CDDL. */ - #include "igb_sw.h" static char ident[] = "Intel 1Gb Ethernet"; +static char igb_version[] = "igb 1.1.4"; /* * Local function protoypes @@ -75,7 +73,8 @@ static void igb_start_watchdog_timer(igb_t *); static void igb_restart_watchdog_timer(igb_t *); static void igb_stop_watchdog_timer(igb_t *); static void igb_disable_adapter_interrupts(igb_t *); -static void igb_enable_adapter_interrupts(igb_t *); +static void igb_enable_adapter_interrupts_82575(igb_t *); +static void igb_enable_adapter_interrupts_82576(igb_t *); static boolean_t is_valid_mac_addr(uint8_t *); static boolean_t igb_stall_check(igb_t *); static boolean_t igb_set_loopback_mode(igb_t *, uint32_t); @@ -91,7 +90,8 @@ static void igb_rem_intr_handlers(igb_t *); static void igb_rem_intrs(igb_t *); static int igb_enable_intrs(igb_t *); static int igb_disable_intrs(igb_t *); -static void igb_setup_adapter_msix(igb_t *); +static void igb_setup_msix_82575(igb_t *); +static void igb_setup_msix_82576(igb_t *); static uint_t igb_intr_legacy(void *, void *); static uint_t igb_intr_msi(void *, void *); static uint_t igb_intr_rx(void *, void *); @@ -185,6 +185,52 @@ static mac_callbacks_t igb_m_callbacks = { }; /* + * Initialize capabilities of each supported adapter type + */ +static adapter_info_t igb_82575_cap = { + /* limits */ + 4, /* maximum number of rx queues */ + 1, /* minimum number of rx queues */ + 4, /* default number of rx queues */ + 4, /* maximum number of tx queues */ + 1, /* minimum number of tx queues */ + 4, /* default number of tx queues */ + 65535, /* maximum interrupt throttle rate */ + 0, /* minimum interrupt throttle rate */ + 200, /* default interrupt throttle rate */ + + /* function pointers */ + igb_enable_adapter_interrupts_82575, + igb_setup_msix_82575, + + /* capabilities */ + (IGB_FLAG_HAS_DCA | /* capability flags */ + IGB_FLAG_VMDQ_POOL) +}; + +static adapter_info_t igb_82576_cap = { + /* limits */ + 12, /* maximum number of rx queues */ + 1, /* minimum number of rx queues */ + 4, /* default number of rx queues */ + 12, /* maximum number of tx queues */ + 1, /* minimum number of tx queues */ + 4, /* default number of tx queues */ + 65535, /* maximum interrupt throttle rate */ + 0, /* minimum interrupt throttle rate */ + 200, /* default interrupt throttle rate */ + + /* function pointers */ + igb_enable_adapter_interrupts_82576, + igb_setup_msix_82576, + + /* capabilities */ + (IGB_FLAG_HAS_DCA | /* capability flags */ + IGB_FLAG_VMDQ_POOL | + IGB_FLAG_NEED_CTX_IDX) +}; + +/* * Module Initialization Functions */ @@ -434,6 +480,7 @@ igb_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) } igb->attach_progress |= ATTACH_PROGRESS_ENABLE_INTR; + igb_log(igb, "%s", igb_version); igb->igb_state |= IGB_INITIALIZED; return (DDI_SUCCESS); @@ -679,11 +726,6 @@ igb_unconfigure(dev_info_t *devinfo, igb_t *igb) } /* - * Free device specific structure - */ - e1000_remove_device(&igb->hw); - - /* * Free the driver data structure */ kmem_free(igb, sizeof (igb_t)); @@ -753,6 +795,20 @@ igb_identify_hardware(igb_t *igb) return (IGB_FAILURE); } + /* + * Install adapter capabilities based on mac type + */ + switch (hw->mac.type) { + case e1000_82575: + igb->capab = &igb_82575_cap; + break; + case e1000_82576: + igb->capab = &igb_82576_cap; + break; + default: + return (IGB_FAILURE); + } + return (IGB_SUCCESS); } @@ -770,14 +826,15 @@ igb_regs_map(igb_t *igb) /* * First get the size of device registers to be mapped. */ - if (ddi_dev_regsize(devinfo, 1, &mem_size) != DDI_SUCCESS) { + if (ddi_dev_regsize(devinfo, IGB_ADAPTER_REGSET, &mem_size) != + DDI_SUCCESS) { return (IGB_FAILURE); } /* * Call ddi_regs_map_setup() to map registers */ - if ((ddi_regs_map_setup(devinfo, 1, + if ((ddi_regs_map_setup(devinfo, IGB_ADAPTER_REGSET, (caddr_t *)&hw->hw_addr, 0, mem_size, &igb_regs_acc_attr, &osdep->reg_handle)) != DDI_SUCCESS) { @@ -881,7 +938,7 @@ igb_init_driver_settings(igb_t *igb) } /* - * Initialize values of interrupt throttling rate + * Initialize values of interrupt throttling rates */ for (i = 1; i < MAX_NUM_EITR; i++) igb->intr_throttling[i] = igb->intr_throttling[0]; @@ -1054,12 +1111,6 @@ igb_init(igb_t *igb) } /* - * Set the FIFO size - */ - pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */ - E1000_WRITE_REG(hw, E1000_PBA, pba); - - /* * Setup flow control * * These parameters set thresholds for the adapter's generation(Tx) @@ -1074,11 +1125,25 @@ igb_init(igb_t *igb) * 90% of the Rx FIFO size, or the full Rx FIFO size minus one full * frame. */ + if (hw->mac.type == e1000_82575) { + pba = E1000_PBA_34K; + } else { + pba = E1000_PBA_64K; + } + high_water = min(((pba << 10) * 9 / 10), ((pba << 10) - igb->max_frame_size)); - hw->fc.high_water = high_water & 0xFFF8; - hw->fc.low_water = hw->fc.high_water - 8; + if (hw->mac.type == e1000_82575) { + /* 8-byte granularity */ + hw->fc.high_water = high_water & 0xFFF8; + hw->fc.low_water = hw->fc.high_water - 8; + } else { + /* 16-byte granularity */ + hw->fc.high_water = high_water & 0xFFF0; + hw->fc.low_water = hw->fc.high_water - 16; + } + hw->fc.pause_time = E1000_FC_PAUSE_TIME; hw->fc.send_xon = B_TRUE; @@ -1235,7 +1300,7 @@ igb_chip_start(igb_t *igb) * Setup MSI-X interrupts */ if (igb->intr_type == DDI_INTR_TYPE_MSIX) - igb_setup_adapter_msix(igb); + igb->capab->setup_msix(igb); /* * Initialize unicast addresses. @@ -1352,7 +1417,7 @@ igb_reset(igb_t *igb) * Enable adapter interrupts * The interrupts must be enabled after the driver state is START */ - igb_enable_adapter_interrupts(igb); + igb->capab->enable_intr(igb); if (igb_check_acc_handle(igb->osdep.cfg_handle) != DDI_FM_OK) goto reset_failure; @@ -1560,7 +1625,7 @@ igb_start(igb_t *igb) * Enable adapter interrupts * The interrupts must be enabled after the driver state is START */ - igb_enable_adapter_interrupts(igb); + igb->capab->enable_intr(igb); if (igb_check_acc_handle(igb->osdep.cfg_handle) != DDI_FM_OK) goto start_failure; @@ -1814,7 +1879,7 @@ igb_setup_rx(igb_t *igb) igb_rx_ring_t *rx_ring; igb_rx_group_t *rx_group; struct e1000_hw *hw = &igb->hw; - uint32_t reg_val; + uint32_t reg_val, rctl; uint32_t ring_per_group; int i; @@ -1826,7 +1891,15 @@ igb_setup_rx(igb_t *igb) * minimum threshold size to 1/2, and the receive buffer size to * 2k. */ - reg_val = E1000_RCTL_EN | /* Enable Receive Unit */ + rctl = E1000_READ_REG(hw, E1000_RCTL); + + /* + * only used for wakeup control. This driver doesn't do wakeup + * but leave this here for completeness. + */ + rctl &= ~(3 << E1000_RCTL_MO_SHIFT); + + rctl |= E1000_RCTL_EN | /* Enable Receive Unit */ E1000_RCTL_BAM | /* Accept Broadcast Packets */ E1000_RCTL_LPE | /* Large Packet Enable bit */ (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT) | @@ -1834,7 +1907,7 @@ igb_setup_rx(igb_t *igb) E1000_RCTL_SECRC | /* Strip Ethernet CRC */ E1000_RCTL_LBM_NO; /* Loopback Mode = none */ - E1000_WRITE_REG(hw, E1000_RCTL, reg_val); + E1000_WRITE_REG(hw, E1000_RCTL, rctl); for (i = 0; i < igb->num_rx_groups; i++) { rx_group = &igb->rx_groups[i]; @@ -1976,16 +2049,15 @@ igb_setup_tx_ring(igb_tx_ring_t *tx_ring) tx_ring->tbd_free = tx_ring->ring_size; /* - * Note: Considering the case that the chipset is being reset, - * and there are still some buffers held by the upper layer, - * we should not reset the values of tcb_head, tcb_tail. + * Note: for the case that the chipset is being reset, we should not + * reset the values of tcb_head, tcb_tail. And considering there might + * still be some packets kept in the pending_list, we should not assert + * (tcb_free == free_list_size) here. */ if (igb->igb_state == IGB_UNKNOWN) { tx_ring->tcb_head = 0; tx_ring->tcb_tail = 0; tx_ring->tcb_free = tx_ring->free_list_size; - } else { - ASSERT(tx_ring->tcb_free == tx_ring->free_list_size); } /* @@ -2003,6 +2075,13 @@ igb_setup_tx_ring(igb_tx_ring_t *tx_ring) tx_ring->hcksum_context.ip_hdr_len = 0; tx_ring->hcksum_context.mac_hdr_len = 0; tx_ring->hcksum_context.l4_proto = 0; + + /* + * Enable TXDCTL per queue + */ + reg_val = E1000_READ_REG(hw, E1000_TXDCTL(tx_ring->index)); + reg_val |= E1000_TXDCTL_QUEUE_ENABLE; + E1000_WRITE_REG(hw, E1000_TXDCTL(tx_ring->index), reg_val); } static void @@ -2021,30 +2100,17 @@ igb_setup_tx(igb_t *igb) /* * Setup the Transmit Control Register (TCTL) */ - reg_val = E1000_TCTL_PSP | E1000_TCTL_EN | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) | - (E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT) | - E1000_TCTL_RTLC; - - /* Enable the MULR bit */ - if (hw->bus.type == e1000_bus_type_pci_express) - reg_val |= E1000_TCTL_MULR; + reg_val = E1000_READ_REG(hw, E1000_TCTL); + reg_val &= ~E1000_TCTL_CT; + reg_val |= E1000_TCTL_PSP | E1000_TCTL_RTLC | + (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - E1000_WRITE_REG(hw, E1000_TCTL, reg_val); + e1000_config_collision_dist(hw); - /* - * Set the default values for the Tx Inter Packet Gap timer - */ - if (hw->phy.media_type == e1000_media_type_fiber) - reg_val = DEFAULT_82543_TIPG_IPGT_FIBER; - else - reg_val = DEFAULT_82543_TIPG_IPGT_COPPER; - reg_val |= - DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; - reg_val |= - DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; + /* Enable transmits */ + reg_val |= E1000_TCTL_EN; - E1000_WRITE_REG(hw, E1000_TIPG, reg_val); + E1000_WRITE_REG(hw, E1000_TCTL, reg_val); } /* @@ -2055,7 +2121,7 @@ igb_setup_rss(igb_t *igb) { struct e1000_hw *hw = &igb->hw; uint32_t i, mrqc, rxcsum; - int shift; + int shift = 0; uint32_t random; union e1000_reta { uint32_t dword; @@ -2063,7 +2129,11 @@ igb_setup_rss(igb_t *igb) } reta; /* Setup the Redirection Table */ - shift = 6; + if (hw->mac.type == e1000_82576) { + shift = 0; + } else if (hw->mac.type == e1000_82575) { + shift = 6; + } for (i = 0; i < (32 * 4); i++) { reta.bytes[i & 3] = (i % igb->num_rx_rings) << shift; if ((i & 3) == 3) { @@ -2166,7 +2236,7 @@ igb_setup_mac_rss_classify(igb_t *igb) /* Define the default group and default queues */ vmdctl = E1000_VMDQ_MAC_GROUP_DEFAULT_QUEUE; - E1000_WRITE_REG(hw, E1000_VMD_CTL, vmdctl); + E1000_WRITE_REG(hw, E1000_VT_CTL, vmdctl); /* * Disable Packet Checksum to enable RSS for multiple receive queues. @@ -2499,7 +2569,7 @@ igb_get_conf(igb_t *igb) if (flow_control == 4) flow_control = e1000_fc_default; - hw->fc.type = flow_control; + hw->fc.requested_mode = flow_control; /* * Multiple rings configurations @@ -2512,10 +2582,16 @@ igb_get_conf(igb_t *igb) igb->mr_enable = igb_get_prop(igb, PROP_MR_ENABLE, 0, 1, 1); igb->num_rx_groups = igb_get_prop(igb, PROP_RX_GROUP_NUM, MIN_RX_GROUP_NUM, MAX_RX_GROUP_NUM, DEFAULT_RX_GROUP_NUM); + /* + * Currently we do not support VMDq for 82576. + * If it is e1000_82576, set num_rx_groups to 1. + */ + if (hw->mac.type == e1000_82576) + igb->num_rx_groups = 1; if (igb->mr_enable) { - igb->num_tx_rings = DEFAULT_TX_QUEUE_NUM; - igb->num_rx_rings = DEFAULT_RX_QUEUE_NUM; + igb->num_tx_rings = igb->capab->def_tx_que_num; + igb->num_rx_rings = igb->capab->def_rx_que_num; } else { igb->num_tx_rings = 1; igb->num_rx_rings = 1; @@ -2605,8 +2681,9 @@ igb_get_conf(igb_t *igb) DEFAULT_RX_LIMIT_PER_INTR); igb->intr_throttling[0] = igb_get_prop(igb, PROP_INTR_THROTTLING, - MIN_INTR_THROTTLING, MAX_INTR_THROTTLING, - DEFAULT_INTR_THROTTLING); + igb->capab->min_intr_throttle, + igb->capab->max_intr_throttle, + igb->capab->def_intr_throttle); } /* @@ -3090,24 +3167,55 @@ igb_disable_adapter_interrupts(igb_t *igb) * Set the IMC register to mask all the interrupts, * including the tx interrupts. */ - E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + E1000_WRITE_REG(hw, E1000_IMC, ~0); + E1000_WRITE_REG(hw, E1000_IAM, 0); /* * Additional disabling for MSI-X */ if (igb->intr_type == DDI_INTR_TYPE_MSIX) { - E1000_WRITE_REG(hw, E1000_EIMC, 0xffffffff); - E1000_WRITE_REG(hw, E1000_EIAC, 0x0); + E1000_WRITE_REG(hw, E1000_EIMC, ~0); + E1000_WRITE_REG(hw, E1000_EIAC, 0); + E1000_WRITE_REG(hw, E1000_EIAM, 0); } E1000_WRITE_FLUSH(hw); } /* - * igb_enable_adapter_interrupts - Mask/enable all hardware interrupts + * igb_enable_adapter_interrupts_82576 - Enable NIC interrupts for 82576 */ static void -igb_enable_adapter_interrupts(igb_t *igb) +igb_enable_adapter_interrupts_82576(igb_t *igb) +{ + struct e1000_hw *hw = &igb->hw; + + if (igb->intr_type == DDI_INTR_TYPE_MSIX) { + + /* Interrupt enabling for MSI-X */ + E1000_WRITE_REG(hw, E1000_EIMS, igb->eims_mask); + E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask); + igb->ims_mask = E1000_IMS_LSC; + E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_LSC); + } else { + /* Interrupt enabling for MSI and legacy */ + E1000_WRITE_REG(hw, E1000_IVAR0, E1000_IVAR_VALID); + igb->ims_mask = IMS_ENABLE_MASK | E1000_IMS_TXQE; + E1000_WRITE_REG(hw, E1000_IMS, + (IMS_ENABLE_MASK | E1000_IMS_TXQE)); + } + + /* Disable auto-mask for ICR interrupt bits */ + E1000_WRITE_REG(hw, E1000_IAM, 0); + + E1000_WRITE_FLUSH(hw); +} + +/* + * igb_enable_adapter_interrupts_82575 - Enable NIC interrupts for 82575 + */ +static void +igb_enable_adapter_interrupts_82575(igb_t *igb) { struct e1000_hw *hw = &igb->hw; uint32_t reg; @@ -3530,6 +3638,9 @@ igb_intr_legacy(void *arg1, void *arg2) ASSERT(igb->num_rx_rings == 1); ASSERT(igb->num_tx_rings == 1); + /* Make sure all interrupt causes cleared */ + (void) E1000_READ_REG(&igb->hw, E1000_EICR); + if (icr & E1000_ICR_RXT0) { mp = igb_rx(&igb->rx_rings[0], IGB_NO_POLL); } @@ -3601,6 +3712,9 @@ igb_intr_msi(void *arg1, void *arg2) icr = E1000_READ_REG(&igb->hw, E1000_ICR); + /* Make sure all interrupt causes cleared */ + (void) E1000_READ_REG(&igb->hw, E1000_EICR); + /* * For MSI interrupt, we have only one vector, * so we have only one rx ring and one tx ring enabled. @@ -4055,19 +4169,20 @@ igb_add_intr_handlers(igb_t *igb) } /* - * igb_setup_adapter_msix - setup the adapter to use MSI-X interrupts + * igb_setup_msix_82575 - setup 82575 adapter to use MSI-X interrupts * * For each vector enabled on the adapter, Set the MSIXBM register accordingly */ static void -igb_setup_adapter_msix(igb_t *igb) +igb_setup_msix_82575(igb_t *igb) { uint32_t eims = 0; int i, vector; struct e1000_hw *hw = &igb->hw; /* - * Set vector for other causes, NOTE assumption that it is vector 0 + * Set vector for tx ring 0 and other causes. + * NOTE assumption that it is vector 0. */ vector = 0; @@ -4083,7 +4198,8 @@ igb_setup_adapter_msix(igb_t *igb) E1000_WRITE_REG(hw, E1000_MSIXBM(vector), eims); /* - * Accumulate bits to enable in igb_enable_adapter_interrupts() + * Accumulate bits to enable in + * igb_enable_adapter_interrupts_82575() */ igb->eims_mask |= eims; @@ -4098,7 +4214,8 @@ igb_setup_adapter_msix(igb_t *igb) E1000_WRITE_REG(hw, E1000_MSIXBM(vector), eims); /* - * Accumulate bits to enable in igb_enable_adapter_interrupts() + * Accumulate bits to enable in + * igb_enable_adapter_interrupts_82575() */ igb->eims_mask |= eims; @@ -4115,6 +4232,98 @@ igb_setup_adapter_msix(igb_t *igb) } /* + * igb_setup_msix_82576 - setup 82576 adapter to use MSI-X interrupts + * + * 82576 uses a table based method for assigning vectors. Each queue has a + * single entry in the table to which we write a vector number along with a + * "valid" bit. The entry is a single byte in a 4-byte register. Vectors + * take a different position in the 4-byte register depending on whether + * they are numbered above or below 8. + */ +static void +igb_setup_msix_82576(igb_t *igb) +{ + struct e1000_hw *hw = &igb->hw; + uint32_t ivar, index, vector; + int i; + + /* must enable msi-x capability before IVAR settings */ + E1000_WRITE_REG(hw, E1000_GPIE, + (E1000_GPIE_MSIX_MODE | E1000_GPIE_PBA | E1000_GPIE_NSICR)); + + /* + * Set vector for tx ring 0 and other causes. + * NOTE assumption that it is vector 0. + * This is also interdependent with installation of interrupt service + * routines in igb_add_intr_handlers(). + */ + + /* assign "other" causes to vector 0 */ + vector = 0; + ivar = ((vector | E1000_IVAR_VALID) << 8); + E1000_WRITE_REG(hw, E1000_IVAR_MISC, ivar); + + /* assign tx ring 0 to vector 0 */ + ivar = ((vector | E1000_IVAR_VALID) << 8); + E1000_WRITE_REG(hw, E1000_IVAR0, ivar); + + /* prepare to enable tx & other interrupt causes */ + igb->eims_mask = (1 << vector); + + vector ++; + for (i = 0; i < igb->num_rx_rings; i++) { + /* + * Set vector for each rx ring + */ + index = (i & 0x7); + ivar = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index); + + if (i < 8) { + /* vector goes into low byte of register */ + ivar = ivar & 0xFFFFFF00; + ivar |= (vector | E1000_IVAR_VALID); + } else { + /* vector goes into third byte of register */ + ivar = ivar & 0xFF00FFFF; + ivar |= ((vector | E1000_IVAR_VALID) << 16); + } + E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar); + + /* Accumulate interrupt-cause bits to enable */ + igb->eims_mask |= (1 << vector); + + vector ++; + } + + for (i = 1; i < igb->num_tx_rings; i++) { + /* + * Set vector for each tx ring from 2nd tx ring. + * Note assumption that tx vectors numericall follow rx vectors. + */ + index = (i & 0x7); + ivar = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index); + + if (i < 8) { + /* vector goes into second byte of register */ + ivar = ivar & 0xFFFF00FF; + ivar |= ((vector | E1000_IVAR_VALID) << 8); + } else { + /* vector goes into fourth byte of register */ + ivar = ivar & 0x00FFFFFF; + ivar |= (vector | E1000_IVAR_VALID) << 24; + } + E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar); + + /* Accumulate interrupt-cause bits to enable */ + igb->eims_mask |= (1 << vector); + + vector ++; + } + + ASSERT(vector == igb->intr_cnt); +} + +/* * igb_rem_intr_handlers - remove the interrupt handlers */ static void diff --git a/usr/src/uts/common/io/igb/igb_manage.c b/usr/src/uts/common/io/igb/igb_manage.c index 56715fbb3b..d34df442af 100644 --- a/usr/src/uts/common/io/igb/igb_manage.c +++ b/usr/src/uts/common/io/igb/igb_manage.c @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,16 +22,13 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.19 v2007-12-10_dragonlake5 */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* IntelVersion: 1.27 v2008-10-7 */ #include "igb_api.h" -#include "igb_manage.h" static u8 e1000_calculate_checksum(u8 *buffer, u32 length); @@ -65,7 +62,7 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length) * * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND * - * This function checks whether the HOST IF is enabled for command operaton + * This function checks whether the HOST IF is enabled for command operation * and also checks whether the previous command is completed. It busy waits * in case of previous command is not completed. */ @@ -104,7 +101,7 @@ out: } /* - * e1000_check_mng_mode_generic - Generic check managament mode + * e1000_check_mng_mode_generic - Generic check management mode * @hw: pointer to the HW structure * * Reads the firmware semaphore register and returns true (>0) if @@ -138,13 +135,13 @@ e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) u32 offset; s32 ret_val, hdr_csum, csum; u8 i, len; - bool tx_filter = TRUE; + bool tx_filter = true; DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); /* No manageability, no filtering */ - if (!e1000_check_mng_mode(hw)) { - tx_filter = FALSE; + if (!hw->mac.ops.check_mng_mode(hw)) { + tx_filter = false; goto out; } @@ -152,9 +149,9 @@ e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) * If we can't read from the host interface for whatever * reason, disable filtering. */ - ret_val = e1000_mng_enable_host_if(hw); + ret_val = hw->mac.ops.mng_enable_host_if(hw); if (ret_val != E1000_SUCCESS) { - tx_filter = FALSE; + tx_filter = false; goto out; } @@ -181,7 +178,7 @@ e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) /* Cookie area is valid, make the final check for filtering. */ if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) - tx_filter = FALSE; + tx_filter = false; out: hw->mac.tx_pkt_filtering = tx_filter; @@ -213,18 +210,18 @@ e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, hdr.checksum = 0; /* Enable the host interface */ - ret_val = e1000_mng_enable_host_if(hw); + ret_val = hw->mac.ops.mng_enable_host_if(hw); if (ret_val) goto out; /* Populate the host interface with the contents of "buffer". */ - ret_val = e1000_mng_host_if_write(hw, buffer, length, + ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, sizeof (hdr), &(hdr.checksum)); if (ret_val) goto out; /* Write the manageability command header */ - ret_val = e1000_mng_write_cmd_header(hw, &hdr); + ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); if (ret_val) goto out; @@ -359,7 +356,7 @@ e1000_enable_mng_pass_thru(struct e1000_hw *hw) { u32 manc; u32 fwsm, factps; - bool ret_val = FALSE; + bool ret_val = false; DEBUGFUNC("e1000_enable_mng_pass_thru"); @@ -379,13 +376,13 @@ e1000_enable_mng_pass_thru(struct e1000_hw *hw) if (!(factps & E1000_FACTPS_MNGCG) && ((fwsm & E1000_FWSM_MODE_MASK) == (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { - ret_val = TRUE; + ret_val = true; goto out; } } else { if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) { - ret_val = TRUE; + ret_val = true; goto out; } } diff --git a/usr/src/uts/common/io/igb/igb_manage.h b/usr/src/uts/common/io/igb/igb_manage.h index 7168a5cf44..4972bf6734 100644 --- a/usr/src/uts/common/io/igb/igb_manage.h +++ b/usr/src/uts/common/io/igb/igb_manage.h @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,17 +22,15 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.15 v2007-12-10_dragonlake5 */ +/* IntelVersion: 1.18 v2008-10-7 */ #ifndef _IGB_MANAGE_H #define _IGB_MANAGE_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -46,14 +44,15 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr); s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, u16 length); +bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); -typedef enum { +enum e1000_mng_mode { e1000_mng_mode_none = 0, e1000_mng_mode_asf, e1000_mng_mode_pt, e1000_mng_mode_ipmi, e1000_mng_mode_host_if_only -} e1000_mng_mode; +}; #define E1000_FACTPS_MNGCG 0x20000000 diff --git a/usr/src/uts/common/io/igb/igb_ndd.c b/usr/src/uts/common/io/igb/igb_ndd.c index 93a0353caa..58ce0e77e5 100644 --- a/usr/src/uts/common/io/igb/igb_ndd.c +++ b/usr/src/uts/common/io/igb/igb_ndd.c @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,12 +22,10 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "igb_sw.h" /* Function prototypes */ @@ -339,7 +337,7 @@ igb_nd_ioctl(igb_t *igb, queue_t *q, switch (cmd) { default: /* NOTREACHED */ - ASSERT(FALSE); + ASSERT(B_FALSE); return (IOC_INVAL); case ND_GET: diff --git a/usr/src/uts/common/io/igb/igb_nvm.c b/usr/src/uts/common/io/igb/igb_nvm.c index 8949a10caf..4552f9e54f 100644 --- a/usr/src/uts/common/io/igb/igb_nvm.c +++ b/usr/src/uts/common/io/igb/igb_nvm.c @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,16 +22,87 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.35 v2007-12-10_dragonlake5 */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* IntelVersion: 1.46 v2008-10-7 */ #include "igb_api.h" -#include "igb_nvm.h" + +static void e1000_stop_nvm(struct e1000_hw *hw); +static void e1000_reload_nvm_generic(struct e1000_hw *hw); + +/* + * e1000_init_nvm_ops_generic - Initialize NVM function pointers + * @hw: pointer to the HW structure + * + * Setups up the function pointers to no-op functions + */ +void +e1000_init_nvm_ops_generic(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + DEBUGFUNC("e1000_init_nvm_ops_generic"); + + /* Initialize function pointers */ + nvm->ops.init_params = e1000_null_ops_generic; + nvm->ops.acquire = e1000_null_ops_generic; + nvm->ops.read = e1000_null_read_nvm; + nvm->ops.release = e1000_null_nvm_generic; + nvm->ops.reload = e1000_reload_nvm_generic; + nvm->ops.update = e1000_null_ops_generic; + nvm->ops.valid_led_default = e1000_null_led_default; + nvm->ops.validate = e1000_null_ops_generic; + nvm->ops.write = e1000_null_write_nvm; +} + +/* + * e1000_null_nvm_read - No-op function, return 0 + * @hw: pointer to the HW structure + */ +s32 +e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c) +{ + DEBUGFUNC("e1000_null_read_nvm"); + UNREFERENCED_4PARAMETER(hw, a, b, c); + return (E1000_SUCCESS); +} + +/* + * e1000_null_nvm_generic - No-op function, return void + * @hw: pointer to the HW structure + */ +void +e1000_null_nvm_generic(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_null_nvm_generic"); + UNREFERENCED_1PARAMETER(hw); +} + +/* + * e1000_null_led_default - No-op function, return 0 + * @hw: pointer to the HW structure + */ +s32 +e1000_null_led_default(struct e1000_hw *hw, u16 *data) +{ + DEBUGFUNC("e1000_null_led_default"); + UNREFERENCED_2PARAMETER(hw, data); + return (E1000_SUCCESS); +} + +/* + * e1000_null_write_nvm - No-op function, return 0 + * @hw: pointer to the HW structure + */ +s32 +e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c) +{ + DEBUGFUNC("e1000_null_write_nvm"); + UNREFERENCED_4PARAMETER(hw, a, b, c); + return (E1000_SUCCESS); +} /* * e1000_raise_eec_clk - Raise EEPROM clock @@ -285,7 +356,7 @@ e1000_stop_nvm(struct e1000_hw *hw) eecd |= E1000_EECD_CS; e1000_lower_eec_clk(hw, &eecd); } else if (hw->nvm.type == e1000_nvm_eeprom_microwire) { - /* CS on Microcwire is active-high */ + /* CS on Microwire is active-high */ eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); E1000_WRITE_REG(hw, E1000_EECD, eecd); e1000_raise_eec_clk(hw, &eecd); @@ -374,71 +445,6 @@ out: } /* - * e1000_read_nvm_spi - Read EEPROM's using SPI - * @hw: pointer to the HW structure - * @offset: offset of word in the EEPROM to read - * @words: number of words to read - * @data: word read from the EEPROM - * - * Reads a 16 bit word from the EEPROM. - */ -s32 -e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i = 0; - s32 ret_val; - u16 word_in; - u8 read_opcode = NVM_READ_OPCODE_SPI; - - DEBUGFUNC("e1000_read_nvm_spi"); - - /* - * A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - ret_val = e1000_acquire_nvm(hw); - if (ret_val) - goto out; - - ret_val = e1000_ready_nvm_eeprom(hw); - if (ret_val) - goto release; - - e1000_standby_nvm(hw); - - if ((nvm->address_bits == 8) && (offset >= 128)) - read_opcode |= NVM_A8_OPCODE_SPI; - - /* Send the READ command (opcode + addr) */ - e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); - e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits); - - /* - * Read the data. SPI NVMs increment the address with each byte - * read and will roll over if reading beyond the end. This allows - * us to read the whole NVM from any offset - */ - for (i = 0; i < words; i++) { - word_in = e1000_shift_in_eec_bits(hw, 16); - data[i] = (word_in >> 8) | (word_in << 8); - } - -release: - e1000_release_nvm(hw); - -out: - return (ret_val); -} - -/* * e1000_read_nvm_microwire - Reads EEPROM's using microwire * @hw: pointer to the HW structure * @offset: offset of word in the EEPROM to read @@ -469,7 +475,7 @@ e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, goto out; } - ret_val = e1000_acquire_nvm(hw); + ret_val = nvm->ops.acquire(hw); if (ret_val) goto out; @@ -492,7 +498,7 @@ e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, } release: - e1000_release_nvm(hw); + nvm->ops.release(hw); out: return (ret_val); @@ -554,7 +560,7 @@ out: * Writes data to EEPROM at offset using SPI interface. * * If e1000_update_nvm_checksum is not called after this function , the - * EEPROM will most likley contain an invalid checksum. + * EEPROM will most likely contain an invalid checksum. */ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) @@ -576,12 +582,10 @@ e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) goto out; } - ret_val = e1000_acquire_nvm(hw); + ret_val = nvm->ops.acquire(hw); if (ret_val) goto out; - msec_delay(10); - while (widx < words) { u8 write_opcode = NVM_WRITE_OPCODE_SPI; @@ -625,7 +629,7 @@ e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) msec_delay(10); release: - e1000_release_nvm(hw); + nvm->ops.release(hw); out: return (ret_val); @@ -641,7 +645,7 @@ out: * Writes data to EEPROM at offset using microwire interface. * * If e1000_update_nvm_checksum is not called after this function , the - * EEPROM will most likley contain an invalid checksum. + * EEPROM will most likely contain an invalid checksum. */ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, @@ -666,7 +670,7 @@ e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, goto out; } - ret_val = e1000_acquire_nvm(hw); + ret_val = nvm->ops.acquire(hw); if (ret_val) goto out; @@ -716,7 +720,7 @@ e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); release: - e1000_release_nvm(hw); + nvm->ops.release(hw); out: return (ret_val); @@ -738,14 +742,14 @@ e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num) DEBUGFUNC("e1000_read_pba_num_generic"); - ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } *pba_num = (u32)(nvm_data << 16); - ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; @@ -774,7 +778,7 @@ e1000_read_mac_addr_generic(struct e1000_hw *hw) for (i = 0; i < ETH_ADDR_LEN; i += 2) { offset = i >> 1; - ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; @@ -811,7 +815,7 @@ e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_validate_nvm_checksum_generic"); for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; @@ -847,7 +851,7 @@ e1000_update_nvm_checksum_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_update_nvm_checksum"); for (i = 0; i < NVM_CHECKSUM_REG; i++) { - ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error while updating checksum.\n"); goto out; @@ -855,10 +859,9 @@ e1000_update_nvm_checksum_generic(struct e1000_hw *hw) checksum += nvm_data; } checksum = (u16) NVM_SUM - checksum; - ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); - if (ret_val) { + ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); + if (ret_val) DEBUGOUT("NVM Write Error while updating checksum.\n"); - } out: return (ret_val); @@ -884,35 +887,3 @@ e1000_reload_nvm_generic(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); } - -/* Function pointers local to this file and not intended for public use */ - -/* - * e1000_acquire_nvm - Acquire exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * For those silicon families which have implemented a NVM acquire function, - * run the defined function else return success. - */ -s32 -e1000_acquire_nvm(struct e1000_hw *hw) -{ - if (hw->func.acquire_nvm) - return (hw->func.acquire_nvm(hw)); - - return (E1000_SUCCESS); -} - -/* - * e1000_release_nvm - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * For those silicon families which have implemented a NVM release function, - * run the defined fucntion else return success. - */ -void -e1000_release_nvm(struct e1000_hw *hw) -{ - if (hw->func.release_nvm) - hw->func.release_nvm(hw); -} diff --git a/usr/src/uts/common/io/igb/igb_nvm.h b/usr/src/uts/common/io/igb/igb_nvm.h index 01b4f9dc6e..f5a96bd89a 100644 --- a/usr/src/uts/common/io/igb/igb_nvm.h +++ b/usr/src/uts/common/io/igb/igb_nvm.h @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,27 +22,29 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.13 v2007-12-10_dragonlake5 */ +/* IntelVersion: 1.18 v2008-10-7 */ #ifndef _IGB_NVM_H #define _IGB_NVM_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif +void e1000_init_nvm_ops_generic(struct e1000_hw *hw); +s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); +void e1000_null_nvm_generic(struct e1000_hw *hw); +s32 e1000_null_led_default(struct e1000_hw *hw, u16 *data); +s32 e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); s32 e1000_acquire_nvm_generic(struct e1000_hw *hw); s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num); -s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, @@ -56,13 +58,7 @@ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw); -void e1000_stop_nvm(struct e1000_hw *hw); void e1000_release_nvm_generic(struct e1000_hw *hw); -void e1000_reload_nvm_generic(struct e1000_hw *hw); - -/* Function pointers */ -s32 e1000_acquire_nvm(struct e1000_hw *hw); -void e1000_release_nvm(struct e1000_hw *hw); #define E1000_STM_OPCODE 0xDB00 diff --git a/usr/src/uts/common/io/igb/igb_osdep.c b/usr/src/uts/common/io/igb/igb_osdep.c index f915edd5ae..99151cd10f 100644 --- a/usr/src/uts/common/io/igb/igb_osdep.c +++ b/usr/src/uts/common/io/igb/igb_osdep.c @@ -1,17 +1,19 @@ /* * CDDL HEADER START * + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. + * You can obtain a copy of the license at: + * http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * When using or redistributing this file, you may do so under the + * License only. No other modification of this header is permitted. + * * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] @@ -20,36 +22,14 @@ */ /* - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms of the CDDL. */ #include "igb_osdep.h" #include "igb_api.h" -s32 -e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, u32 size) -{ - hw->dev_spec = kmem_zalloc(size, KM_SLEEP); - - return (E1000_SUCCESS); -} - -void -e1000_free_dev_spec_struct(struct e1000_hw *hw) -{ - if (hw->dev_spec == NULL) - return; - - kmem_free(hw->dev_spec, hw->dev_spec_size); - hw->dev_spec = NULL; -} - void e1000_pci_set_mwi(struct e1000_hw *hw) { diff --git a/usr/src/uts/common/io/igb/igb_osdep.h b/usr/src/uts/common/io/igb/igb_osdep.h index f56f320a1c..158e753909 100644 --- a/usr/src/uts/common/io/igb/igb_osdep.h +++ b/usr/src/uts/common/io/igb/igb_osdep.h @@ -1,17 +1,19 @@ /* * CDDL HEADER START * + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. + * You can obtain a copy of the license at: + * http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * When using or redistributing this file, you may do so under the + * License only. No other modification of this header is permitted. + * * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] @@ -20,12 +22,8 @@ */ /* - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms of the CDDL. */ #ifndef _IGB_OSDEP_H @@ -56,25 +54,26 @@ extern "C" { #define usec_delay(x) drv_usecwait(x) #define msec_delay(x) drv_usecwait(x * 1000) +#define msec_delay_irq msec_delay #ifdef IGB_DEBUG #define DEBUGOUT(S) IGB_DEBUGLOG_0(NULL, S) #define DEBUGOUT1(S, A) IGB_DEBUGLOG_1(NULL, S, A) #define DEBUGOUT2(S, A, B) IGB_DEBUGLOG_2(NULL, S, A, B) #define DEBUGOUT3(S, A, B, C) IGB_DEBUGLOG_3(NULL, S, A, B, C) -#define DEBUGFUNC(F) #else #define DEBUGOUT(S) #define DEBUGOUT1(S, A) #define DEBUGOUT2(S, A, B) #define DEBUGOUT3(S, A, B, C) -#define DEBUGFUNC(F) #endif +#define DEBUGFUNC(F) + #define OS_DEP(hw) ((struct igb_osdep *)((hw)->back)) -#define FALSE 0 -#define TRUE 1 +#define false B_FALSE +#define true B_TRUE #define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */ #define PCI_COMMAND_REGISTER 0x04 @@ -132,9 +131,16 @@ extern "C" { #define E1000_READ_REG_ARRAY_DWORD(a, reg, offset) \ E1000_READ_REG_ARRAY(a, reg, offset) -#define msec_delay_irq msec_delay +#define UNREFERENCED_1PARAMETER(_p) _NOTE(ARGUNUSED(_p)) +#define UNREFERENCED_2PARAMETER(_p, _q) _NOTE(ARGUNUSED(_p, _q)) +#define UNREFERENCED_3PARAMETER(_p, _q, _r) _NOTE(ARGUNUSED(_p, _q, _r)) +#define UNREFERENCED_4PARAMETER(_p, _q, _r, _s) _NOTE(ARGUNUSED(_p, _q, _r, _s)) +#define UNREFERENCED_5PARAMETER(_p, _q, _r, _s, _t) \ + _NOTE(ARGUNUSED(_p, _q, _r, _s, _t)) -#define UNREFERENCED_PARAMETER(x) _NOTE(ARGUNUSED(x)) +#define __le16 u16 +#define __le32 u32 +#define __le64 u64 typedef int8_t s8; typedef int16_t s16; diff --git a/usr/src/uts/common/io/igb/igb_phy.c b/usr/src/uts/common/io/igb/igb_phy.c index 5cc7304734..daf53a13e0 100644 --- a/usr/src/uts/common/io/igb/igb_phy.c +++ b/usr/src/uts/common/io/igb/igb_phy.c @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,21 +22,15 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.71 v2007-12-10_dragonlake5 */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* IntelVersion: 1.112 v2008-10-7 */ #include "igb_api.h" -#include "igb_phy.h" -static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw); -static void e1000_release_phy(struct e1000_hw *hw); -static s32 e1000_acquire_phy(struct e1000_hw *hw); -static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); +static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); /* Cable length tables */ static const u16 e1000_m88_cable_length_table[] = @@ -61,6 +55,85 @@ static const u16 e1000_igp_2_cable_length_table[] = sizeof (e1000_igp_2_cable_length_table[0])) /* + * e1000_init_phy_ops_generic - Initialize PHY function pointers + * @hw: pointer to the HW structure + * + * Setups up the function pointers to no-op functions + */ +void +e1000_init_phy_ops_generic(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + DEBUGFUNC("e1000_init_phy_ops_generic"); + + /* Initialize function pointers */ + phy->ops.init_params = e1000_null_ops_generic; + phy->ops.acquire = e1000_null_ops_generic; + phy->ops.check_polarity = e1000_null_ops_generic; + phy->ops.check_reset_block = e1000_null_ops_generic; + phy->ops.commit = e1000_null_ops_generic; + phy->ops.force_speed_duplex = e1000_null_ops_generic; + phy->ops.get_cfg_done = e1000_null_ops_generic; + phy->ops.get_cable_length = e1000_null_ops_generic; + phy->ops.get_info = e1000_null_ops_generic; + phy->ops.read_reg = e1000_null_read_reg; + phy->ops.release = e1000_null_phy_generic; + phy->ops.reset = e1000_null_ops_generic; + phy->ops.set_d0_lplu_state = e1000_null_lplu_state; + phy->ops.set_d3_lplu_state = e1000_null_lplu_state; + phy->ops.write_reg = e1000_null_write_reg; + phy->ops.power_up = e1000_null_phy_generic; + phy->ops.power_down = e1000_null_phy_generic; +} + +/* + * e1000_null_read_reg - No-op function, return 0 + * @hw: pointer to the HW structure + */ +s32 +e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data) +{ + DEBUGFUNC("e1000_null_read_reg"); + UNREFERENCED_3PARAMETER(hw, offset, data); + return (E1000_SUCCESS); +} + +/* + * e1000_null_phy_generic - No-op function, return void + * @hw: pointer to the HW structure + */ +void +e1000_null_phy_generic(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_null_phy_generic"); + UNREFERENCED_1PARAMETER(hw); +} + +/* + * e1000_null_lplu_state - No-op function, return 0 + * @hw: pointer to the HW structure + */ +s32 +e1000_null_lplu_state(struct e1000_hw *hw, bool active) +{ + DEBUGFUNC("e1000_null_lplu_state"); + UNREFERENCED_2PARAMETER(hw, active); + return (E1000_SUCCESS); +} + +/* + * e1000_null_write_reg - No-op function, return 0 + * @hw: pointer to the HW structure + */ +s32 +e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data) +{ + DEBUGFUNC("e1000_null_write_reg"); + UNREFERENCED_3PARAMETER(hw, offset, data); + return (E1000_SUCCESS); +} + +/* * e1000_check_reset_block_generic - Check if PHY reset is blocked * @hw: pointer to the HW structure * @@ -97,13 +170,16 @@ e1000_get_phy_id(struct e1000_hw *hw) DEBUGFUNC("e1000_get_phy_id"); - ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id); + if (!(phy->ops.read_reg)) + goto out; + + ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); if (ret_val) goto out; phy->id = (u32)(phy_id << 16); usec_delay(20); - ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id); + ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); if (ret_val) goto out; @@ -123,15 +199,18 @@ out: s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw) { - s32 ret_val; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_phy_reset_dsp_generic"); - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); + if (!(hw->phy.ops.write_reg)) + goto out; + + ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); if (ret_val) goto out; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); + ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); out: return (ret_val); @@ -143,7 +222,7 @@ out: * @offset: register offset to be read * @data: pointer to the read data * - * Reads the MDI control regsiter in the PHY at offset and stores the + * Reads the MDI control register in the PHY at offset and stores the * information read to data. */ s32 @@ -155,12 +234,6 @@ e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) DEBUGFUNC("e1000_read_phy_reg_mdic"); - if (offset > MAX_PHY_REG_ADDRESS) { - DEBUGOUT1("PHY Address %d is out of range\n", offset); - ret_val = -E1000_ERR_PARAM; - goto out; - } - /* * Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the @@ -216,12 +289,6 @@ e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) DEBUGFUNC("e1000_write_phy_reg_mdic"); - if (offset > MAX_PHY_REG_ADDRESS) { - DEBUGOUT1("PHY Address %d is out of range\n", offset); - ret_val = -E1000_ERR_PARAM; - goto out; - } - /* * Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the @@ -273,18 +340,21 @@ out: s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) { - s32 ret_val; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_phy_reg_m88"); - ret_val = e1000_acquire_phy(hw); + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); - e1000_release_phy(hw); + hw->phy.ops.release(hw); out: return (ret_val); @@ -302,18 +372,21 @@ out: s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) { - s32 ret_val; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_phy_reg_m88"); - ret_val = e1000_acquire_phy(hw); + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); - e1000_release_phy(hw); + hw->phy.ops.release(hw); out: return (ret_val); @@ -332,11 +405,14 @@ out: s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) { - s32 ret_val; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_phy_reg_igp"); - ret_val = e1000_acquire_phy(hw); + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; @@ -344,7 +420,7 @@ e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (ret_val) { - e1000_release_phy(hw); + hw->phy.ops.release(hw); goto out; } } @@ -352,7 +428,7 @@ 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, data); - e1000_release_phy(hw); + hw->phy.ops.release(hw); out: return (ret_val); @@ -370,11 +446,14 @@ out: s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) { - s32 ret_val; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_phy_reg_igp"); - ret_val = e1000_acquire_phy(hw); + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; @@ -382,7 +461,7 @@ e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (ret_val) { - e1000_release_phy(hw); + hw->phy.ops.release(hw); goto out; } } @@ -390,7 +469,7 @@ 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, data); - e1000_release_phy(hw); + hw->phy.ops.release(hw); out: return (ret_val); @@ -410,11 +489,14 @@ s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) { u32 kmrnctrlsta; - s32 ret_val; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_kmrn_reg_generic"); - ret_val = e1000_acquire_phy(hw); + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; @@ -427,7 +509,7 @@ e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); *data = (u16)kmrnctrlsta; - e1000_release_phy(hw); + hw->phy.ops.release(hw); out: return (ret_val); @@ -447,11 +529,14 @@ s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) { u32 kmrnctrlsta; - s32 ret_val; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_kmrn_reg_generic"); - ret_val = e1000_acquire_phy(hw); + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; @@ -460,7 +545,7 @@ e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); usec_delay(2); - e1000_release_phy(hw); + hw->phy.ops.release(hw); out: return (ret_val); @@ -488,13 +573,11 @@ e1000_copper_link_setup_m88(struct e1000_hw *hw) } /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; - /* For newer PHYs this bit is downshift enable */ - if (phy->type == e1000_phy_m88) - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; /* * Options: @@ -533,23 +616,17 @@ e1000_copper_link_setup_m88(struct e1000_hw *hw) if (phy->disable_polarity_correction == 1) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - /* Enable downshift on BM (disabled by default) */ - if (phy->type == e1000_phy_bm) - phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT; - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; - if ((phy->type == e1000_phy_m88) && - (phy->revision < E1000_REVISION_4) && - (phy->id != BME1000_E_PHY_ID_R2)) { + if (phy->revision < E1000_REVISION_4) { /* * Force TX_CLK in the Extended PHY Specific Control Register * to 25MHz clock. */ - ret_val = e1000_read_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); if (ret_val) goto out; @@ -567,14 +644,14 @@ e1000_copper_link_setup_m88(struct e1000_hw *hw) phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); } - ret_val = e1000_write_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); if (ret_val) goto out; } /* Commit the changes. */ - ret_val = e1000_phy_commit(hw); + ret_val = phy->ops.commit(hw); if (ret_val) { DEBUGOUT("Error committing the PHY changes\n"); goto out; @@ -605,14 +682,17 @@ e1000_copper_link_setup_igp(struct e1000_hw *hw) goto out; } - ret_val = e1000_phy_hw_reset(hw); + ret_val = hw->phy.ops.reset(hw); if (ret_val) { DEBUGOUT("Error resetting the PHY.\n"); goto out; } - /* Wait 15ms for MAC to configure PHY from NVM settings. */ - msec_delay(15); + /* + * Wait 100ms for MAC to configure PHY from NVM settings, to avoid + * timeout issues when LFS is enabled. + */ + msec_delay(100); /* * The NVM settings will configure LPLU in D3 for @@ -620,7 +700,7 @@ e1000_copper_link_setup_igp(struct e1000_hw *hw) */ if (phy->type == e1000_phy_igp) { /* disable lplu d3 during driver init */ - ret_val = e1000_set_d3_lplu_state(hw, FALSE); + ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); if (ret_val) { DEBUGOUT("Error Disabling LPLU D3\n"); goto out; @@ -628,13 +708,15 @@ e1000_copper_link_setup_igp(struct e1000_hw *hw) } /* disable lplu d0 during driver init */ - ret_val = e1000_set_d0_lplu_state(hw, FALSE); - if (ret_val) { - DEBUGOUT("Error Disabling LPLU D0\n"); - goto out; + if (hw->phy.ops.set_d0_lplu_state) { + ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); + if (ret_val) { + DEBUGOUT("Error Disabling LPLU D0\n"); + goto out; + } } /* Configure mdi-mdix settings */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); if (ret_val) goto out; @@ -652,7 +734,7 @@ e1000_copper_link_setup_igp(struct e1000_hw *hw) data |= IGP01E1000_PSCR_AUTO_MDIX; break; } - ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); if (ret_val) goto out; @@ -665,29 +747,29 @@ e1000_copper_link_setup_igp(struct e1000_hw *hw) */ if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { /* Disable SmartSpeed */ - ret_val = e1000_read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; /* Set auto Master/Slave resolution process */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); if (ret_val) goto out; data &= ~CR_1000T_MS_ENABLE; - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, data); + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); if (ret_val) goto out; } - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); if (ret_val) goto out; @@ -711,7 +793,7 @@ e1000_copper_link_setup_igp(struct e1000_hw *hw) default: break; } - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, data); + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); if (ret_val) goto out; } @@ -763,12 +845,12 @@ e1000_copper_link_autoneg(struct e1000_hw *hw) * Restart auto-negotiation by setting the Auto Neg Enable bit and * the Auto Neg Restart bit in the PHY control register. */ - ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &phy_ctrl); + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) goto out; phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, phy_ctrl); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) goto out; @@ -777,7 +859,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw) * check at a later time (for example, callback routine). */ if (phy->autoneg_wait_to_complete) { - ret_val = e1000_wait_autoneg(hw); + ret_val = hw->mac.ops.wait_autoneg(hw); if (ret_val) { DEBUGOUT("Error while waiting for " "autoneg to complete\n"); @@ -785,7 +867,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw) } } - hw->mac.get_link_status = TRUE; + hw->mac.get_link_status = true; out: return (ret_val); @@ -813,14 +895,14 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw) phy->autoneg_advertised &= phy->autoneg_mask; /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); + ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); if (ret_val) goto out; if (phy->autoneg_mask & ADVERTISE_1000_FULL) { /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = e1000_read_phy_reg(hw, - PHY_1000T_CTRL, &mii_1000t_ctrl_reg); + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, + &mii_1000t_ctrl_reg); if (ret_val) goto out; } @@ -871,9 +953,8 @@ 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) { @@ -899,7 +980,7 @@ 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 @@ -941,14 +1022,14 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw) goto out; } - ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); + ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); if (ret_val) goto out; DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); if (ret_val) goto out; @@ -989,7 +1070,7 @@ e1000_setup_copper_link_generic(struct e1000_hw *hw) * depending on user settings. */ DEBUGOUT("Forcing Speed and Duplex\n"); - ret_val = e1000_phy_force_speed_duplex(hw); + ret_val = hw->phy.ops.force_speed_duplex(hw); if (ret_val) { DEBUGOUT("Error Forcing Speed and Duplex\n"); goto out; @@ -1037,13 +1118,13 @@ e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) DEBUGFUNC("e1000_phy_force_speed_duplex_igp"); - ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &phy_data); + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) goto out; e1000_phy_force_speed_duplex_setup(hw, &phy_data); - ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, phy_data); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) goto out; @@ -1051,14 +1132,14 @@ e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) * Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed and duplex are forced. */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); if (ret_val) goto out; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); if (ret_val) goto out; @@ -1076,9 +1157,8 @@ 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, @@ -1117,39 +1197,37 @@ e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed and duplex are forced. */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); - ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &phy_data); + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) goto out; e1000_phy_force_speed_duplex_setup(hw, &phy_data); - /* Reset the phy to commit changes. */ - phy_data |= MII_CR_RESET; - - ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, phy_data); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) goto out; - usec_delay(1); + /* Reset the phy to commit changes. */ + ret_val = hw->phy.ops.commit(hw); + if (ret_val) + goto out; 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; @@ -1158,7 +1236,7 @@ e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) * We didn't get link. * Reset the DSP and cross our fingers. */ - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x001d); if (ret_val) @@ -1169,15 +1247,13 @@ 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; } - ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; @@ -1187,7 +1263,7 @@ e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) * the reset value of 2.5MHz. */ phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; @@ -1195,12 +1271,12 @@ e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) * In addition, we must re-enable CRS on Tx for both half and full * duplex. */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); out: return (ret_val); @@ -1227,7 +1303,7 @@ 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); @@ -1288,18 +1364,21 @@ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; + s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_set_d3_lplu_state_generic"); - ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); + if (!(hw->phy.ops.read_reg)) + goto out; + + ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) goto out; if (!active) { data &= ~IGP02E1000_PM_D3_LPLU; - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) @@ -1311,27 +1390,27 @@ e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1000_read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1000_read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) @@ -1341,21 +1420,21 @@ 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 = e1000_write_phy_reg(hw, + 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 = e1000_read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1000_write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); } @@ -1365,7 +1444,7 @@ out: } /* - * e1000_check_downshift_generic - Checks whether a downshift in speed occured + * e1000_check_downshift_generic - Checks whether a downshift in speed occurred * @hw: pointer to the HW structure * * Success returns 0, Failure returns 1 @@ -1384,7 +1463,6 @@ e1000_check_downshift_generic(struct e1000_hw *hw) switch (phy->type) { case e1000_phy_m88: case e1000_phy_gg82563: - case e1000_phy_bm: offset = M88E1000_PHY_SPEC_STATUS; mask = M88E1000_PSSR_DOWNSHIFT; break; @@ -1396,15 +1474,15 @@ e1000_check_downshift_generic(struct e1000_hw *hw) break; default: /* speed downshift not supported */ - phy->speed_downgraded = FALSE; + phy->speed_downgraded = false; ret_val = E1000_SUCCESS; goto out; } - ret_val = e1000_read_phy_reg(hw, offset, &phy_data); + ret_val = phy->ops.read_reg(hw, offset, &phy_data); if (!ret_val) - phy->speed_downgraded = (phy_data & mask) ? TRUE : FALSE; + phy->speed_downgraded = (phy_data & mask) ? true : false; out: return (ret_val); @@ -1427,7 +1505,7 @@ e1000_check_polarity_m88(struct e1000_hw *hw) DEBUGFUNC("e1000_check_polarity_m88"); - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); if (!ret_val) phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) @@ -1459,7 +1537,7 @@ e1000_check_polarity_igp(struct e1000_hw *hw) * Polarity is determined based on the speed of * our connection. */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) goto out; @@ -1476,7 +1554,7 @@ e1000_check_polarity_igp(struct e1000_hw *hw) mask = IGP01E1000_PSSR_POLARITY_REVERSED; } - ret_val = e1000_read_phy_reg(hw, offset, &data); + ret_val = phy->ops.read_reg(hw, offset, &data); if (!ret_val) phy->cable_polarity = (data & mask) @@ -1488,7 +1566,7 @@ out: } /* - * e1000_wait_autoneg_generic - Wait for auto-neg compeletion + * e1000_wait_autoneg_generic - Wait for auto-neg completion * @hw: pointer to the HW structure * * Waits for auto-negotiation to complete or for the auto-negotiation time @@ -1502,12 +1580,15 @@ e1000_wait_autoneg_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_wait_autoneg_generic"); + if (!(hw->phy.ops.read_reg)) + return (E1000_SUCCESS); + /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_AUTONEG_COMPLETE) @@ -1540,16 +1621,19 @@ e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, DEBUGFUNC("e1000_phy_has_link_generic"); + if (!(hw->phy.ops.read_reg)) + return (E1000_SUCCESS); + for (i = 0; i < iterations; i++) { /* * Some PHYs require the PHY_STATUS register to be read * twice due to the link bit being sticky. No harm doing * it across the board. */ - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_LINK_STATUS) @@ -1560,7 +1644,7 @@ e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, usec_delay(usec_interval); } - *success = (i < iterations) ? TRUE : FALSE; + *success = (i < iterations) ? true : false; return (ret_val); } @@ -1589,16 +1673,21 @@ e1000_get_cable_length_m88(struct e1000_hw *hw) DEBUGFUNC("e1000_get_cable_length_m88"); - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) goto out; 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); @@ -1610,8 +1699,8 @@ out: * * The automatic gain control (agc) normalizes the amplitude of the * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which reperesent the - * cobination of course and fine gain value, the value can be put + * 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. */ @@ -1633,13 +1722,13 @@ e1000_get_cable_length_igp_2(struct e1000_hw *hw) /* Read the AGC registers for all channels */ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { - ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data); + ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); if (ret_val) goto out; /* * Getting bits 15:9, which represent the combination of - * course and fine gain values. The result is a number + * coarse and fine gain values. The result is a number * that can be put into the lookup table to obtain the * approximate cable length. */ @@ -1715,30 +1804,29 @@ e1000_get_phy_info_m88(struct e1000_hw *hw) goto out; } - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) 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) goto out; - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) goto out; - phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? TRUE : FALSE; + phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { - ret_val = e1000_get_cable_length(hw); + ret_val = hw->phy.ops.get_cable_length(hw); if (ret_val) goto out; - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); if (ret_val) goto out; @@ -1789,25 +1877,25 @@ e1000_get_phy_info_igp(struct e1000_hw *hw) goto out; } - phy->polarity_correction = TRUE; + phy->polarity_correction = true; ret_val = e1000_check_polarity_igp(hw); if (ret_val) goto out; - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) goto out; - phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? TRUE : FALSE; + phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? true : false; if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { - ret_val = e1000_get_cable_length(hw); + ret_val = hw->phy.ops.get_cable_length(hw); if (ret_val) goto out; - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); if (ret_val) goto out; @@ -1838,17 +1926,20 @@ out: s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw) { - s32 ret_val; + s32 ret_val = E1000_SUCCESS; u16 phy_ctrl; DEBUGFUNC("e1000_phy_sw_reset_generic"); - ret_val = e1000_read_phy_reg(hw, PHY_CONTROL, &phy_ctrl); + if (!(hw->phy.ops.read_reg)) + goto out; + + ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) goto out; phy_ctrl |= MII_CR_RESET; - ret_val = e1000_write_phy_reg(hw, PHY_CONTROL, phy_ctrl); + ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) goto out; @@ -1865,24 +1956,24 @@ out: * Verify the reset block is not blocking us from resetting. Acquire * 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 relase the semaphore (if necessary). + * reset and release the semaphore (if necessary). */ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; + s32 ret_val = E1000_SUCCESS; u32 ctrl; DEBUGFUNC("e1000_phy_hw_reset_generic"); - ret_val = e1000_check_reset_block(hw); + ret_val = phy->ops.check_reset_block(hw); if (ret_val) { ret_val = E1000_SUCCESS; goto out; } - ret_val = e1000_acquire_phy(hw); + ret_val = phy->ops.acquire(hw); if (ret_val) goto out; @@ -1897,9 +1988,9 @@ e1000_phy_hw_reset_generic(struct e1000_hw *hw) usec_delay(150); - e1000_release_phy(hw); + phy->ops.release(hw); - ret_val = e1000_get_phy_cfg_done(hw); + ret_val = phy->ops.get_cfg_done(hw); out: return (ret_val); @@ -1916,77 +2007,13 @@ s32 e1000_get_cfg_done_generic(struct e1000_hw *hw) { DEBUGFUNC("e1000_get_cfg_done_generic"); - UNREFERENCED_PARAMETER(hw); + UNREFERENCED_1PARAMETER(hw); msec_delay_irq(10); return (E1000_SUCCESS); } -/* Internal function pointers */ - -/* - * e1000_get_phy_cfg_done - Generic PHY configuration done - * @hw: pointer to the HW structure - * - * Return success if silicon family did not implement a family specific - * get_cfg_done function. - */ -static s32 -e1000_get_phy_cfg_done(struct e1000_hw *hw) -{ - if (hw->func.get_cfg_done) - return (hw->func.get_cfg_done(hw)); - - return (E1000_SUCCESS); -} - -/* - * e1000_release_phy - Generic release PHY - * @hw: pointer to the HW structure - * - * Return if silicon family does not require a semaphore when accessing the - * PHY. - */ -static void -e1000_release_phy(struct e1000_hw *hw) -{ - if (hw->func.release_phy) - hw->func.release_phy(hw); -} - -/* - * e1000_acquire_phy - Generic acquire PHY - * @hw: pointer to the HW structure - * - * Return success if silicon family does not require a semaphore when - * accessing the PHY. - */ -static s32 -e1000_acquire_phy(struct e1000_hw *hw) -{ - if (hw->func.acquire_phy) - return (hw->func.acquire_phy(hw)); - - return (E1000_SUCCESS); -} - -/* - * e1000_phy_force_speed_duplex - Generic force PHY speed/duplex - * @hw: pointer to the HW structure - * - * When the silicon family has not implemented a forced speed/duplex - * function for the PHY, simply return (E1000_SUCCESS). - */ -s32 -e1000_phy_force_speed_duplex(struct e1000_hw *hw) -{ - if (hw->func.force_speed_duplex) - return (hw->func.force_speed_duplex(hw)); - - return (E1000_SUCCESS); -} - /* * e1000_phy_init_script_igp3 - Inits the IGP3 PHY * @hw: pointer to the HW structure @@ -2000,75 +2027,75 @@ e1000_phy_init_script_igp3(struct e1000_hw *hw) /* PHY init IGP 3 */ /* Enable rise/fall, 10-mode work in class-A */ - (void) e1000_write_phy_reg(hw, 0x2F5B, 0x9018); + (void) hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); /* Remove all caps from Replica path filter */ - (void) e1000_write_phy_reg(hw, 0x2F52, 0x0000); + (void) hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); /* Bias trimming for ADC, AFE and Driver (Default) */ - (void) e1000_write_phy_reg(hw, 0x2FB1, 0x8B24); + (void) hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); /* Increase Hybrid poly bias */ - (void) e1000_write_phy_reg(hw, 0x2FB2, 0xF8F0); - /* Add 4% to Tx amplitude in Giga mode */ - (void) e1000_write_phy_reg(hw, 0x2010, 0x10B0); + (void) hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); + /* Add 4% to Tx amplitude in Gig mode */ + (void) hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); /* Disable trimming (TTT) */ - (void) e1000_write_phy_reg(hw, 0x2011, 0x0000); + (void) hw->phy.ops.write_reg(hw, 0x2011, 0x0000); /* Poly DC correction to 94.6% + 2% for all channels */ - (void) e1000_write_phy_reg(hw, 0x20DD, 0x249A); + (void) hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); /* ABS DC correction to 95.9% */ - (void) e1000_write_phy_reg(hw, 0x20DE, 0x00D3); + (void) hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); /* BG temp curve trim */ - (void) e1000_write_phy_reg(hw, 0x28B4, 0x04CE); + (void) hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); /* Increasing ADC OPAMP stage 1 currents to max */ - (void) e1000_write_phy_reg(hw, 0x2F70, 0x29E4); + (void) hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); /* Force 1000 ( required for enabling PHY regs configuration) */ - (void) e1000_write_phy_reg(hw, 0x0000, 0x0140); + (void) hw->phy.ops.write_reg(hw, 0x0000, 0x0140); /* Set upd_freq to 6 */ - (void) e1000_write_phy_reg(hw, 0x1F30, 0x1606); + (void) hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); /* Disable NPDFE */ - (void) e1000_write_phy_reg(hw, 0x1F31, 0xB814); + (void) hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); /* Disable adaptive fixed FFE (Default) */ - (void) e1000_write_phy_reg(hw, 0x1F35, 0x002A); + (void) hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); /* Enable FFE hysteresis */ - (void) e1000_write_phy_reg(hw, 0x1F3E, 0x0067); + (void) hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); /* Fixed FFE for short cable lengths */ - (void) e1000_write_phy_reg(hw, 0x1F54, 0x0065); + (void) hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); /* Fixed FFE for medium cable lengths */ - (void) e1000_write_phy_reg(hw, 0x1F55, 0x002A); + (void) hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); /* Fixed FFE for long cable lengths */ - (void) e1000_write_phy_reg(hw, 0x1F56, 0x002A); + (void) hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); /* Enable Adaptive Clip Threshold */ - (void) e1000_write_phy_reg(hw, 0x1F72, 0x3FB0); + (void) hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); /* AHT reset limit to 1 */ - (void) e1000_write_phy_reg(hw, 0x1F76, 0xC0FF); + (void) hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); /* Set AHT master delay to 127 msec */ - (void) e1000_write_phy_reg(hw, 0x1F77, 0x1DEC); + (void) hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); /* Set scan bits for AHT */ - (void) e1000_write_phy_reg(hw, 0x1F78, 0xF9EF); + (void) hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); /* Set AHT Preset bits */ - (void) e1000_write_phy_reg(hw, 0x1F79, 0x0210); + (void) hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); /* Change integ_factor of channel A to 3 */ - (void) e1000_write_phy_reg(hw, 0x1895, 0x0003); + (void) hw->phy.ops.write_reg(hw, 0x1895, 0x0003); /* Change prop_factor of channels BCD to 8 */ - (void) e1000_write_phy_reg(hw, 0x1796, 0x0008); + (void) hw->phy.ops.write_reg(hw, 0x1796, 0x0008); /* Change cg_icount + enable integbp for channels BCD */ - (void) e1000_write_phy_reg(hw, 0x1798, 0xD008); + (void) hw->phy.ops.write_reg(hw, 0x1798, 0xD008); /* * Change cg_icount + enable integbp + change prop_factor_master * to 8 for channel A */ - (void) e1000_write_phy_reg(hw, 0x1898, 0xD918); + (void) hw->phy.ops.write_reg(hw, 0x1898, 0xD918); /* Disable AHT in Slave mode on channel A */ - (void) e1000_write_phy_reg(hw, 0x187A, 0x0800); + (void) hw->phy.ops.write_reg(hw, 0x187A, 0x0800); /* * Enable LPLU and disable AN to 1000 in non-D0a states, * Enable SPD+B2B */ - (void) e1000_write_phy_reg(hw, 0x0019, 0x008D); + (void) hw->phy.ops.write_reg(hw, 0x0019, 0x008D); /* Enable restart AN on an1000_dis change */ - (void) e1000_write_phy_reg(hw, 0x001B, 0x2080); + (void) hw->phy.ops.write_reg(hw, 0x001B, 0x2080); /* Enable wh_fifo read clock in 10/100 modes */ - (void) e1000_write_phy_reg(hw, 0x0014, 0x0045); + (void) hw->phy.ops.write_reg(hw, 0x0014, 0x0045); /* Restart AN, Speed selection is 1000 */ - (void) e1000_write_phy_reg(hw, 0x0000, 0x1340); + (void) hw->phy.ops.write_reg(hw, 0x0000, 0x1340); return (E1000_SUCCESS); } @@ -2079,10 +2106,10 @@ e1000_phy_init_script_igp3(struct e1000_hw *hw) * * Returns the phy type from the id. */ -e1000_phy_type +enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) { - e1000_phy_type phy_type = e1000_phy_unknown; + enum e1000_phy_type phy_type = e1000_phy_unknown; switch (phy_id) { case M88E1000_I_PHY_ID: @@ -2105,10 +2132,6 @@ e1000_get_phy_type_from_id(u32 phy_id) case IFE_C_E_PHY_ID: phy_type = e1000_phy_ife; break; - case BME1000_E_PHY_ID: - case BME1000_E_PHY_ID_R2: - phy_type = e1000_phy_bm; - break; default: phy_type = e1000_phy_unknown; break; @@ -2117,408 +2140,6 @@ e1000_get_phy_type_from_id(u32 phy_id) } /* - * e1000_determine_phy_address - Determines PHY address. - * @hw: pointer to the HW structure - * - * This uses a trial and error method to loop through possible PHY - * 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 ret_val = -E1000_ERR_PHY_TYPE; - u32 phy_addr = 0; - u32 i = 0; - e1000_phy_type phy_type = e1000_phy_unknown; - - do { - for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { - hw->phy.addr = phy_addr; - (void) 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 != e1000_phy_unknown) { - ret_val = E1000_SUCCESS; - break; - } - } - i++; - } while ((ret_val != E1000_SUCCESS) && (i < 100)); - - return (ret_val); -} - -/* - * e1000_get_phy_addr_for_bm_page - Retrieve PHY page address - * @page: page to access - * - * Returns the phy address for the page requested. - */ -static u32 -e1000_get_phy_addr_for_bm_page(u32 page, u32 reg) -{ - u32 phy_addr = 2; - - if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31)) - phy_addr = 1; - - return (phy_addr); -} - -/* - * e1000_write_phy_reg_bm - Write BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - */ -s32 -e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - u32 page_select = 0; - u32 page = offset >> IGP_PAGE_SHIFT; - u32 page_shift = 0; - - DEBUGFUNC("e1000_write_phy_reg_bm"); - - /* 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); - goto out; - } - - ret_val = e1000_acquire_phy(hw); - if (ret_val) - goto out; - - hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* - * Page select is register 31 for phy address 1 and 22 for - * phy address 2 and 3. Page select is shifted only for - * phy address 1. - */ - if (hw->phy.addr == 1) { - page_shift = IGP_PAGE_SHIFT; - page_select = IGP01E1000_PHY_PAGE_SELECT; - } else { - page_shift = 0; - page_select = BM_PHY_PAGE_SELECT; - } - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000_write_phy_reg_mdic(hw, page_select, - (page << page_shift)); - if (ret_val) { - e1000_release_phy(hw); - goto out; - } - } - - ret_val = e1000_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - - e1000_release_phy(hw); - -out: - return (ret_val); -} - -/* - * e1000_read_phy_reg_bm - Read BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - */ -s32 -e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - u32 page_select = 0; - u32 page = offset >> IGP_PAGE_SHIFT; - u32 page_shift = 0; - - DEBUGFUNC("e1000_write_phy_reg_bm"); - - /* 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); - goto out; - } - - ret_val = e1000_acquire_phy(hw); - if (ret_val) - goto out; - - hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* - * Page select is register 31 for phy address 1 and 22 for - * phy address 2 and 3. Page select is shifted only for - * phy address 1. - */ - if (hw->phy.addr == 1) { - page_shift = IGP_PAGE_SHIFT; - page_select = IGP01E1000_PHY_PAGE_SELECT; - } else { - page_shift = 0; - page_select = BM_PHY_PAGE_SELECT; - } - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000_write_phy_reg_mdic(hw, page_select, - (page << page_shift)); - if (ret_val) { - e1000_release_phy(hw); - goto out; - } - } - - ret_val = e1000_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - e1000_release_phy(hw); - -out: - return (ret_val); -} - -/* - * e1000_read_phy_reg_bm2 - Read BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - */ -s32 -e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - u16 page = (u16)(offset >> IGP_PAGE_SHIFT); - - DEBUGFUNC("e1000_write_phy_reg_bm2"); - - /* 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); - goto out; - } - - ret_val = e1000_acquire_phy(hw); - if (ret_val) - goto out; - - hw->phy.addr = 1; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000_write_phy_reg_mdic(hw, - BM_PHY_PAGE_SELECT, - page); - - if (ret_val) { - e1000_release_phy(hw); - goto out; - } - } - - ret_val = e1000_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - e1000_release_phy(hw); - -out: - return (ret_val); -} - -/* - * e1000_write_phy_reg_bm2 - Write BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - */ -s32 -e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - u16 page = (u16)(offset >> IGP_PAGE_SHIFT); - - DEBUGFUNC("e1000_write_phy_reg_bm2"); - - /* 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); - goto out; - } - - ret_val = e1000_acquire_phy(hw); - if (ret_val) - goto out; - - hw->phy.addr = 1; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000_write_phy_reg_mdic(hw, - BM_PHY_PAGE_SELECT, - page); - - if (ret_val) { - e1000_release_phy(hw); - goto out; - } - } - - ret_val = e1000_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - - e1000_release_phy(hw); - -out: - return (ret_val); -} - -/* - * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register - * @hw: pointer to the HW structure - * @offset: register offset to be read or written - * @data: pointer to the data to read or write - * @read: determines if operation is read or write - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. Note that procedure to read the wakeup - * registers are different. It works as such: - * 1) Set page 769, register 17, bit 2 = 1 - * 2) Set page to 800 for host (801 if we were manageability) - * 3) Write the address using the address opcode (0x11) - * 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) -{ - s32 ret_val; - u16 reg = ((u16)offset) & PHY_REG_MASK; - u16 phy_reg = 0; - u8 phy_acquired = 1; - - DEBUGFUNC("e1000_read_phy_wakeup_reg_bm"); - - ret_val = e1000_acquire_phy(hw); - if (ret_val) { - DEBUGOUT("Couldnt acquire PHY\n"); - phy_acquired = 0; - goto out; - } - - /* All operations in this function are phy address 1 */ - hw->phy.addr = 1; - - /* Set page 769 */ - (void) e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); - - ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); - if (ret_val) { - DEBUGOUT("Couldnt read PHY page 769\n"); - goto out; - } - - /* First clear bit 4 to avoid a power state change */ - phy_reg &= ~(BM_WUC_HOST_WU_BIT); - ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); - if (ret_val) { - DEBUGOUT("Couldnt clear PHY page 769 bit 4\n"); - goto out; - } - - /* Write bit 2 = 1, and clear bit 4 to 769_17 */ - ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, - phy_reg | BM_WUC_ENABLE_BIT); - if (ret_val) { - DEBUGOUT("Couldnt write PHY page 769 bit 2\n"); - goto out; - } - - /* Select page 800 */ - ret_val = e1000_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (BM_WUC_PAGE << IGP_PAGE_SHIFT)); - - /* Write the page 800 offset value using opcode 0x11 */ - ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); - if (ret_val) { - DEBUGOUT("Couldnt write address opcode to page 800\n"); - goto out; - } - - if (read) { - /* Read the page 800 value using opcode 0x12 */ - ret_val = e1000_read_phy_reg_mdic(hw, - BM_WUC_DATA_OPCODE, - data); - } else { - /* Read the page 800 value using opcode 0x12 */ - ret_val = e1000_write_phy_reg_mdic(hw, - BM_WUC_DATA_OPCODE, - *data); - } - - if (ret_val) { - DEBUGOUT("Couldnt read data value from page 800\n"); - goto out; - } - - /* - * Restore 769_17.2 to its original value - * Set page 769 - */ - (void) e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); - - /* Clear 769_17.2 */ - ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); - if (ret_val) { - DEBUGOUT("Couldnt clear PHY page 769 bit 2\n"); - goto out; - } - -out: - if (phy_acquired == 1) - e1000_release_phy(hw); - return (ret_val); -} - -/* * e1000_power_up_phy_copper - Restore copper link in case of PHY power down * @hw: pointer to the HW structure * @@ -2532,9 +2153,9 @@ e1000_power_up_phy_copper(struct e1000_hw *hw) u16 mii_reg = 0; /* The PHY will retain its settings across a power down/up cycle */ - (void) e1000_read_phy_reg(hw, PHY_CONTROL, &mii_reg); + (void) hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); mii_reg &= ~MII_CR_POWER_DOWN; - (void) e1000_write_phy_reg(hw, PHY_CONTROL, mii_reg); + (void) hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); } /* @@ -2551,8 +2172,8 @@ e1000_power_down_phy_copper(struct e1000_hw *hw) u16 mii_reg = 0; /* The PHY will retain its settings across a power down/up cycle */ - (void) e1000_read_phy_reg(hw, PHY_CONTROL, &mii_reg); + (void) hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); mii_reg |= MII_CR_POWER_DOWN; - (void) e1000_write_phy_reg(hw, PHY_CONTROL, mii_reg); + (void) hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); msec_delay(1); } diff --git a/usr/src/uts/common/io/igb/igb_phy.h b/usr/src/uts/common/io/igb/igb_phy.h index 2be5683e21..6a2cb12716 100644 --- a/usr/src/uts/common/io/igb/igb_phy.h +++ b/usr/src/uts/common/io/igb/igb_phy.h @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,41 +22,29 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.39 v2007-12-10_dragonlake5 */ +/* IntelVersion: 1.55 v2008-10-7 */ #ifndef _IGB_PHY_H #define _IGB_PHY_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif - -typedef enum { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -} e1000_ms_type; - -typedef enum { - e1000_smart_speed_default = 0, - e1000_smart_speed_on, - e1000_smart_speed_off -} e1000_smart_speed; - +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); +s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active); +s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_check_downshift_generic(struct e1000_hw *hw); s32 e1000_check_polarity_m88(struct e1000_hw *hw); s32 e1000_check_polarity_igp(struct e1000_hw *hw); s32 e1000_check_reset_block_generic(struct e1000_hw *hw); s32 e1000_copper_link_autoneg(struct e1000_hw *hw); -s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw); s32 e1000_copper_link_setup_igp(struct e1000_hw *hw); s32 e1000_copper_link_setup_m88(struct e1000_hw *hw); s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw); @@ -71,7 +59,6 @@ s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw); void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw); s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw); -s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); @@ -85,14 +72,7 @@ s32 e1000_phy_reset_dsp(struct e1000_hw *hw); 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); -e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); -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); +enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); void e1000_power_up_phy_copper(struct e1000_hw *hw); void e1000_power_down_phy_copper(struct e1000_hw *hw); s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); @@ -113,18 +93,6 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); #define IGP_PAGE_SHIFT 5 #define PHY_REG_MASK 0x1F -#define BM_WUC_PAGE 800 -#define BM_WUC_ADDRESS_OPCODE 0x11 -#define BM_WUC_DATA_OPCODE 0x12 -#define BM_WUC_ENABLE_PAGE 769 -#define BM_WUC_ENABLE_REG 17 -#define BM_WUC_ENABLE_BIT (1 << 2) -#define BM_WUC_HOST_WU_BIT (1 << 4) - -/* BM PHY Copper Specific Control 1 */ -#define BM_CS_CTRL1 16 -#define BM_CR_CTRL1_ENERGY_DETECT 0x0300 /* Enable Energy Detect */ - #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 #define IGP01E1000_PHY_POLARITY_MASK 0x0078 diff --git a/usr/src/uts/common/io/igb/igb_regs.h b/usr/src/uts/common/io/igb/igb_regs.h index db09340c0c..588817d60b 100644 --- a/usr/src/uts/common/io/igb/igb_regs.h +++ b/usr/src/uts/common/io/igb/igb_regs.h @@ -1,7 +1,7 @@ /* * CDDL HEADER START * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. @@ -22,17 +22,15 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.41 v2007-12-10_dragonlake5 */ +/* IntelVersion: 1.61 v2008-10-7 */ #ifndef _IGB_REGS_H #define _IGB_REGS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -48,6 +46,7 @@ extern "C" { #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 */ @@ -58,7 +57,6 @@ extern "C" { #define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ #define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ #define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ -#define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ #define E1000_RCTL 0x00100 /* Rx Control - RW */ #define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ #define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ @@ -70,6 +68,9 @@ extern "C" { #define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */ #define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */ #define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */ +#define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */ +#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */ +#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */ #define E1000_TCTL 0x00400 /* Tx Control - RW */ #define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */ #define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */ @@ -95,6 +96,12 @@ extern "C" { #define E1000_SWDSTS 0x01044 /* SW Device Status - RW */ #define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */ #define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */ +#define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */ +#define E1000_ICR_V2 0x01500 /* Interrupt Cause - new location - RC */ +#define E1000_ICS_V2 0x01504 /* Interrupt Cause Set - new location - WO */ +#define E1000_IMS_V2 0x01508 /* Interrupt Mask Set/Read - new location - RW */ +#define E1000_IMC_V2 0x0150C /* Interrupt Mask Clear - new location - WO */ +#define E1000_IAM_V2 0x01510 /* Interrupt Ack Auto Mask - new location - RW */ #define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ @@ -108,6 +115,13 @@ extern "C" { #define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */ #define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */ #define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */ +#define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */ +#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ +#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 */ /* @@ -118,67 +132,75 @@ extern "C" { * 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_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_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_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) (0x05400 + ((_i) * 8)) -#define E1000_RAH(_i) (0x05404 + ((_i) * 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)) #define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8)) #define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8)) #define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8)) +#define E1000_PBSLAC 0x03100 /* Packet Buffer Slave Access Control */ +/* Packet Buffer DWORD (_n) */ +#define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) +#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ #define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ #define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ #define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ @@ -190,6 +212,9 @@ extern "C" { #define E1000_TDPURD 0x03588 /* DMA Tx Descriptor uC Data Read - RW */ #define E1000_TDPUCTL 0x0358C /* DMA Tx Descriptor uC Control - RW */ #define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */ +#define E1000_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */ +#define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */ +#define E1000_DTXMXSZRQ 0x03540 /* DMA Tx Max Total Allow Size Requests - RW */ #define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ #define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ #define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ @@ -252,21 +277,94 @@ extern "C" { #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 */ -/* Interrupt Cause Rx Packet Timer Expire Count */ -#define E1000_ICRXPTC 0x04104 -/* Interrupt Cause Rx Absolute Timer Expire Count */ -#define E1000_ICRXATC 0x04108 -/* Interrupt Cause Tx Packet Timer Expire Count */ -#define E1000_ICTXPTC 0x0410C -/* Interrupt Cause Tx Absolute Timer Expire Count */ -#define E1000_ICTXATC 0x04110 +#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 */ -/* Interrupt Cause Tx Queue Minimum Threshold Count */ -#define E1000_ICTXQMTC 0x0411C -/* Interrupt Cause Rx Descriptor Minimum Threshold Count */ -#define E1000_ICRXDMTC 0x04120 +#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 */ +/* LinkSec Tx Untagged Packet Count - OutPktsUntagged */ +#define E1000_LSECTXUT 0x04300 +/* LinkSec Encrypted Tx Packets Count - OutPktsEncrypted */ +#define E1000_LSECTXPKTE 0x04304 +/* LinkSec Protected Tx Packet Count - OutPktsProtected */ +#define E1000_LSECTXPKTP 0x04308 +/* LinkSec Encrypted Tx Octets Count - OutOctetsEncrypted */ +#define E1000_LSECTXOCTE 0x0430C +/* LinkSec Protected Tx Octets Count - OutOctetsProtected */ +#define E1000_LSECTXOCTP 0x04310 +/* LinkSec Untagged non-Strict Rx Packet Count - InPktsUntagged/InPktsNoTag */ +#define E1000_LSECRXUT 0x04314 +/* LinkSec Rx Octets Decrypted Count - InOctetsDecrypted */ +#define E1000_LSECRXOCTD 0x0431C +/* LinkSec Rx Octets Validated - InOctetsValidated */ +#define E1000_LSECRXOCTV 0x04320 +/* LinkSec Rx Bad Tag - InPktsBadTag */ +#define E1000_LSECRXBAD 0x04324 +/* LinkSec Rx Packet No SCI Count - InPktsNoSci */ +#define E1000_LSECRXNOSCI 0x04328 +/* LinkSec Rx Packet Unknown SCI Count - InPktsUnknownSci */ +#define E1000_LSECRXUNSCI 0x0432C +/* LinkSec Rx Unchecked Packets Count - InPktsUnchecked */ +#define E1000_LSECRXUNCH 0x04330 +/* LinkSec Rx Delayed Packet Count - InPktsDelayed */ +#define E1000_LSECRXDELAY 0x04340 +/* LinkSec Rx Late Packets Count - InPktsLate */ +#define E1000_LSECRXLATE 0x04350 +/* LinkSec Rx Packet OK Count - InPktsOk */ +#define E1000_LSECRXOK(_n) (0x04360 + (0x04 * (_n))) +/* LinkSec Rx Invalid Count - InPktsInvalid */ +#define E1000_LSECRXINV(_n) (0x04380 + (0x04 * (_n))) +/* LinkSec Rx Not Valid Count - InPktsNotValid */ +#define E1000_LSECRXNV(_n) (0x043A0 + (0x04 * (_n))) +/* LinkSec Rx Unused SA Count - InPktsUnusedSa */ +#define E1000_LSECRXUNSA 0x043C0 +/* LinkSec Rx Not Using SA Count - InPktsNotUsingSa */ +#define E1000_LSECRXNUSA 0x043D0 +/* LinkSec Tx Capabilities Register - RO */ +#define E1000_LSECTXCAP 0x0B000 +/* LinkSec Rx Capabilities Register - RO */ +#define E1000_LSECRXCAP 0x0B300 +#define E1000_LSECTXCTRL 0x0B004 /* LinkSec Tx Control - RW */ +#define E1000_LSECRXCTRL 0x0B304 /* LinkSec Rx Control - RW */ +#define E1000_LSECTXSCL 0x0B008 /* LinkSec Tx SCI Low - RW */ +#define E1000_LSECTXSCH 0x0B00C /* LinkSec Tx SCI High - RW */ +#define E1000_LSECTXSA 0x0B010 /* LinkSec Tx SA0 - RW */ +#define E1000_LSECTXPN0 0x0B018 /* LinkSec Tx SA PN 0 - RW */ +#define E1000_LSECTXPN1 0x0B01C /* LinkSec Tx SA PN 1 - RW */ +#define E1000_LSECRXSCL 0x0B3D0 /* LinkSec Rx SCI Low - RW */ +#define E1000_LSECRXSCH 0x0B3E0 /* LinkSec Rx SCI High - RW */ +/* LinkSec Tx 128-bit Key 0 - WO */ +#define E1000_LSECTXKEY0(_n) (0x0B020 + (0x04 * (_n))) +/* LinkSec Tx 128-bit Key 1 - WO */ +#define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n))) +/* LinkSec Rx SAs - RW */ +#define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) +/* LinkSec Rx SAs - RW */ +#define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) +/* + * LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit + * key - RW. + */ +#define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m))) + +#define E1000_SSVPC 0x041A0 /* Switch Security Violation Packet Count */ +#define E1000_IPSCTRL 0xB430 /* IpSec Control Register */ +#define E1000_IPSRXCMD 0x0B408 /* IPSec Rx Command Register - RW */ +#define E1000_IPSRXIDX 0x0B400 /* IPSec Rx Index - RW */ +/* IPSec Rx IPv4/v6 Address - RW */ +#define E1000_IPSRXIPADDR(_n) (0x0B420+ (0x04 * (_n))) +/* IPSec Rx 128-bit Key - RW */ +#define E1000_IPSRXKEY(_n) (0x0B410 + (0x04 * (_n))) +#define E1000_IPSRXSALT 0x0B404 /* IPSec Rx Salt - RW */ +#define E1000_IPSRXSPI 0x0B40C /* IPSec Rx SPI - RW */ +/* IPSec Tx 128-bit Key - RW */ +#define E1000_IPSTXKEY(_n) (0x0B460 + (0x04 * (_n))) +#define E1000_IPSTXSALT 0x0B454 /* IPSec Tx Salt - RW */ +#define E1000_IPSTXIDX 0x0B450 /* IPSec Tx SA IDX - RW */ #define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */ #define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ #define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */ @@ -287,17 +385,17 @@ extern "C" { #define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */ #define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ #define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */ -/* Link Partner Ability Next Page - RW */ -#define E1000_PCS_LPABNP 0x04224 -/* 1GSTAT Code Violation Packet Count - RW */ -#define E1000_1GSTAT_RCV 0x04228 +#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */ +#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Packet Count - RW */ #define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ #define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */ #define E1000_RFCTL 0x05008 /* Receive Filter Control */ #define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ #define E1000_RA 0x05400 /* Receive Address - RW Array */ +/* 2nd half of receive address array - RW Array */ +#define E1000_RA2 0x054E0 #define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -#define E1000_VMD_CTL 0x0581C /* VMDq Control - RW */ +#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */ #define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */ #define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */ #define E1000_WUC 0x05800 /* Wakeup Control - RW */ @@ -314,6 +412,10 @@ extern "C" { #define E1000_HOST_IF 0x08800 /* Host Interface */ #define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ #define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ +/* Flexible Host Filter Table */ +#define E1000_FHFT(_n) (0x09000 + (_n * 0x100)) +/* Ext Flexible Host Filter Table */ +#define E1000_FHFT_EXT(_n) (0x09A00 + (_n * 0x100)) #define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ #define E1000_MDPHYA 0x0003C /* PHY address - RW */ @@ -335,7 +437,7 @@ extern "C" { #define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */ #define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */ #define E1000_FFLT_DBG 0x05F04 /* Debug Register */ -#define E1000_HICR 0x08F00 /* Host Inteface Control */ +#define E1000_HICR 0x08F00 /* Host Interface Control */ /* RSS registers */ #define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */ @@ -361,6 +463,76 @@ extern "C" { #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) #define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ #define E1000_RSSIR 0x05868 /* RSS Interrupt Request */ +/* VT Registers */ +#define E1000_SWPBS 0x03004 /* Switch Packet Buffer Size - RW */ +#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */ +#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */ +#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */ +#define E1000_VFRE 0x00C8C /* VF Receive Enables */ +#define E1000_VFTE 0x00C90 /* VF Transmit Enables */ +#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */ +#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */ +#define E1000_VLVF 0x05D00 /* VLAN Virtual Machine Filter - RW */ +#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */ +#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */ +#define E1000_IOVTCL 0x05BBC /* IOV Control Register */ +#define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */ +/* These act per VF so an array friendly macro is used */ +#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n))) +#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n))) +#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n))) +#define E1000_VFVMBMEM(_n) (0x00800 + (_n)) +#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n))) + +/* Filtering Registers */ +#define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */ +#define E1000_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */ +#define E1000_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */ +#define E1000_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */ +#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ +#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ + +#define E1000_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */ +#define E1000_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */ +#define E1000_RTRPCS 0x2474 /* Rx packet plane control and status */ +#define E1000_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */ +#define E1000_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */ +/* Tx Desc plane TC Rate-scheduler config */ +#define E1000_RTTDTCRC(_n) (0x3610 + ((_n) * 4)) +/* Tx Packet plane TC Rate-Scheduler Config */ +#define E1000_RTTPTCRC(_n) (0x3480 + ((_n) * 4)) +/* Rx Packet plane TC Rate-Scheduler Config */ +#define E1000_RTRPTCRC(_n) (0x2480 + ((_n) * 4)) +/* Tx Desc Plane TC Rate-Scheduler Status */ +#define E1000_RTTDTCRS(_n) (0x3630 + ((_n) * 4)) +/* Tx Desc Plane TC Rate-Scheduler MMW */ +#define E1000_RTTDTCRM(_n) (0x3650 + ((_n) * 4)) +/* Tx Packet plane TC Rate-Scheduler Status */ +#define E1000_RTTPTCRS(_n) (0x34A0 + ((_n) * 4)) +/* Tx Packet plane TC Rate-scheduler MMW */ +#define E1000_RTTPTCRM(_n) (0x34C0 + ((_n) * 4)) +/* Rx Packet plane TC Rate-Scheduler Status */ +#define E1000_RTRPTCRS(_n) (0x24A0 + ((_n) * 4)) +/* Rx Packet plane TC Rate-Scheduler MMW */ +#define E1000_RTRPTCRM(_n) (0x24C0 + ((_n) * 4)) +/* Tx Desc plane VM Rate-Scheduler MMW */ +#define E1000_RTTDVMRM(_n) (0x3670 + ((_n) * 4)) +/* Tx BCN Rate-Scheduler MMW */ +#define E1000_RTTBCNRM(_n) (0x3690 + ((_n) * 4)) +#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */ +#define E1000_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */ +#define E1000_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */ +#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */ +#define E1000_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */ +#define E1000_RTTBCNCR 0xB200 /* Tx BCN Control Register */ +#define E1000_RTTBCNTG 0x35A4 /* Tx BCN Tagging */ +#define E1000_RTTBCNCP 0xB208 /* Tx BCN Congestion point */ +#define E1000_RTRBCNCR 0xB20C /* Rx BCN Control Register */ +#define E1000_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */ +#define E1000_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */ +#define E1000_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */ +#define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */ +#define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */ #ifdef __cplusplus } diff --git a/usr/src/uts/common/io/igb/igb_rx.c b/usr/src/uts/common/io/igb/igb_rx.c index acf15ed35c..d1f6368a8d 100644 --- a/usr/src/uts/common/io/igb/igb_rx.c +++ b/usr/src/uts/common/io/igb/igb_rx.c @@ -1,17 +1,19 @@ /* * CDDL HEADER START * + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. + * You can obtain a copy of the license at: + * http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * When using or redistributing this file, you may do so under the + * License only. No other modification of this header is permitted. + * * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] @@ -20,12 +22,8 @@ */ /* - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms of the CDDL. */ #include "igb_sw.h" @@ -68,13 +66,9 @@ igb_rx_recycle(caddr_t arg) * Using the recycled data buffer to generate a new mblk */ recycle_rcb->mp = desballoc((unsigned char *) - (recycle_rcb->rx_buf.address - IPHDR_ALIGN_ROOM), - (recycle_rcb->rx_buf.size + IPHDR_ALIGN_ROOM), + recycle_rcb->rx_buf.address, + recycle_rcb->rx_buf.size, 0, &recycle_rcb->free_rtn); - if (recycle_rcb->mp != NULL) { - recycle_rcb->mp->b_rptr += IPHDR_ALIGN_ROOM; - recycle_rcb->mp->b_wptr += IPHDR_ALIGN_ROOM; - } /* * Put the recycled rx control block into free list @@ -169,8 +163,8 @@ igb_rx_bind(igb_rx_ring_t *rx_ring, uint32_t index, uint32_t pkt_len) */ if (current_rcb->mp == NULL) { current_rcb->mp = desballoc((unsigned char *) - (current_rcb->rx_buf.address - IPHDR_ALIGN_ROOM), - (current_rcb->rx_buf.size + IPHDR_ALIGN_ROOM), + current_rcb->rx_buf.address, + current_rcb->rx_buf.size, 0, ¤t_rcb->free_rtn); /* * If it is failed to built a mblk using the current diff --git a/usr/src/uts/common/io/igb/igb_sw.h b/usr/src/uts/common/io/igb/igb_sw.h index a69ba3bb77..4cd1045c16 100644 --- a/usr/src/uts/common/io/igb/igb_sw.h +++ b/usr/src/uts/common/io/igb/igb_sw.h @@ -1,17 +1,19 @@ /* * CDDL HEADER START * + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. + * You can obtain a copy of the license at: + * http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * When using or redistributing this file, you may do so under the + * License only. No other modification of this header is permitted. + * * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] @@ -20,12 +22,8 @@ */ /* - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms of the CDDL. */ #ifndef _IGB_SW_H @@ -88,16 +86,25 @@ extern "C" { #define IGB_INTR_MSI 2 #define IGB_INTR_LEGACY 3 +#define IGB_ADAPTER_REGSET 1 /* mapping adapter registers */ +#define IGB_ADAPTER_MSIXTAB 4 /* mapping msi-x table */ + #define IGB_NO_POLL -1 #define IGB_NO_FREE_SLOT -1 #define MAX_NUM_UNICAST_ADDRESSES E1000_RAR_ENTRIES #define MAX_NUM_MULTICAST_ADDRESSES 256 -#define MAX_NUM_EITR 10 #define MAX_COOKIE 16 #define MIN_NUM_TX_DESC 2 /* + * Number of settings for interrupt throttle rate (ITR). There is one of + * these per msi-x vector and it needs to be the maximum of all silicon + * types supported by this driver. + */ +#define MAX_NUM_EITR 25 + +/* * Maximum values for user configurable parameters */ #define MAX_TX_RING_SIZE 4096 @@ -110,7 +117,6 @@ extern "C" { #define MAX_RX_INTR_ABS_DELAY 65535 #define MAX_TX_INTR_DELAY 65535 #define MAX_TX_INTR_ABS_DELAY 65535 -#define MAX_INTR_THROTTLING 65535 #define MAX_RX_COPY_THRESHOLD 9216 #define MAX_TX_COPY_THRESHOLD 9216 @@ -131,7 +137,6 @@ extern "C" { #define MIN_RX_INTR_ABS_DELAY 0 #define MIN_TX_INTR_DELAY 0 #define MIN_TX_INTR_ABS_DELAY 0 -#define MIN_INTR_THROTTLING 0 #define MIN_RX_COPY_THRESHOLD 0 #define MIN_TX_COPY_THRESHOLD 0 #define MIN_TX_RECYCLE_THRESHOLD MIN_NUM_TX_DESC @@ -141,8 +146,6 @@ extern "C" { /* * Default values for user configurable parameters */ -#define DEFAULT_TX_QUEUE_NUM 4 -#define DEFAULT_RX_QUEUE_NUM 4 #define DEFAULT_TX_RING_SIZE 512 #define DEFAULT_RX_RING_SIZE 512 #define DEFAULT_RX_GROUP_NUM 1 @@ -153,7 +156,6 @@ extern "C" { #define DEFAULT_RX_INTR_ABS_DELAY 0 #define DEFAULT_TX_INTR_DELAY 300 #define DEFAULT_TX_INTR_ABS_DELAY 0 -#define DEFAULT_INTR_THROTTLING 200 /* In unit of 256 nsec */ #define DEFAULT_RX_COPY_THRESHOLD 128 #define DEFAULT_TX_COPY_THRESHOLD 512 #define DEFAULT_TX_RECYCLE_THRESHOLD MAX_COOKIE @@ -337,6 +339,33 @@ typedef struct link_list { DDI_PROP_DONTPASS, (n), -1) +/* capability/feature flags */ +#define IGB_FLAG_HAS_DCA (1 << 0) /* has Direct Cache Access */ +#define IGB_FLAG_VMDQ_POOL (1 << 1) /* has vmdq capability */ +#define IGB_FLAG_NEED_CTX_IDX (1 << 2) /* context descriptor needs index */ + +/* function pointer for nic-specific functions */ +typedef void (*igb_nic_func_t)(struct igb *); + +/* adapter-specific info for each supported device type */ +typedef struct adapter_info { + /* limits */ + uint32_t max_rx_que_num; /* maximum number of rx queues */ + uint32_t min_rx_que_num; /* minimum number of rx queues */ + uint32_t def_rx_que_num; /* default number of rx queues */ + uint32_t max_tx_que_num; /* maximum number of tx queues */ + uint32_t min_tx_que_num; /* minimum number of tx queues */ + uint32_t def_tx_que_num; /* default number of tx queues */ + uint32_t max_intr_throttle; /* maximum interrupt throttle */ + uint32_t min_intr_throttle; /* minimum interrupt throttle */ + uint32_t def_intr_throttle; /* default interrupt throttle */ + /* function pointers */ + igb_nic_func_t enable_intr; /* enable adapter interrupts */ + igb_nic_func_t setup_msix; /* set up msi-x vectors */ + /* capabilities */ + uint32_t flags; /* capability flags */ +} adapter_info_t; + /* * Named Data (ND) Parameter Management Structure */ @@ -620,6 +649,8 @@ typedef struct igb { struct e1000_hw hw; struct igb_osdep osdep; + adapter_info_t *capab; /* adapter capabilities */ + uint32_t igb_state; link_state_t link_state; uint32_t link_speed; @@ -780,6 +811,9 @@ typedef struct igb_stat { * Function prototypes in e1000_osdep.c */ void e1000_enable_pciex_master(struct e1000_hw *); +void e1000_rar_clear(struct e1000_hw *hw, uint32_t); +void e1000_rar_set_vmdq(struct e1000_hw *hw, const uint8_t *, uint32_t, + uint32_t, uint8_t); /* * Function prototypes in igb_buf.c diff --git a/usr/src/uts/common/io/igb/igb_tx.c b/usr/src/uts/common/io/igb/igb_tx.c index 7b43bbad97..5b7883435e 100644 --- a/usr/src/uts/common/io/igb/igb_tx.c +++ b/usr/src/uts/common/io/igb/igb_tx.c @@ -1,17 +1,19 @@ /* * CDDL HEADER START * + * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. + * You can obtain a copy of the license at: + * http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * When using or redistributing this file, you may do so under the + * License only. No other modification of this header is permitted. + * * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] @@ -20,12 +22,8 @@ */ /* - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms of the CDDL. */ #include "igb_sw.h" @@ -682,6 +680,7 @@ igb_tx_fill_ring(igb_tx_ring_t *tx_ring, link_list_t *pending_list, union e1000_adv_tx_desc *tbd, *first_tbd; tx_control_block_t *tcb, *first_tcb; uint32_t hcksum_flags; + uint32_t pay_len; int i; igb_t *igb = tx_ring->igb; @@ -692,6 +691,7 @@ igb_tx_fill_ring(igb_tx_ring_t *tx_ring, link_list_t *pending_list, first_tcb = NULL; desc_num = 0; hcksum_flags = 0; + pay_len = 0; load_context = B_FALSE; /* @@ -758,10 +758,13 @@ igb_tx_fill_ring(igb_tx_ring_t *tx_ring, link_list_t *pending_list, tbd->read.cmd_type_len = tcb->desc[i].length; tbd->read.cmd_type_len |= E1000_ADVTXD_DCMD_RS | - E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_DATA; + E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_DATA | + E1000_ADVTXD_DCMD_IFCS; tbd->read.olinfo_status = 0; + pay_len += tcb->desc[i].length; + index = NEXT_INDEX(index, 1, tx_ring->ring_size); desc_num++; } @@ -788,9 +791,14 @@ igb_tx_fill_ring(igb_tx_ring_t *tx_ring, link_list_t *pending_list, /* * The Insert Ethernet CRC (IFCS) bit and the checksum fields are only * valid in the first descriptor of the packet. + * 82576 also requires the payload length setting even without TSO */ ASSERT(first_tbd != NULL); first_tbd->read.cmd_type_len |= E1000_ADVTXD_DCMD_IFCS; + if (hw->mac.type == e1000_82576) { + first_tbd->read.olinfo_status = + (pay_len << E1000_ADVTXD_PAYLEN_SHIFT); + } /* Set hardware checksum bits */ if (hcksum_flags != 0) { |