summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDariusz Swiderski <dms@cvs.openbsd.org>2009-09-04 22:13:52 +0000
committerDariusz Swiderski <dms@cvs.openbsd.org>2009-09-04 22:13:52 +0000
commit0dbf04da90af2e82aba43252aa4674fea37504bf (patch)
tree73a4c476910133ceb4a34ce6ef6b6976af211a62
parentf7f10e59339db8aa79216f84d17bb6c58bbe9b55 (diff)
Bring back support for iCH10 based chips. This time support for fiber cards
seems to be fixed, thanks to tests done by mpf at mailq dot de. Also support for older fiber cards that have no PHY seems to be working, thanks to claudio@ The code includes all the changes that i backed out, plus two tweaks: 1. em_detect_gig_phy() gets called in em_setup_link() instead of em_copper_link_preconfig(), this enables phy detection on fiber cards. 2. em_detect_gig_phy() gets a condition to look for old fiber cards, that have no PHY. ok by claudio@, prodded by deraadt@
-rw-r--r--sys/dev/pci/if_em.c20
-rw-r--r--sys/dev/pci/if_em_hw.c350
-rw-r--r--sys/dev/pci/if_em_hw.h3
3 files changed, 256 insertions, 117 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index 8e0f3ec112d..2670ea5ec58 100644
--- a/sys/dev/pci/if_em.c
+++ b/sys/dev/pci/if_em.c
@@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
-/* $OpenBSD: if_em.c,v 1.221 2009/08/21 22:54:10 dms Exp $ */
+/* $OpenBSD: if_em.c,v 1.222 2009/09/04 22:13:51 dms Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -132,13 +132,19 @@ const struct pci_matchid em_devices[] = {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_C },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_M },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IGP_M_AMT },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH9_BM },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH9_IFE },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH9_IFE_G },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH9_IFE_GT },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH9_IGP_AMT },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH9_IGP_C },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH9_IGP_M },
- { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH9_IGP_M_AMT }
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH9_IGP_M_AMT },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH10_D_BM_LF },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH10_D_BM_LM },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH10_R_BM_LF },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH10_R_BM_LM },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH10_R_BM_V }
};
/*********************************************************************
@@ -333,13 +339,15 @@ em_attach(struct device *parent, struct device *self, void *aux)
case em_82574:
case em_82575:
case em_ich9lan:
- case em_80003es2lan: /* Limit Jumbo Frame size */
+ case em_ich10lan:
+ case em_80003es2lan:
+ /* Limit Jumbo Frame size */
sc->hw.max_frame_size = 9234;
break;
- /* Adapters that do not support Jumbo frames */
case em_82542_rev2_0:
case em_82542_rev2_1:
case em_ich8lan:
+ /* Adapters that do not support Jumbo frames */
sc->hw.max_frame_size = ETHER_MAX_LEN;
break;
default:
@@ -689,6 +697,7 @@ em_init(void *arg)
pba = E1000_PBA_8K;
break;
case em_ich9lan:
+ case em_ich10lan:
pba = E1000_PBA_10K;
break;
default:
@@ -1517,7 +1526,8 @@ em_allocate_pci_resources(struct em_softc *sc)
/* for ICH8 and family we need to find the flash memory */
if (sc->hw.mac_type == em_ich8lan ||
- sc->hw.mac_type == em_ich9lan) {
+ sc->hw.mac_type == em_ich9lan ||
+ sc->hw.mac_type == em_ich10lan) {
val = pci_conf_read(pa->pa_pc, pa->pa_tag, EM_FLASH);
if (PCI_MAPREG_TYPE(val) != PCI_MAPREG_TYPE_MEM) {
printf(": flash is not mem space\n");
diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c
index c2760b1a149..143f0a17ad8 100644
--- a/sys/dev/pci/if_em_hw.c
+++ b/sys/dev/pci/if_em_hw.c
@@ -31,7 +31,7 @@
*******************************************************************************/
-/* $OpenBSD: if_em_hw.c,v 1.37 2009/08/21 22:54:10 dms Exp $ */
+/* $OpenBSD: if_em_hw.c,v 1.38 2009/09/04 22:13:51 dms Exp $ */
/* if_em_hw.c
* Shared functions for accessing and configuring the MAC
@@ -85,6 +85,7 @@ static void em_clear_vfta(struct em_hw *hw);
static int32_t em_commit_shadow_ram(struct em_hw *hw);
static int32_t em_config_dsp_after_link_change(struct em_hw *hw, boolean_t link_up);
static int32_t em_config_fc_after_link_up(struct em_hw *hw);
+static int32_t em_match_gig_phy(struct em_hw *hw);
static int32_t em_detect_gig_phy(struct em_hw *hw);
static int32_t em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t bank);
static int32_t em_get_auto_rd_done(struct em_hw *hw);
@@ -475,6 +476,7 @@ em_set_mac_type(struct em_hw *hw)
case E1000_DEV_ID_ICH8_IGP_M_AMT:
hw->mac_type = em_ich8lan;
break;
+ case E1000_DEV_ID_ICH9_BM:
case E1000_DEV_ID_ICH9_IFE:
case E1000_DEV_ID_ICH9_IFE_G:
case E1000_DEV_ID_ICH9_IFE_GT:
@@ -482,8 +484,15 @@ em_set_mac_type(struct em_hw *hw)
case E1000_DEV_ID_ICH9_IGP_C:
case E1000_DEV_ID_ICH9_IGP_M:
case E1000_DEV_ID_ICH9_IGP_M_AMT:
+ case E1000_DEV_ID_ICH10_R_BM_LF:
+ case E1000_DEV_ID_ICH10_R_BM_LM:
+ case E1000_DEV_ID_ICH10_R_BM_V:
hw->mac_type = em_ich9lan;
break;
+ case E1000_DEV_ID_ICH10_D_BM_LF:
+ case E1000_DEV_ID_ICH10_D_BM_LM:
+ hw->mac_type = em_ich10lan;
+ break;
default:
/* Should never have loaded on this device */
return -E1000_ERR_MAC_TYPE;
@@ -492,6 +501,7 @@ em_set_mac_type(struct em_hw *hw)
switch (hw->mac_type) {
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
hw->swfwhw_semaphore_present = TRUE;
hw->asf_firmware_present = TRUE;
break;
@@ -552,6 +562,7 @@ em_set_media_type(struct em_hw *hw)
break;
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
case em_82573:
case em_82574:
/* The STATUS_TBIMODE bit is reserved or reused for the this
@@ -690,6 +701,7 @@ em_reset_hw(struct em_hw *hw)
break;
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
if (!hw->phy_reset_disable &&
em_check_phy_reset_block(hw) == E1000_SUCCESS) {
/* PHY HW reset requires MAC CORE reset at the same
@@ -781,7 +793,9 @@ em_reset_hw(struct em_hw *hw)
em_pci_set_mwi(hw);
}
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
uint32_t kab = E1000_READ_REG(hw, KABGTXD);
kab |= E1000_KABGTXD_BGSQLBIAS;
E1000_WRITE_REG(hw, KABGTXD, kab);
@@ -866,6 +880,7 @@ em_initialize_hardware_bits(struct em_hw *hw)
break;
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
if (hw->mac_type == em_ich8lan)
reg_tarc0 |= 0x30000000; /* Set TARC0 bits 29 and 28 */
reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
@@ -945,7 +960,9 @@ em_init_hw(struct em_hw *hw)
/* Disabling VLAN filtering. */
DEBUGOUT("Initializing the IEEE VLAN\n");
/* VET hardcoded to standard value and VFTA removed in ICH8/ICH9 LAN */
- if (hw->mac_type != em_ich8lan && hw->mac_type != em_ich9lan) {
+ if (hw->mac_type != em_ich8lan &&
+ hw->mac_type != em_ich9lan &&
+ hw->mac_type != em_ich10lan) {
if (hw->mac_type < em_82545_rev_3)
E1000_WRITE_REG(hw, VET, 0);
em_clear_vfta(hw);
@@ -977,7 +994,9 @@ em_init_hw(struct em_hw *hw)
/* Zero out the Multicast HASH table */
DEBUGOUT("Zeroing the MTA\n");
mta_size = E1000_MC_TBL_SIZE;
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
mta_size = E1000_MC_TBL_SIZE_ICH8LAN;
for (i = 0; i < mta_size; i++) {
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
@@ -1023,7 +1042,9 @@ em_init_hw(struct em_hw *hw)
}
/* More time needed for PHY to initialize */
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
msec_delay(15);
/* Call a subroutine to configure the link and setup flow control. */
@@ -1070,6 +1091,7 @@ em_init_hw(struct em_hw *hw)
case em_82575:
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
ctrl = E1000_READ_REG(hw, TXDCTL1);
ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
E1000_WRITE_REG(hw, TXDCTL1, ctrl);
@@ -1093,9 +1115,12 @@ em_init_hw(struct em_hw *hw)
* Set to snoop by default after reset. */
if (hw->mac_type == em_ich8lan)
snoop = PCI_EX_82566_SNOOP_ALL;
- else if (hw->mac_type == em_ich9lan)
+ else if (hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
snoop = (u_int32_t)~(PCI_EX_NO_SNOOP_ALL);
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
em_set_pci_ex_no_snoop(hw, snoop);
if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
@@ -1187,6 +1212,7 @@ em_setup_link(struct em_hw *hw)
switch (hw->mac_type) {
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
case em_82573:
case em_82574:
hw->fc = E1000_FC_FULL;
@@ -1242,6 +1268,14 @@ em_setup_link(struct em_hw *hw)
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
}
+ /* Make sure we have a valid PHY */
+ ret_val = em_detect_gig_phy(hw);
+ if (ret_val) {
+ DEBUGOUT("Error, did not detect valid phy.\n");
+ return ret_val;
+ }
+ DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
+
/* Call the necessary subroutine to configure the link. */
ret_val = (hw->media_type == em_media_type_copper) ?
em_setup_copper_link(hw) :
@@ -1254,8 +1288,13 @@ em_setup_link(struct em_hw *hw)
*/
DEBUGOUT("Initializing the Flow Control address, type and timer regs\n");
- /* FCAL/H and FCT are hardcoded to standard values in em_ich8lan/em_ich9lan. */
- if (hw->mac_type != em_ich8lan && hw->mac_type != em_ich9lan) {
+ /*
+ * FCAL/H and FCT are hardcoded to standard values in
+ * em_ich8lan / em_ich9lan / em_ich10lan.
+ */
+ if (hw->mac_type != em_ich8lan &&
+ hw->mac_type != em_ich9lan &&
+ hw->mac_type != em_ich10lan) {
E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
@@ -1469,14 +1508,6 @@ em_copper_link_preconfig(struct em_hw *hw)
return ret_val;
}
- /* Make sure we have a valid PHY */
- ret_val = em_detect_gig_phy(hw);
- if (ret_val) {
- DEBUGOUT("Error, did not detect valid phy.\n");
- return ret_val;
- }
- DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
-
/* Set PHY to class A mode (if necessary) */
ret_val = em_set_phy_mode(hw);
if (ret_val)
@@ -1523,7 +1554,9 @@ em_copper_link_igp_setup(struct em_hw *hw)
/* Wait 15ms for MAC to configure PHY from eeprom settings */
msec_delay(15);
- if (hw->mac_type != em_ich8lan && hw->mac_type != em_ich9lan) {
+ if (hw->mac_type != em_ich8lan &&
+ hw->mac_type != em_ich9lan &&
+ hw->mac_type != em_ich10lan) {
/* Configure activity LED after PHY reset */
led_ctrl = E1000_READ_REG(hw, LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
@@ -1863,7 +1896,8 @@ em_copper_link_mgp_setup(struct em_hw *hw)
return ret_val;
if ((hw->phy_type == em_phy_m88) &&
- (hw->phy_revision < M88E1011_I_REV_4)) {
+ (hw->phy_revision < M88E1011_I_REV_4) &&
+ (hw->phy_id != BME1000_E_PHY_ID)) {
/* Force TX_CLK in the Extended PHY Specific Control Register
* to 25MHz clock.
*/
@@ -2050,6 +2084,7 @@ em_setup_copper_link(struct em_hw *hw)
case em_80003es2lan:
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
/* Set the mac to wait the maximum time between each
* iteration and increase the max iterations when
* polling the phy; this fixes erroneous timeouts at 10Mbps. */
@@ -3628,7 +3663,6 @@ em_read_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr,
{
uint32_t i;
uint32_t mdic = 0;
- const uint32_t phy_addr = 1;
DEBUGFUNC("em_read_phy_reg_ex");
@@ -3643,7 +3677,7 @@ em_read_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr,
* PHY to retrieve the desired data.
*/
mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
- (phy_addr << E1000_MDIC_PHY_SHIFT) |
+ (hw->phy_addr << E1000_MDIC_PHY_SHIFT) |
(E1000_MDIC_OP_READ));
E1000_WRITE_REG(hw, MDIC, mdic);
@@ -3681,7 +3715,7 @@ em_read_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr,
* READ operation is performed. These two bits are thrown away
* followed by a shift in of 16 bits which contains the desired data.
*/
- mdic = ((reg_addr) | (phy_addr << 5) |
+ mdic = ((reg_addr) | (hw->phy_addr << 5) |
(PHY_OP_READ << 10) | (PHY_SOF << 12));
em_shift_out_mdi_bits(hw, mdic, 14);
@@ -3773,7 +3807,6 @@ em_write_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr,
{
uint32_t i;
uint32_t mdic = 0;
- const uint32_t phy_addr = 1;
DEBUGFUNC("em_write_phy_reg_ex");
@@ -3789,7 +3822,7 @@ em_write_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr,
*/
mdic = (((uint32_t) phy_data) |
(reg_addr << E1000_MDIC_REG_SHIFT) |
- (phy_addr << E1000_MDIC_PHY_SHIFT) |
+ (hw->phy_addr << E1000_MDIC_PHY_SHIFT) |
(E1000_MDIC_OP_WRITE));
E1000_WRITE_REG(hw, MDIC, mdic);
@@ -3818,7 +3851,7 @@ em_write_phy_reg_ex(struct em_hw *hw, uint32_t reg_addr,
* format of a MII write instruction is as follows:
* <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
*/
- mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
+ mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (hw->phy_addr << 7) |
(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
mdic <<= 16;
mdic |= (uint32_t) phy_data;
@@ -4093,52 +4126,19 @@ em_kumeran_lock_loss_workaround(struct em_hw *hw)
}
/******************************************************************************
-* Probes the expected PHY address for known PHY IDs
+* Reads and matches the expected PHY address for known PHY IDs
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
STATIC int32_t
-em_detect_gig_phy(struct em_hw *hw)
+em_match_gig_phy(struct em_hw *hw)
{
int32_t phy_init_status, ret_val;
uint16_t phy_id_high, phy_id_low;
boolean_t match = FALSE;
- DEBUGFUNC("em_detect_gig_phy");
-
- if (hw->phy_id != 0)
- return E1000_SUCCESS;
+ DEBUGFUNC("em_match_gig_phy");
- /* The 82571 firmware may still be configuring the PHY. In this
- * case, we cannot access the PHY until the configuration is done. So
- * we explicitly set the PHY values. */
- if (hw->mac_type == em_82571 ||
- hw->mac_type == em_82572 ||
- hw->mac_type == em_82575) {
- hw->phy_id = IGP01E1000_I_PHY_ID;
- hw->phy_type = em_phy_igp_2;
- return E1000_SUCCESS;
- }
-
- /* until something better comes along... makes the Lenovo X200 work */
- if (hw->mac_type == em_ich9lan &&
- (hw->device_id == E1000_DEV_ID_ICH9_IGP_M ||
- hw->device_id == E1000_DEV_ID_ICH9_IGP_M_AMT)) {
- hw->phy_id = IGP03E1000_E_PHY_ID;
- hw->phy_type = em_phy_igp_3;
- return E1000_SUCCESS;
- }
-
- /* ESB-2 PHY reads require em_phy_gg82563 to be set because of a work-
- * around that forces PHY page 0 to be set or the reads fail. The rest of
- * the code in this routine uses em_read_phy_reg to read the PHY ID.
- * So for ESB-2 we need to have this set so our reads won't fail. If the
- * attached PHY is not a em_phy_gg82563, the routines below will figure
- * this out as well. */
- if (hw->mac_type == em_80003es2lan)
- hw->phy_type = em_phy_gg82563;
-
- /* Read the PHY ID Registers to identify which PHY is onboard. */
ret_val = em_read_phy_reg(hw, PHY_ID1, &phy_id_high);
if (ret_val)
return ret_val;
@@ -4154,55 +4154,126 @@ em_detect_gig_phy(struct em_hw *hw)
switch (hw->mac_type) {
case em_82543:
- if (hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
- break;
+ if (hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
+ break;
case em_82544:
- if (hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
- break;
+ if (hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
+ break;
case em_82540:
case em_82545:
case em_82545_rev_3:
case em_82546:
case em_82546_rev_3:
- if (hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
- break;
+ if (hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
+ break;
case em_82541:
case em_82541_rev_2:
case em_82547:
case em_82547_rev_2:
- if (hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
- break;
+ if (hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
+ break;
case em_82573:
- if (hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
- break;
+ if (hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
+ break;
case em_82574:
- if (hw->phy_id == BME1000_E_PHY_ID) match = TRUE;
- break;
+ if (hw->phy_id == BME1000_E_PHY_ID) match = TRUE;
+ break;
case em_80003es2lan:
- if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
- break;
+ if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
+ break;
case em_ich8lan:
case em_ich9lan:
- if (hw->phy_id == IGP03E1000_E_PHY_ID) match = TRUE;
- if (hw->phy_id == IFE_E_PHY_ID) match = TRUE;
- if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = TRUE;
- if (hw->phy_id == IFE_C_E_PHY_ID) match = TRUE;
- break;
+ case em_ich10lan:
+ if (hw->phy_id == IGP03E1000_E_PHY_ID) match = TRUE;
+ if (hw->phy_id == IFE_E_PHY_ID) match = TRUE;
+ if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = TRUE;
+ if (hw->phy_id == IFE_C_E_PHY_ID) match = TRUE;
+ if (hw->phy_id == BME1000_E_PHY_ID) match = TRUE;
+ break;
default:
- DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
- return -E1000_ERR_CONFIG;
+ DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
+ return -E1000_ERR_CONFIG;
}
phy_init_status = em_set_phy_type(hw);
if ((match) && (phy_init_status == E1000_SUCCESS)) {
- DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id);
- return E1000_SUCCESS;
+ DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id);
+ return E1000_SUCCESS;
}
DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id);
return -E1000_ERR_PHY;
}
/******************************************************************************
+* Probes the expected PHY address for known PHY IDs
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+STATIC int32_t
+em_detect_gig_phy(struct em_hw *hw)
+{
+ int32_t ret_val;
+
+ DEBUGFUNC("em_detect_gig_phy");
+
+ if (hw->phy_id != 0)
+ return E1000_SUCCESS;
+
+ /* default phy address, most phys reside here, but not all (ICH10) */
+ hw->phy_addr = 1;
+
+ /* The 82571 firmware may still be configuring the PHY. In this
+ * case, we cannot access the PHY until the configuration is done. So
+ * we explicitly set the PHY values. */
+ if (hw->mac_type == em_82571 ||
+ hw->mac_type == em_82572 ||
+ hw->mac_type == em_82575) {
+ hw->phy_id = IGP01E1000_I_PHY_ID;
+ hw->phy_type = em_phy_igp_2;
+ return E1000_SUCCESS;
+ }
+
+ /* Some of the fiber cards dont have a phy, so we must exit cleanly here */
+ if ((hw->media_type == em_media_type_fiber) &&
+ (hw->mac_type == em_82542_rev2_0 ||
+ hw->mac_type == em_82542_rev2_1 ||
+ hw->mac_type == em_82543 ||
+ hw->mac_type == em_82574 ||
+ hw->mac_type == em_82573 ||
+ hw->mac_type == em_82574 ||
+ hw->mac_type == em_80003es2lan)) {
+ hw->phy_type = em_phy_undefined;
+ return E1000_SUCCESS;
+ }
+
+ /* until something better comes along... makes the Lenovo X200 work */
+ if (hw->mac_type == em_ich9lan &&
+ (hw->device_id == E1000_DEV_ID_ICH9_IGP_M ||
+ hw->device_id == E1000_DEV_ID_ICH9_IGP_M_AMT)) {
+ hw->phy_id = IGP03E1000_E_PHY_ID;
+ hw->phy_type = em_phy_igp_3;
+ return E1000_SUCCESS;
+ }
+
+ /* ESB-2 PHY reads require em_phy_gg82563 to be set because of a work-
+ * around that forces PHY page 0 to be set or the reads fail. The rest of
+ * the code in this routine uses em_read_phy_reg to read the PHY ID.
+ * So for ESB-2 we need to have this set so our reads won't fail. If the
+ * attached PHY is not a em_phy_gg82563, the routines below will figure
+ * this out as well. */
+ if (hw->mac_type == em_80003es2lan)
+ hw->phy_type = em_phy_gg82563;
+
+ /* Read the PHY ID Registers to identify which PHY is onboard. */
+ for (hw->phy_addr = 1; (hw->phy_addr < 4); hw->phy_addr++) {
+ ret_val = em_match_gig_phy(hw);
+ if (ret_val == E1000_SUCCESS)
+ return E1000_SUCCESS;
+ }
+ return -E1000_ERR_PHY;
+}
+
+/******************************************************************************
* Resets the PHY's DSP
*
* hw - Struct containing variables accessed by shared code
@@ -4362,6 +4433,7 @@ em_init_eeprom_params(struct em_hw *hw)
break;
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
{
int32_t i = 0;
uint32_t flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG);
@@ -4981,7 +5053,9 @@ em_is_onboard_nvm_eeprom(struct em_hw *hw)
DEBUGFUNC("em_is_onboard_nvm_eeprom");
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
return FALSE;
if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) {
@@ -5034,7 +5108,9 @@ em_validate_eeprom_checksum(struct em_hw *hw)
}
}
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
/* Drivers must allocate the shadow ram structure for the
* EEPROM checksum to be updated. Otherwise, this bit as well
* as the checksum must both be set correctly for this
@@ -5591,7 +5667,9 @@ em_init_rx_addrs(struct em_hw *hw)
* the other port. */
if ((hw->mac_type == em_82571) && (hw->laa_is_present == TRUE))
rar_num -= 1;
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
rar_num = E1000_RAR_ENTRIES_ICH8LAN;
if (hw->mac_type == em_ich8lan)
rar_num -= 1;
@@ -5640,7 +5718,9 @@ em_mc_addr_list_update(struct em_hw *hw,
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
num_rar_entry = E1000_RAR_ENTRIES;
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
num_rar_entry = E1000_RAR_ENTRIES_ICH8LAN;
if (hw->mac_type == em_ich8lan)
num_rar_entry -= 1;
@@ -5661,7 +5741,9 @@ em_mc_addr_list_update(struct em_hw *hw,
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
num_mta_entry = E1000_NUM_MTA_REGISTERS;
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
num_mta_entry = E1000_NUM_MTA_REGISTERS_ICH8LAN;
for (i = 0; i < num_mta_entry; i++) {
@@ -5722,7 +5804,9 @@ em_hash_mc_addr(struct em_hw *hw,
* LSB MSB
*/
case 0:
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
/* [47:38] i.e. 0x158 for above example address */
hash_value = ((mc_addr[4] >> 6) | (((uint16_t) mc_addr[5]) << 2));
} else {
@@ -5731,7 +5815,9 @@ em_hash_mc_addr(struct em_hw *hw,
}
break;
case 1:
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
/* [46:37] i.e. 0x2B1 for above example address */
hash_value = ((mc_addr[4] >> 5) | (((uint16_t) mc_addr[5]) << 3));
} else {
@@ -5740,7 +5826,9 @@ em_hash_mc_addr(struct em_hw *hw,
}
break;
case 2:
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
/*[45:36] i.e. 0x163 for above example address */
hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
} else {
@@ -5749,7 +5837,9 @@ em_hash_mc_addr(struct em_hw *hw,
}
break;
case 3:
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
/* [43:34] i.e. 0x18D for above example address */
hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
} else {
@@ -5760,7 +5850,9 @@ em_hash_mc_addr(struct em_hw *hw,
}
hash_value &= 0xFFF;
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
hash_value &= 0x3FF;
return hash_value;
@@ -5789,7 +5881,9 @@ em_mta_set(struct em_hw *hw,
* register are determined by the lower 5 bits of the value.
*/
hash_reg = (hash_value >> 5) & 0x7F;
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
hash_reg &= 0x1F;
hash_bit = hash_value & 0x1F;
@@ -5885,7 +5979,9 @@ em_clear_vfta(struct em_hw *hw)
uint32_t vfta_offset = 0;
uint32_t vfta_bit_in_reg = 0;
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
return;
if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) {
@@ -5943,7 +6039,9 @@ em_id_led_init(struct em_hw * hw)
eeprom_data = ID_LED_DEFAULT_82573;
else if ((eeprom_data == ID_LED_RESERVED_0000) ||
(eeprom_data == ID_LED_RESERVED_FFFF)) {
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
eeprom_data = ID_LED_DEFAULT_ICH8LAN;
else
eeprom_data = ID_LED_DEFAULT;
@@ -6016,7 +6114,9 @@ em_clear_hw_cntrs(struct em_hw *hw)
temp = E1000_READ_REG(hw, XOFFTXC);
temp = E1000_READ_REG(hw, FCRUC);
- if (hw->mac_type != em_ich8lan && hw->mac_type != em_ich9lan) {
+ if (hw->mac_type != em_ich8lan &&
+ hw->mac_type != em_ich9lan &&
+ hw->mac_type != em_ich10lan) {
temp = E1000_READ_REG(hw, PRC64);
temp = E1000_READ_REG(hw, PRC127);
temp = E1000_READ_REG(hw, PRC255);
@@ -6045,7 +6145,9 @@ em_clear_hw_cntrs(struct em_hw *hw)
temp = E1000_READ_REG(hw, TPR);
temp = E1000_READ_REG(hw, TPT);
- if (hw->mac_type != em_ich8lan && hw->mac_type != em_ich9lan) {
+ if (hw->mac_type != em_ich8lan &&
+ hw->mac_type != em_ich9lan &&
+ hw->mac_type != em_ich10lan) {
temp = E1000_READ_REG(hw, PTC64);
temp = E1000_READ_REG(hw, PTC127);
temp = E1000_READ_REG(hw, PTC255);
@@ -6077,7 +6179,9 @@ em_clear_hw_cntrs(struct em_hw *hw)
temp = E1000_READ_REG(hw, IAC);
temp = E1000_READ_REG(hw, ICRXOC);
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan)
return;
temp = E1000_READ_REG(hw, ICRXPTC);
@@ -6207,6 +6311,7 @@ em_get_bus_info(struct em_hw *hw)
break;
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
hw->bus_type = em_bus_type_pci_express;
hw->bus_speed = em_bus_speed_2500;
hw->bus_width = em_bus_width_pciex_1;
@@ -6768,7 +6873,9 @@ em_set_d3_lplu_state(struct em_hw *hw,
ret_val = em_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
if (ret_val)
return ret_val;
- } else if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ } else if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
/* MAC writes into PHY register based on the state transition
* and start auto-negotiation. SW driver can overwrite the settings
* in CSR PHY power control E1000_PHY_CTRL register. */
@@ -6787,7 +6894,9 @@ em_set_d3_lplu_state(struct em_hw *hw,
if (ret_val)
return ret_val;
} else {
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
} else {
@@ -6838,7 +6947,9 @@ em_set_d3_lplu_state(struct em_hw *hw,
if (ret_val)
return ret_val;
} else {
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
} else {
@@ -6890,7 +7001,9 @@ em_set_d0_lplu_state(struct em_hw *hw,
if (hw->mac_type <= em_82547_rev_2)
return E1000_SUCCESS;
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
} else {
ret_val = em_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
@@ -6899,7 +7012,9 @@ em_set_d0_lplu_state(struct em_hw *hw,
}
if (!active) {
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
} else {
@@ -6940,7 +7055,9 @@ em_set_d0_lplu_state(struct em_hw *hw,
} else {
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
} else {
@@ -7099,7 +7216,9 @@ em_check_mng_mode(struct em_hw *hw)
fwsm = E1000_READ_REG(hw, FWSM);
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
if ((fwsm & E1000_FWSM_MODE_MASK) ==
(E1000_MNG_ICH_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
return TRUE;
@@ -7347,6 +7466,7 @@ em_get_auto_rd_done(struct em_hw *hw)
case em_80003es2lan:
case em_ich8lan:
case em_ich9lan:
+ case em_ich10lan:
while (timeout) {
if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD)
break;
@@ -7574,7 +7694,9 @@ em_check_phy_reset_block(struct em_hw *hw)
uint32_t manc = 0;
uint32_t fwsm = 0;
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
fwsm = E1000_READ_REG(hw, FWSM);
return (fwsm & E1000_FWSM_RSPCIPHY) ? E1000_SUCCESS
: E1000_BLK_PHY_RESET;
@@ -7615,7 +7737,9 @@ em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop)
E1000_WRITE_REG(hw, GCR, gcr_reg);
}
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
uint32_t ctrl_ext;
ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
@@ -7643,7 +7767,9 @@ em_get_software_flag(struct em_hw *hw)
DEBUGFUNC("em_get_software_flag");
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
while (timeout) {
extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
@@ -7681,7 +7807,9 @@ em_release_software_flag(struct em_hw *hw)
DEBUGFUNC("em_release_software_flag");
- if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan) {
+ if (hw->mac_type == em_ich8lan ||
+ hw->mac_type == em_ich9lan ||
+ hw->mac_type == em_ich10lan) {
extcnf_ctrl= E1000_READ_REG(hw, EXTCNF_CTRL);
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h
index 13b43a95100..2bec83a44d4 100644
--- a/sys/dev/pci/if_em_hw.h
+++ b/sys/dev/pci/if_em_hw.h
@@ -31,7 +31,7 @@
*******************************************************************************/
-/* $OpenBSD: if_em_hw.h,v 1.32 2009/08/21 22:54:10 dms Exp $ */
+/* $OpenBSD: if_em_hw.h,v 1.33 2009/09/04 22:13:51 dms Exp $ */
/* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */
/* if_em_hw.h
@@ -72,6 +72,7 @@ typedef enum {
em_80003es2lan,
em_ich8lan,
em_ich9lan,
+ em_ich10lan,
em_num_macs
} em_mac_type;