Index: if_em.c =================================================================== RCS file: /usr/cvs/src/sys/dev/em/if_em.c,v retrieving revision 1.65.2.16 diff -u -r1.65.2.16 if_em.c --- if_em.c 19 May 2006 00:19:57 -0000 1.65.2.16 +++ if_em.c 13 Jul 2006 14:15:57 -0000 @@ -48,7 +48,7 @@ * Driver version *********************************************************************/ -char em_driver_version[] = "Version - 3.2.18"; +char em_driver_version[] = "Version - 5.1.5"; /********************************************************************* @@ -102,6 +102,7 @@ { 0x8086, E1000_DEV_ID_82546GB_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82546GB_PCIE, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82547EI, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82547EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, @@ -114,10 +115,13 @@ { 0x8086, E1000_DEV_ID_82572EI_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82572EI_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82572EI_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_82572EI, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82573E, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82573E_IAMT, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82573L, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_80003ES2LAN_COPPER_DPT, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_80003ES2LAN_SERDES_DPT, PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} @@ -515,6 +519,11 @@ adapter->unit); } + /* Indicate SOL/IDER usage */ + if (em_check_phy_reset_block(&adapter->hw)) + device_printf(dev, + "PHY reset is blocked due to SOL/IDER session.\n"); + /* Identify 82544 on PCIX */ em_get_bus_info(&adapter->hw); if(adapter->hw.bus_type == em_bus_type_pcix && @@ -727,17 +736,27 @@ case SIOCSIFMTU: { int max_frame_size; + uint16_t eeprom_data = 0; IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); switch (adapter->hw.mac_type) { + case em_82573: + /* + * 82573 only supports jumbo frames + * if ASPM is disabled. + */ + em_read_eeprom(&adapter->hw, EEPROM_INIT_3GIO_3, 1, + &eeprom_data); + if (eeprom_data & EEPROM_WORD1A_ASPM_MASK) { + max_frame_size = ETHER_MAX_LEN; + break; + } + /* Allow Jumbo frames - fall thru */ case em_82571: case em_82572: - max_frame_size = 10500; - break; - case em_82573: - /* 82573 does not support jumbo frames. */ - max_frame_size = ETHER_MAX_LEN; + case em_80003es2lan: /* Limit Jumbo Frame size */ + max_frame_size = 9234; break; default: max_frame_size = MAX_JUMBO_FRAME_SIZE; @@ -916,6 +935,7 @@ adapter->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT; adapter->tx_fifo_size = (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT; break; + case em_80003es2lan: /* 80003es2lan: Total Packet Buffer is 48K */ case em_82571: /* 82571: Total Packet Buffer is 48K */ case em_82572: /* 82572: Total Packet Buffer is 48K */ pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */ @@ -1986,7 +2006,10 @@ adapter->hw.fc_high_water = rx_buffer_size - roundup2(adapter->hw.max_frame_size, 1024); adapter->hw.fc_low_water = adapter->hw.fc_high_water - 1500; - adapter->hw.fc_pause_time = 0x1000; + if (adapter->hw.mac_type == em_80003es2lan) + adapter->hw.fc_pause_time = 0xFFFF; + else + adapter->hw.fc_pause_time = 0x1000; adapter->hw.fc_send_xon = TRUE; adapter->hw.fc = em_fc_full; @@ -2335,7 +2358,7 @@ static void em_initialize_transmit_unit(struct adapter * adapter) { - u_int32_t reg_tctl; + u_int32_t reg_tctl, tarc; u_int32_t reg_tipg = 0; u_int64_t bus_addr; @@ -2365,6 +2388,11 @@ reg_tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; reg_tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; break; + case em_80003es2lan: + reg_tipg = DEFAULT_82543_TIPG_IPGR1; + reg_tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 << + E1000_TIPG_IPGR2_SHIFT; + break; default: if (adapter->hw.media_type == em_media_type_fiber) reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER; @@ -2392,6 +2420,29 @@ } E1000_WRITE_REG(&adapter->hw, TCTL, reg_tctl); + if (adapter->hw.mac_type == em_82571 || + adapter->hw.mac_type == em_82572) { + tarc = E1000_READ_REG(&adapter->hw, TARC0); + tarc |= ((1 << 25) | (1 << 21)); + E1000_WRITE_REG(&adapter->hw, TARC0, tarc); + tarc = E1000_READ_REG(&adapter->hw, TARC1); + tarc |= (1 << 25); + if (reg_tctl & E1000_TCTL_MULR) + tarc &= ~(1 << 28); + else + tarc |= (1 << 28); + E1000_WRITE_REG(&adapter->hw, TARC1, tarc); + } else if (adapter->hw.mac_type == em_80003es2lan) { + tarc = E1000_READ_REG(&adapter->hw, TARC0); + tarc |= 1; + if (adapter->hw.media_type == em_media_type_internal_serdes) + tarc |= (1 << 20); + E1000_WRITE_REG(&adapter->hw, TARC0, tarc); + tarc = E1000_READ_REG(&adapter->hw, TARC1); + tarc |= 1; + E1000_WRITE_REG(&adapter->hw, TARC1, tarc); + } + /* Setup Transmit Descriptor Settings for this adapter */ adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_RS; Index: if_em_hw.c =================================================================== RCS file: /usr/cvs/src/sys/dev/em/if_em_hw.c,v retrieving revision 1.16.2.1 diff -u -r1.16.2.1 if_em_hw.c --- if_em_hw.c 25 Nov 2005 14:11:59 -0000 1.16.2.1 +++ if_em_hw.c 13 Jul 2006 14:00:38 -0000 @@ -76,6 +76,8 @@ static int32_t em_set_phy_mode(struct em_hw *hw); static int32_t em_host_if_read_cookie(struct em_hw *hw, uint8_t *buffer); static uint8_t em_calculate_mng_checksum(char *buffer, uint32_t length); +static int32_t em_configure_kmrn_for_10_100(struct em_hw *hw, uint16_t duplex); +static int32_t em_configure_kmrn_for_1000(struct em_hw *hw, uint16_t duplex); /* IGP cable length table */ static const @@ -91,14 +93,15 @@ static const uint16_t em_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] = - { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, - 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, - 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, - 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, - 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, - 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, - 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, - 104, 109, 114, 118, 121, 124}; + { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, + 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, + 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, + 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, + 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, + 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, + 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, + 104, 109, 114, 118, 121, 124}; + /****************************************************************************** * Set the phy type member in the hw struct. @@ -128,6 +131,11 @@ hw->phy_type = em_phy_igp; break; } + case GG82563_E_PHY_ID: + if (hw->mac_type == em_80003es2lan) { + hw->phy_type = em_phy_gg82563; + break; + } /* Fall Through */ default: /* Should never have loaded on this device */ @@ -294,6 +302,7 @@ case E1000_DEV_ID_82546GB_SERDES: case E1000_DEV_ID_82546GB_PCIE: case E1000_DEV_ID_82546GB_QUAD_COPPER: + case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: hw->mac_type = em_82546_rev_3; break; case E1000_DEV_ID_82541EI: @@ -317,24 +326,32 @@ case E1000_DEV_ID_82571EB_COPPER: case E1000_DEV_ID_82571EB_FIBER: case E1000_DEV_ID_82571EB_SERDES: - hw->mac_type = em_82571; - break; + hw->mac_type = em_82571; + break; case E1000_DEV_ID_82572EI_COPPER: case E1000_DEV_ID_82572EI_FIBER: case E1000_DEV_ID_82572EI_SERDES: - hw->mac_type = em_82572; - break; + case E1000_DEV_ID_82572EI: + hw->mac_type = em_82572; + break; case E1000_DEV_ID_82573E: case E1000_DEV_ID_82573E_IAMT: case E1000_DEV_ID_82573L: hw->mac_type = em_82573; break; + case E1000_DEV_ID_80003ES2LAN_COPPER_DPT: + case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: + hw->mac_type = em_80003es2lan; + break; default: /* Should never have loaded on this device */ return -E1000_ERR_MAC_TYPE; } switch(hw->mac_type) { + case em_80003es2lan: + hw->swfw_sync_present = TRUE; + /* fall through */ case em_82571: case em_82572: case em_82573: @@ -345,8 +362,9 @@ case em_82541_rev_2: case em_82547_rev_2: hw->asf_firmware_present = TRUE; + break; default: - break; + break; } return E1000_SUCCESS; @@ -374,29 +392,31 @@ case E1000_DEV_ID_82546GB_SERDES: case E1000_DEV_ID_82571EB_SERDES: case E1000_DEV_ID_82572EI_SERDES: + case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: hw->media_type = em_media_type_internal_serdes; break; default: - switch (hw->mac_type) { - case em_82542_rev2_0: - case em_82542_rev2_1: - hw->media_type = em_media_type_fiber; - break; - case em_82573: - /* - * The STATUS_TBIMODE bit is reserved or reused for - * this device. - */ - hw->media_type = em_media_type_copper; - break; - default: - status = E1000_READ_REG(hw, STATUS); - if (status & E1000_STATUS_TBIMODE) { - hw->media_type = em_media_type_fiber; - /* tbi_compatibility not valid on fiber */ - hw->tbi_compatibility_en = FALSE; - } else - hw->media_type = em_media_type_copper; + switch (hw->mac_type) { + case em_82542_rev2_0: + case em_82542_rev2_1: + hw->media_type = em_media_type_fiber; + break; + case em_82573: + /* The STATUS_TBIMODE bit is reserved or reused for the this + * device. + */ + hw->media_type = em_media_type_copper; + break; + default: + status = E1000_READ_REG(hw, STATUS); + if (status & E1000_STATUS_TBIMODE) { + hw->media_type = em_media_type_fiber; + /* tbi_compatibility not valid on fiber */ + hw->tbi_compatibility_en = FALSE; + } else { + hw->media_type = em_media_type_copper; + } + break; } } } @@ -540,23 +560,24 @@ /* Wait for EEPROM reload */ msec_delay(20); break; - case em_82573: - if (em_is_onboard_nvm_eeprom(hw) == FALSE) { - usec_delay(10); - ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - } - /* fall through */ - case em_82571: - case em_82572: - ret_val = em_get_auto_rd_done(hw); - if(ret_val) - /* We don't want to continue accessing MAC registers. */ - return ret_val; - break; - default: + case em_82573: + if (em_is_onboard_nvm_eeprom(hw) == FALSE) { + usec_delay(10); + ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); + } + /* fall through */ + case em_82571: + case em_82572: + case em_80003es2lan: + ret_val = em_get_auto_rd_done(hw); + if(ret_val) + /* We don't want to continue accessing MAC registers. */ + return ret_val; + break; + default: /* Wait for EEPROM reload (it happens automatically) */ msec_delay(5); break; @@ -617,6 +638,8 @@ uint16_t cmd_mmrbc; uint16_t stat_mmrbc; uint32_t mta_size; + uint32_t reg_data; + uint32_t ctrl_ext; DEBUGFUNC("em_init_hw"); @@ -708,14 +731,15 @@ if(hw->mac_type > em_82544) { ctrl = E1000_READ_REG(hw, TXDCTL); ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; - switch (hw->mac_type) { - case em_82571: + switch (hw->mac_type) { + default: + break; + case em_82571: case em_82572: - ctrl |= (1 << 22); case em_82573: - ctrl |= E1000_TXDCTL_COUNT_DESC; - default: - break; + case em_80003es2lan: + ctrl |= E1000_TXDCTL_COUNT_DESC; + break; } E1000_WRITE_REG(hw, TXDCTL, ctrl); } @@ -725,21 +749,46 @@ } switch (hw->mac_type) { + default: + break; + case em_80003es2lan: + /* Enable retransmit on late collisions */ + reg_data = E1000_READ_REG(hw, TCTL); + reg_data |= E1000_TCTL_RTLC; + E1000_WRITE_REG(hw, TCTL, reg_data); + + /* Configure Gigabit Carry Extend Padding */ + reg_data = E1000_READ_REG(hw, TCTL_EXT); + reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; + reg_data |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX; + E1000_WRITE_REG(hw, TCTL_EXT, reg_data); + + /* Configure Transmit Inter-Packet Gap */ + reg_data = E1000_READ_REG(hw, TIPG); + reg_data &= ~E1000_TIPG_IPGT_MASK; + reg_data |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000; + E1000_WRITE_REG(hw, TIPG, reg_data); + + reg_data = E1000_READ_REG_ARRAY(hw, FFLT, 0x0001); + reg_data &= ~0x00100000; + E1000_WRITE_REG_ARRAY(hw, FFLT, 0x0001, reg_data); + /* Fall through */ case em_82571: case em_82572: - ctrl = E1000_READ_REG(hw, TXDCTL1); - ctrl &= ~E1000_TXDCTL_WTHRESH; - ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB; - ctrl |= (1 << 22); - E1000_WRITE_REG(hw, TXDCTL1, ctrl); - default: - break; + ctrl = E1000_READ_REG(hw, TXDCTL1); + ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; + if(hw->mac_type >= em_82571) + ctrl |= E1000_TXDCTL_COUNT_DESC; + E1000_WRITE_REG(hw, TXDCTL1, ctrl); + break; } + + if (hw->mac_type == em_82573) { - uint32_t gcr = E1000_READ_REG(hw, GCR); - gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; - E1000_WRITE_REG(hw, GCR, gcr); + uint32_t gcr = E1000_READ_REG(hw, GCR); + gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; + E1000_WRITE_REG(hw, GCR, gcr); } /* Clear all of the statistics registers (clear on read). It is @@ -749,6 +798,15 @@ */ em_clear_hw_cntrs(hw); + if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER || + hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) { + ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + /* Relaxed ordering must be disabled to avoid a parity + * error crash in a PCI slot. */ + ctrl_ext |= E1000_CTRL_EXT_RO_DIS; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + } + return ret_val; } @@ -815,7 +873,7 @@ /* In the case of the phy reset being blocked, we already have a link. * We do not have to set it up again. */ if (em_check_phy_reset_block(hw)) - return E1000_SUCCESS; + return E1000_SUCCESS; /* Read and store word 0x0F of the EEPROM. This word contains bits * that determine the hardware's default PAUSE (flow control) mode, @@ -826,26 +884,26 @@ * be initialized based on a value in the EEPROM. */ if (hw->fc == em_fc_default) { - switch (hw->mac_type) { - case em_82573: - hw->fc = em_fc_full; - break; - default: - ret_val = em_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, - 1, &eeprom_data); - if (ret_val) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - - if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) - hw->fc = em_fc_none; - else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == - EEPROM_WORD0F_ASM_DIR) - hw->fc = em_fc_tx_pause; - else - hw->fc = em_fc_full; - } + switch (hw->mac_type) { + case em_82573: + hw->fc = em_fc_full; + break; + default: + ret_val = em_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, + 1, &eeprom_data); + if (ret_val) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } + if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) + hw->fc = em_fc_none; + else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == + EEPROM_WORD0F_ASM_DIR) + hw->fc = em_fc_tx_pause; + else + hw->fc = em_fc_full; + break; + } } /* We want to save off the original Flow Control configuration just @@ -944,7 +1002,7 @@ * loopback mode is disabled during initialization. */ if (hw->mac_type == em_82571 || hw->mac_type == em_82572) - E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK); + E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK); /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be * set when the optics detect a signal. On older adapters, it will be @@ -1266,11 +1324,159 @@ ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); if(ret_val) return ret_val; - } + } - return E1000_SUCCESS; + return E1000_SUCCESS; } +/******************************************************************** +* Copper link setup for em_phy_gg82563 series. +* +* hw - Struct containing variables accessed by shared code +*********************************************************************/ +static int32_t +em_copper_link_ggp_setup(struct em_hw *hw) +{ + int32_t ret_val; + uint16_t phy_data; + uint32_t reg_data; + + DEBUGFUNC("em_copper_link_ggp_setup"); + + if(!hw->phy_reset_disable) { + + /* Enable CRS on TX for half-duplex operation. */ + ret_val = em_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, + &phy_data); + if(ret_val) + return ret_val; + + phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; + /* Use 25MHz for both link down and 1000BASE-T for Tx clock */ + phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ; + + ret_val = em_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, + phy_data); + if(ret_val) + return ret_val; + + /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + ret_val = em_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &phy_data); + if(ret_val) + return ret_val; + + phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; + + switch (hw->mdix) { + case 1: + phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDI; + break; + case 2: + phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDIX; + break; + case 0: + default: + phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; + break; + } + + /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; + if(hw->disable_polarity_correction == 1) + phy_data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; + ret_val = em_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data); + + if(ret_val) + return ret_val; + + /* SW Reset the PHY so all changes take effect */ + ret_val = em_phy_reset(hw); + if (ret_val) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } + } /* phy_reset_disable */ + + if (hw->mac_type == em_80003es2lan) { + /* Bypass RX and TX FIFO's */ + ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL, + E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS | + E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS); + if (ret_val) + return ret_val; + + ret_val = em_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &phy_data); + if (ret_val) + return ret_val; + + phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; + ret_val = em_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, phy_data); + + if (ret_val) + return ret_val; + + reg_data = E1000_READ_REG(hw, CTRL_EXT); + reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK); + E1000_WRITE_REG(hw, CTRL_EXT, reg_data); + + ret_val = em_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, + &phy_data); + if (ret_val) + return ret_val; + + /* Do not init these registers when the HW is in IAMT mode, since the + * firmware will have already initialized them. We only initialize + * them if the HW is not in IAMT mode. + */ + if (em_check_mng_mode(hw) == FALSE) { + /* Enable Electrical Idle on the PHY */ + phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; + ret_val = em_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, + phy_data); + if (ret_val) + return ret_val; + + ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + &phy_data); + if (ret_val) + return ret_val; + + /* Disable Pass False Carrier on the PHY */ + phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + + ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + phy_data); + if (ret_val) + return ret_val; + } + + /* Workaround: Disable padding in Kumeran interface in the MAC + * and in the PHY to avoid CRC errors. + */ + ret_val = em_read_phy_reg(hw, GG82563_PHY_INBAND_CTRL, + &phy_data); + if (ret_val) + return ret_val; + phy_data |= GG82563_ICR_DIS_PADDING; + ret_val = em_write_phy_reg(hw, GG82563_PHY_INBAND_CTRL, + phy_data); + if (ret_val) + return ret_val; + } + + return E1000_SUCCESS; +} /******************************************************************** * Copper link setup for em_phy_m88 series. @@ -1481,14 +1687,50 @@ int32_t ret_val; uint16_t i; uint16_t phy_data; + uint16_t reg_data; DEBUGFUNC("em_setup_copper_link"); + switch (hw->mac_type) { + case em_80003es2lan: + /* 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. */ + ret_val = em_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF); + if (ret_val) + return ret_val; + ret_val = em_read_kmrn_reg(hw, GG82563_REG(0x34, 9), ®_data); + if (ret_val) + return ret_val; + reg_data |= 0x3F; + ret_val = em_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data); + if (ret_val) + return ret_val; + default: + break; + } + /* Check if it is a valid PHY and set PHY mode if necessary. */ ret_val = em_copper_link_preconfig(hw); if(ret_val) return ret_val; + switch (hw->mac_type) { + case em_80003es2lan: + ret_val = em_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL, + ®_data); + if (ret_val) + return ret_val; + reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING; + ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL, + reg_data); + if (ret_val) + return ret_val; + break; + default: + break; + } + if (hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2) { ret_val = em_copper_link_igp_setup(hw); @@ -1498,6 +1740,10 @@ ret_val = em_copper_link_mgp_setup(hw); if(ret_val) return ret_val; + } else if (hw->phy_type == em_phy_gg82563) { + ret_val = em_copper_link_ggp_setup(hw); + if(ret_val) + return ret_val; } if(hw->autoneg) { @@ -1545,6 +1791,86 @@ } /****************************************************************************** +* Configure the MAC-to-PHY interface for 10/100Mbps +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static int32_t +em_configure_kmrn_for_10_100(struct em_hw *hw, uint16_t duplex) +{ + int32_t ret_val = E1000_SUCCESS; + uint32_t tipg; + uint16_t reg_data; + + DEBUGFUNC("em_configure_kmrn_for_10_100"); + + reg_data = E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT; + ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL, + reg_data); + if (ret_val) + return ret_val; + + /* Configure Transmit Inter-Packet Gap */ + tipg = E1000_READ_REG(hw, TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100; + E1000_WRITE_REG(hw, TIPG, tipg); + + ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data); + if (ret_val) + return ret_val; + + /* Enable pass false carrier when in half duplex mode. */ + if (duplex == HALF_DUPLEX) + reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; + else + reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + + + ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + reg_data); + + return ret_val; +} + +static int32_t +em_configure_kmrn_for_1000(struct em_hw *hw, uint16_t duplex) +{ + int32_t ret_val = E1000_SUCCESS; + uint16_t reg_data; + uint32_t tipg; + + DEBUGFUNC("em_configure_kmrn_for_1000"); + + reg_data = E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT; + ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL, + reg_data); + if (ret_val) + return ret_val; + + /* Configure Transmit Inter-Packet Gap */ + tipg = E1000_READ_REG(hw, TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000; + E1000_WRITE_REG(hw, TIPG, tipg); + + + ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + ®_data); + if (ret_val) + return ret_val; + + /* Disable Pass False Carrier on the PHY */ + reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; + + ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + reg_data); + + return ret_val; +} + +/****************************************************************************** * Configures PHY autoneg and flow control advertisement settings * * hw - Struct containing variables accessed by shared code @@ -1563,10 +1889,10 @@ if(ret_val) return ret_val; - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); - if(ret_val) - return ret_val; + /* Read the MII 1000Base-T Control Register (Address 9). */ + ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); + if(ret_val) + return ret_val; /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for @@ -1765,7 +2091,8 @@ /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); - if (hw->phy_type == em_phy_m88) { + if ((hw->phy_type == em_phy_m88) || + (hw->phy_type == em_phy_gg82563)) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if(ret_val) return ret_val; @@ -1834,7 +2161,8 @@ msec_delay(100); } if((i == 0) && - (hw->phy_type == em_phy_m88)) { + ((hw->phy_type == em_phy_m88) || + (hw->phy_type == em_phy_gg82563))) { /* We didn't get link. Reset the DSP and wait again for link. */ ret_val = em_phy_reset_dsp(hw); if(ret_val) { @@ -1893,6 +2221,27 @@ if(ret_val) return ret_val; } + } else if (hw->phy_type == em_phy_gg82563) { + /* The TX_CLK of the Extended PHY Specific Control Register defaults + * to 2.5MHz on a reset. We need to re-force it back to 25MHz, if + * we're not in a forced 10/duplex configuration. */ + ret_val = em_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); + if (ret_val) + return ret_val; + + phy_data &= ~GG82563_MSCR_TX_CLK_MASK; + if ((hw->forced_speed_duplex == em_10_full) || + (hw->forced_speed_duplex == em_10_half)) + phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ; + else + phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25MHZ; + + /* Also due to the reset, we need to enable CRS on Tx. */ + phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; + + ret_val = em_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); + if (ret_val) + return ret_val; } return E1000_SUCCESS; } @@ -1908,14 +2257,19 @@ void em_config_collision_dist(struct em_hw *hw) { - uint32_t tctl; + uint32_t tctl, coll_dist; DEBUGFUNC("em_config_collision_dist"); + if (hw->mac_type < em_82543) + coll_dist = E1000_COLLISION_DISTANCE_82542; + else + coll_dist = E1000_COLLISION_DISTANCE; + tctl = E1000_READ_REG(hw, TCTL); tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; + tctl |= coll_dist << E1000_COLD_SHIFT; E1000_WRITE_REG(hw, TCTL, tctl); E1000_WRITE_FLUSH(hw); @@ -2159,10 +2513,10 @@ */ if(hw->original_fc == em_fc_full) { hw->fc = em_fc_full; - DEBUGOUT("Flow Control = FULL.\r\n"); + DEBUGOUT("Flow Control = FULL.\n"); } else { hw->fc = em_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } } /* For receiving PAUSE frames ONLY. @@ -2178,7 +2532,7 @@ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc = em_fc_tx_pause; - DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. * @@ -2193,7 +2547,7 @@ !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc = em_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } /* Per the IEEE spec, at this point flow control should be * disabled. However, we want to consider that we could @@ -2219,10 +2573,10 @@ hw->original_fc == em_fc_tx_pause) || hw->fc_strict_ieee) { hw->fc = em_fc_none; - DEBUGOUT("Flow Control = NONE.\r\n"); + DEBUGOUT("Flow Control = NONE.\n"); } else { hw->fc = em_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } /* Now we need to do one last check... If we auto- @@ -2247,7 +2601,7 @@ return ret_val; } } else { - DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n"); + DEBUGOUT("Copper PHY and Auto Neg has not completed.\n"); } } return E1000_SUCCESS; @@ -2430,7 +2784,7 @@ hw->autoneg_failed = 1; return 0; } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); + DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE)); @@ -2455,7 +2809,7 @@ else if(((hw->media_type == em_media_type_fiber) || (hw->media_type == em_media_type_internal_serdes)) && (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n"); + DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); E1000_WRITE_REG(hw, TXCW, hw->txcw); E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); @@ -2518,13 +2872,13 @@ if(status & E1000_STATUS_FD) { *duplex = FULL_DUPLEX; - DEBUGOUT("Full Duplex\r\n"); + DEBUGOUT("Full Duplex\n"); } else { *duplex = HALF_DUPLEX; - DEBUGOUT(" Half Duplex\r\n"); + DEBUGOUT(" Half Duplex\n"); } } else { - DEBUGOUT("1000 Mbs, Full Duplex\r\n"); + DEBUGOUT("1000 Mbs, Full Duplex\n"); *speed = SPEED_1000; *duplex = FULL_DUPLEX; } @@ -2550,6 +2904,16 @@ } } + if ((hw->mac_type == em_80003es2lan) && + (hw->media_type == em_media_type_copper)) { + if (*speed == SPEED_1000) + ret_val = em_configure_kmrn_for_1000(hw, *duplex); + else + ret_val = em_configure_kmrn_for_10_100(hw, *duplex); + if (ret_val) + return ret_val; + } + return E1000_SUCCESS; } @@ -2725,6 +3089,72 @@ return data; } +int32_t +em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask) +{ + uint32_t swfw_sync = 0; + uint32_t swmask = mask; + uint32_t fwmask = mask << 16; + int32_t timeout = 200; + + DEBUGFUNC("em_swfw_sync_acquire"); + + if (!hw->swfw_sync_present) + return em_get_hw_eeprom_semaphore(hw); + + while(timeout) { + if (em_get_hw_eeprom_semaphore(hw)) + return -E1000_ERR_SWFW_SYNC; + + swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC); + if (!(swfw_sync & (fwmask | swmask))) { + break; + } + + /* firmware currently using resource (fwmask) */ + /* or other software thread currently using resource (swmask) */ + em_put_hw_eeprom_semaphore(hw); + msec_delay_irq(5); + timeout--; + } + + if (!timeout) { + DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); + return -E1000_ERR_SWFW_SYNC; + } + + swfw_sync |= swmask; + E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync); + + em_put_hw_eeprom_semaphore(hw); + return E1000_SUCCESS; +} + +void +em_swfw_sync_release(struct em_hw *hw, uint16_t mask) +{ + uint32_t swfw_sync; + uint32_t swmask = mask; + + DEBUGFUNC("em_swfw_sync_release"); + + if (!hw->swfw_sync_present) { + em_put_hw_eeprom_semaphore(hw); + return; + } + + /* if (em_get_hw_eeprom_semaphore(hw)) + * return -E1000_ERR_SWFW_SYNC; */ + while (em_get_hw_eeprom_semaphore(hw) != E1000_SUCCESS); + /* empty */ + + swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC); + swfw_sync &= ~swmask; + E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync); + + em_put_hw_eeprom_semaphore(hw); +} + /***************************************************************************** * Reads the value from a PHY register, if the value is on a specific non zero * page, sets the page first. @@ -2737,22 +3167,55 @@ uint16_t *phy_data) { uint32_t ret_val; + uint16_t swfw; DEBUGFUNC("em_read_phy_reg"); + if ((hw->mac_type == em_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + if((hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (uint16_t)reg_addr); if(ret_val) { + em_swfw_sync_release(hw, swfw); return ret_val; } + } else if (hw->phy_type == em_phy_gg82563) { + if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) || + (hw->mac_type == em_80003es2lan)) { + /* Select Configuration Page */ + if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + ret_val = em_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } else { + /* Use Alternative Page Select register to access + * registers 30 and 31 + */ + ret_val = em_write_phy_reg_ex(hw, + GG82563_PHY_PAGE_SELECT_ALT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } + + if (ret_val) { + em_swfw_sync_release(hw, swfw); + return ret_val; + } + } } ret_val = em_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); + em_swfw_sync_release(hw, swfw); return ret_val; } @@ -2843,22 +3306,55 @@ uint16_t phy_data) { uint32_t ret_val; + uint16_t swfw; DEBUGFUNC("em_write_phy_reg"); + if ((hw->mac_type == em_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + if((hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (uint16_t)reg_addr); if(ret_val) { + em_swfw_sync_release(hw, swfw); return ret_val; } + } else if (hw->phy_type == em_phy_gg82563) { + if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) || + (hw->mac_type == em_80003es2lan)) { + /* Select Configuration Page */ + if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + ret_val = em_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } else { + /* Use Alternative Page Select register to access + * registers 30 and 31 + */ + ret_val = em_write_phy_reg_ex(hw, + GG82563_PHY_PAGE_SELECT_ALT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } + + if (ret_val) { + em_swfw_sync_release(hw, swfw); + return ret_val; + } + } } ret_val = em_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); + em_swfw_sync_release(hw, swfw); return ret_val; } @@ -2891,7 +3387,7 @@ E1000_WRITE_REG(hw, MDIC, mdic); /* Poll the ready bit to see if the MDI read completed */ - for(i = 0; i < 640; i++) { + for(i = 0; i < 641; i++) { usec_delay(5); mdic = E1000_READ_REG(hw, MDIC); if(mdic & E1000_MDIC_READY) break; @@ -2925,6 +3421,65 @@ return E1000_SUCCESS; } +int32_t +em_read_kmrn_reg(struct em_hw *hw, + uint32_t reg_addr, + uint16_t *data) +{ + uint32_t reg_val; + uint16_t swfw; + DEBUGFUNC("em_read_kmrn_reg"); + + if ((hw->mac_type == em_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + + /* Write register address */ + reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) & + E1000_KUMCTRLSTA_OFFSET) | + E1000_KUMCTRLSTA_REN; + E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val); + usec_delay(2); + + /* Read the data returned */ + reg_val = E1000_READ_REG(hw, KUMCTRLSTA); + *data = (uint16_t)reg_val; + + em_swfw_sync_release(hw, swfw); + return E1000_SUCCESS; +} + +int32_t +em_write_kmrn_reg(struct em_hw *hw, + uint32_t reg_addr, + uint16_t data) +{ + uint32_t reg_val; + uint16_t swfw; + DEBUGFUNC("em_write_kmrn_reg"); + + if ((hw->mac_type == em_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + + reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) & + E1000_KUMCTRLSTA_OFFSET) | data; + E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val); + usec_delay(2); + + em_swfw_sync_release(hw, swfw); + return E1000_SUCCESS; +} /****************************************************************************** * Returns the PHY to the power-on reset state @@ -2937,6 +3492,7 @@ uint32_t ctrl, ctrl_ext; uint32_t led_ctrl; int32_t ret_val; + uint16_t swfw; DEBUGFUNC("em_phy_hw_reset"); @@ -2949,22 +3505,37 @@ DEBUGOUT("Resetting Phy...\n"); if(hw->mac_type > em_82543) { - /* - * Read the device control register and assert the E1000_CTRL_PHY_RST - * bit. Then, take it out of reset. - * For pre-em_82571 hardware, we delay for 10ms between the assert - * and deassert. For em_82571 hardware and later, we instead delay - * for 10ms after the deassertion. - */ - ctrl = E1000_READ_REG(hw, CTRL); - E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); - E1000_WRITE_FLUSH(hw); - if (hw->mac_type < em_82571) - msec_delay(10); - E1000_WRITE_REG(hw, CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - if (hw->mac_type >= em_82571) - msec_delay(10); + if ((hw->mac_type == em_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (em_swfw_sync_acquire(hw, swfw)) { + em_release_software_semaphore(hw); + return -E1000_ERR_SWFW_SYNC; + } + /* Read the device control register and assert the E1000_CTRL_PHY_RST + * bit. Then, take it out of reset. + * For pre-em_82571 hardware, we delay for 10ms between the assert + * and deassert. For em_82571 hardware and later, we instead delay + * for 50us between and 10ms after the deassertion. + */ + ctrl = E1000_READ_REG(hw, CTRL); + E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); + E1000_WRITE_FLUSH(hw); + + if (hw->mac_type < em_82571) + msec_delay(10); + else + usec_delay(100); + + E1000_WRITE_REG(hw, CTRL, ctrl); + E1000_WRITE_FLUSH(hw); + + if (hw->mac_type >= em_82571) + msec_delay(10); + em_swfw_sync_release(hw, swfw); } else { /* Read the Extended Device Control Register, assert the PHY_RESET_DIR * bit to put the PHY into reset. Then, take it out of reset. @@ -2991,6 +3562,7 @@ /* Wait for FW to finish PHY configuration. */ ret_val = em_get_phy_cfg_done(hw); + em_release_software_semaphore(hw); return ret_val; } @@ -3061,12 +3633,22 @@ /* 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->phy_id = IGP01E1000_I_PHY_ID; - hw->phy_type = em_phy_igp_2; - return E1000_SUCCESS; + if(hw->mac_type == em_82571 || + hw->mac_type == em_82572) { + hw->phy_id = IGP01E1000_I_PHY_ID; + hw->phy_type = em_phy_igp_2; + 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) @@ -3104,6 +3686,9 @@ case em_82573: if(hw->phy_id == M88E1111_I_PHY_ID) match = TRUE; break; + case em_80003es2lan: + if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE; + break; default: DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type); return -E1000_ERR_CONFIG; @@ -3130,8 +3715,10 @@ DEBUGFUNC("em_phy_reset_dsp"); do { - ret_val = em_write_phy_reg(hw, 29, 0x001d); - if(ret_val) break; + if (hw->phy_type != em_phy_gg82563) { + ret_val = em_write_phy_reg(hw, 29, 0x001d); + if(ret_val) break; + } ret_val = em_write_phy_reg(hw, 30, 0x00c1); if(ret_val) break; ret_val = em_write_phy_reg(hw, 30, 0x0000); @@ -3263,8 +3850,17 @@ /* Cable Length Estimation and Local/Remote Receiver Information * are only valid at 1000 Mbps. */ - phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT); + if (hw->phy_type != em_phy_gg82563) { + phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + M88E1000_PSSR_CABLE_LENGTH_SHIFT); + } else { + ret_val = em_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE, + &phy_data); + if (ret_val) + return ret_val; + + phy_info->cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH; + } ret_val = em_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); if(ret_val) @@ -3345,7 +3941,8 @@ /****************************************************************************** * Sets up eeprom variables in the hw struct. Must be called after mac_type - * is configured. + * is configured. Additionally, if this is ICH8, the flash controller GbE + * registers must be mapped, or this will crash. * * hw - Struct containing variables accessed by shared code *****************************************************************************/ @@ -3422,19 +4019,19 @@ break; case em_82571: case em_82572: - eeprom->type = em_eeprom_spi; - eeprom->opcode_bits = 8; - eeprom->delay_usec = 1; - if (eecd & E1000_EECD_ADDR_BITS) { - eeprom->page_size = 32; - eeprom->address_bits = 16; - } else { - eeprom->page_size = 8; - eeprom->address_bits = 8; - } - eeprom->use_eerd = FALSE; - eeprom->use_eewr = FALSE; - break; + eeprom->type = em_eeprom_spi; + eeprom->opcode_bits = 8; + eeprom->delay_usec = 1; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->page_size = 32; + eeprom->address_bits = 16; + } else { + eeprom->page_size = 8; + eeprom->address_bits = 8; + } + eeprom->use_eerd = FALSE; + eeprom->use_eewr = FALSE; + break; case em_82573: eeprom->type = em_eeprom_spi; eeprom->opcode_bits = 8; @@ -3458,6 +4055,20 @@ E1000_WRITE_REG(hw, EECD, eecd); } break; + case em_80003es2lan: + eeprom->type = em_eeprom_spi; + eeprom->opcode_bits = 8; + eeprom->delay_usec = 1; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->page_size = 32; + eeprom->address_bits = 16; + } else { + eeprom->page_size = 8; + eeprom->address_bits = 8; + } + eeprom->use_eerd = TRUE; + eeprom->use_eewr = FALSE; + break; default: break; } @@ -3638,32 +4249,31 @@ DEBUGFUNC("em_acquire_eeprom"); - if(em_get_hw_eeprom_semaphore(hw)) - return -E1000_ERR_EEPROM; - + if (em_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM)) + return -E1000_ERR_SWFW_SYNC; eecd = E1000_READ_REG(hw, EECD); if (hw->mac_type != em_82573) { - /* Request EEPROM Access */ - if(hw->mac_type > em_82544) { - eecd |= E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - eecd = E1000_READ_REG(hw, EECD); - while((!(eecd & E1000_EECD_GNT)) && - (i < E1000_EEPROM_GRANT_ATTEMPTS)) { - i++; - usec_delay(5); - eecd = E1000_READ_REG(hw, EECD); - } - if(!(eecd & E1000_EECD_GNT)) { - eecd &= ~E1000_EECD_REQ; + /* Request EEPROM Access */ + if(hw->mac_type > em_82544) { + eecd |= E1000_EECD_REQ; E1000_WRITE_REG(hw, EECD, eecd); - DEBUGOUT("Could not acquire EEPROM grant\n"); - em_put_hw_eeprom_semaphore(hw); - return -E1000_ERR_EEPROM; + eecd = E1000_READ_REG(hw, EECD); + while((!(eecd & E1000_EECD_GNT)) && + (i < E1000_EEPROM_GRANT_ATTEMPTS)) { + i++; + usec_delay(5); + eecd = E1000_READ_REG(hw, EECD); + } + if(!(eecd & E1000_EECD_GNT)) { + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + DEBUGOUT("Could not acquire EEPROM grant\n"); + em_swfw_sync_release(hw, E1000_SWFW_EEP_SM); + return -E1000_ERR_EEPROM; + } } } - } /* Setup EEPROM for Read/Write */ @@ -3782,7 +4392,7 @@ E1000_WRITE_REG(hw, EECD, eecd); } - em_put_hw_eeprom_semaphore(hw); + em_swfw_sync_release(hw, E1000_SWFW_EEP_SM); } /****************************************************************************** @@ -3857,17 +4467,21 @@ return -E1000_ERR_EEPROM; } - /* FLASH reads without acquiring the semaphore are safe in 82573-based - * controllers. - */ - if ((em_is_onboard_nvm_eeprom(hw) == TRUE) || - (hw->mac_type != em_82573)) { - /* Prepare the EEPROM for reading */ - if(em_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; + /* FLASH reads without acquiring the semaphore are safe */ + if (em_is_onboard_nvm_eeprom(hw) == TRUE && + hw->eeprom.use_eerd == FALSE) { + switch (hw->mac_type) { + case em_80003es2lan: + break; + default: + /* Prepare the EEPROM for reading */ + if (em_acquire_eeprom(hw) != E1000_SUCCESS) + return -E1000_ERR_EEPROM; + break; + } } - if(eeprom->use_eerd == TRUE) { + if (eeprom->use_eerd == TRUE) { ret_val = em_read_eeprom_eerd(hw, offset, words, data); if ((em_is_onboard_nvm_eeprom(hw) == TRUE) || (hw->mac_type != em_82573)) @@ -3976,6 +4590,9 @@ uint32_t i = 0; int32_t error = 0; + if (em_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM)) + return -E1000_ERR_SWFW_SYNC; + for (i = 0; i < words; i++) { register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | @@ -3995,6 +4612,7 @@ } } + em_swfw_sync_release(hw, E1000_SWFW_EEP_SM); return error; } @@ -4036,6 +4654,8 @@ { uint32_t eecd = 0; + DEBUGFUNC("em_is_onboard_nvm_eeprom"); + if(hw->mac_type == em_82573) { eecd = E1000_READ_REG(hw, EECD); @@ -4374,7 +4994,7 @@ return -E1000_ERR_EEPROM; } - /* If STM opcode located in bits 15:8 of flop, reset firmware */ + /* If STM opcode located in bits 15:8 of flop, reset firmware */ if ((flop & 0xFF00) == E1000_STM_OPCODE) { E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET); } @@ -4382,7 +5002,7 @@ /* Perform the flash update */ E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD); - for (i=0; i < attempts; i++) { + for (i=0; i < attempts; i++) { eecd = E1000_READ_REG(hw, EECD); if ((eecd & E1000_EECD_FLUPD) == 0) { break; @@ -4455,14 +5075,17 @@ hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF); hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8); } + switch (hw->mac_type) { + default: + break; case em_82546: case em_82546_rev_3: case em_82571: - if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) - hw->perm_mac_addr[5] ^= 0x01; - default: - break; + case em_80003es2lan: + if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) + hw->perm_mac_addr[5] ^= 0x01; + break; } for(i = 0; i < NODE_ADDRESS_SIZE; i++) @@ -4498,7 +5121,7 @@ * an 82571 issue in which a reset on one port will reload the MAC on * the other port. */ if ((hw->mac_type == em_82571) && (hw->laa_is_present == TRUE)) - rar_num -= 1; + rar_num -= 1; /* Zero out the other 15 receive addresses. */ DEBUGOUT("Clearing RAR[1-15]\n"); for(i = 1; i < rar_num; i++) { @@ -4545,7 +5168,7 @@ * an 82571 issue in which a reset on one port will reload the MAC on * the other port. */ if ((hw->mac_type == em_82571) && (hw->laa_is_present == TRUE)) - num_rar_entry -= 1; + num_rar_entry -= 1; for(i = rar_used_count; i < num_rar_entry; i++) { E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); @@ -4696,8 +5319,37 @@ rar_low = ((uint32_t) addr[0] | ((uint32_t) addr[1] << 8) | ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24)); + rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8)); - rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8) | E1000_RAH_AV); + /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx + * unit hang. + * + * Description: + * If there are any Rx frames queued up or otherwise present in the HW + * before RSS is enabled, and then we enable RSS, the HW Rx unit will + * hang. To work around this issue, we have to disable receives and + * flush out all Rx frames before we enable RSS. To do so, we modify we + * redirect all Rx traffic to manageability and then reset the HW. + * This flushes away Rx frames, and (since the redirections to + * manageability persists across resets) keeps new ones from coming in + * while we work. Then, we clear the Address Valid AV bit for all MAC + * addresses and undo the re-direction to manageability. + * Now, frames are coming in again, but the MAC won't accept them, so + * far so good. We now proceed to initialize RSS (if necessary) and + * configure the Rx unit. Last, we re-enable the AV bits and continue + * on our merry way. + */ + switch (hw->mac_type) { + case em_82571: + case em_82572: + case em_80003es2lan: + if (hw->leave_av_bit_off == TRUE) + break; + default: + /* Indicate to hardware the Address is Valid. */ + rar_high |= E1000_RAH_AV; + break; + } E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low); E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high); @@ -5104,7 +5756,6 @@ temp = E1000_READ_REG(hw, ICTXQEC); temp = E1000_READ_REG(hw, ICTXQMTC); temp = E1000_READ_REG(hw, ICRXDMTC); - } /****************************************************************************** @@ -5275,11 +5926,12 @@ case em_82573: hw->bus_type = em_bus_type_pci_express; hw->bus_speed = em_bus_speed_2500; - hw->bus_width = em_bus_width_pciex_1; - break; + hw->bus_width = em_bus_width_pciex_1; + break; case em_82571: - hw->bus_type = em_bus_type_pci_express; - hw->bus_speed = em_bus_speed_2500; + case em_80003es2lan: + hw->bus_type = em_bus_type_pci_express; + hw->bus_speed = em_bus_speed_2500; hw->bus_width = em_bus_width_pciex_4; break; default: @@ -5375,7 +6027,7 @@ { int32_t ret_val; uint16_t agc_value = 0; - uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE; + uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1; uint16_t max_agc = 0; uint16_t i, phy_data; uint16_t cable_length; @@ -5420,6 +6072,34 @@ return -E1000_ERR_PHY; break; } + } else if (hw->phy_type == em_phy_gg82563) { + ret_val = em_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE, + &phy_data); + if (ret_val) + return ret_val; + cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH; + + switch (cable_length) { + case em_gg_cable_length_60: + *min_length = 0; + *max_length = em_igp_cable_length_60; + break; + case em_gg_cable_length_60_115: + *min_length = em_igp_cable_length_60; + *max_length = em_igp_cable_length_115; + break; + case em_gg_cable_length_115_150: + *min_length = em_igp_cable_length_115; + *max_length = em_igp_cable_length_150; + break; + case em_gg_cable_length_150: + *min_length = em_igp_cable_length_150; + *max_length = em_igp_cable_length_180; + break; + default: + return -E1000_ERR_PHY; + break; + } } else if(hw->phy_type == em_phy_igp) { /* For IGP PHY */ uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {IGP01E1000_PHY_AGC_A, @@ -5466,50 +6146,39 @@ *max_length = em_igp_cable_length_table[agc_value] + IGP01E1000_AGC_RANGE; } else if (hw->phy_type == em_phy_igp_2) { - uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = - {IGP02E1000_PHY_AGC_A, - IGP02E1000_PHY_AGC_B, - IGP02E1000_PHY_AGC_C, - IGP02E1000_PHY_AGC_D}; - - /* Read the AGC registers for all channels */ - for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { - ret_val = em_read_phy_reg(hw, agc_reg_array[i], - &phy_data); - if (ret_val) - return ret_val; - - /* - * Getting bits 15:9, which represent the combination - * of course and fine gain values. The result is a - * number that can be put into the lookup table to - * obtain the approximate cable length. - */ - cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & - IGP02E1000_AGC_LENGTH_MASK; - - /* Remove min & max AGC values from calculation. */ - if (em_igp_2_cable_length_table[min_agc] > - em_igp_2_cable_length_table[cur_agc]) - min_agc = cur_agc; - if (em_igp_2_cable_length_table[max_agc] < - em_igp_2_cable_length_table[cur_agc]) - max_agc = cur_agc; - - agc_value += em_igp_2_cable_length_table[cur_agc]; - } - - agc_value -= (em_igp_2_cable_length_table[min_agc] + - em_igp_2_cable_length_table[max_agc]); - agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); - - /* - * Calculate cable length with the error range - * of +/- 10 meters. - */ - *min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? - (agc_value - IGP02E1000_AGC_RANGE) : 0; - *max_length = agc_value + IGP02E1000_AGC_RANGE; + uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = + {IGP02E1000_PHY_AGC_A, + IGP02E1000_PHY_AGC_B, + IGP02E1000_PHY_AGC_C, + IGP02E1000_PHY_AGC_D}; + /* Read the AGC registers for all channels */ + for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { + ret_val = em_read_phy_reg(hw, agc_reg_array[i], &phy_data); + if (ret_val) + return ret_val; + + /* Getting bits 15:9, which represent the combination of course and + * fine gain values. The result is a number that can be put into + * the lookup table to obtain the approximate cable length. */ + cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & + IGP02E1000_AGC_LENGTH_MASK; + + /* Remove min & max AGC values from calculation. */ + if (em_igp_2_cable_length_table[min_agc] > em_igp_2_cable_length_table[cur_agc]) + min_agc = cur_agc; + if (em_igp_2_cable_length_table[max_agc] < em_igp_2_cable_length_table[cur_agc]) + max_agc = cur_agc; + + agc_value += em_igp_2_cable_length_table[cur_agc]; + } + + agc_value -= (em_igp_2_cable_length_table[min_agc] + em_igp_2_cable_length_table[max_agc]); + agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); + + /* Calculate cable length with the error range of +/- 10 meters. */ + *min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? + (agc_value - IGP02E1000_AGC_RANGE) : 0; + *max_length = agc_value + IGP02E1000_AGC_RANGE; } return E1000_SUCCESS; @@ -5540,7 +6209,8 @@ DEBUGFUNC("em_check_polarity"); - if(hw->phy_type == em_phy_m88) { + if ((hw->phy_type == em_phy_m88) || + (hw->phy_type == em_phy_gg82563)) { /* return the Polarity bit in the Status register. */ ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); @@ -5609,7 +6279,8 @@ return ret_val; hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; - } else if(hw->phy_type == em_phy_m88) { + } else if ((hw->phy_type == em_phy_m88) || + (hw->phy_type == em_phy_gg82563)) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if(ret_val) @@ -6634,9 +7305,13 @@ DEBUGFUNC("em_get_auto_rd_done"); switch (hw->mac_type) { - case em_82573: + default: + msec_delay(5); + break; case em_82571: case em_82572: + case em_82573: + case em_80003es2lan: while(timeout) { if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break; else msec_delay(1); @@ -6648,15 +7323,13 @@ return -E1000_ERR_RESET; } break; - default: - msec_delay(5); } /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high. * Need to wait for PHY configuration completion before accessing NVM * and PHY. */ if (hw->mac_type == em_82573) - msec_delay(25); + msec_delay(25); return E1000_SUCCESS; } @@ -6673,32 +7346,38 @@ int32_t em_get_phy_cfg_done(struct em_hw *hw) { - int32_t timeout = PHY_CFG_TIMEOUT; - uint32_t cfg_mask = E1000_EEPROM_CFG_DONE; + int32_t timeout = PHY_CFG_TIMEOUT; + uint32_t cfg_mask = E1000_EEPROM_CFG_DONE; - DEBUGFUNC("em_get_phy_cfg_done"); + DEBUGFUNC("em_get_phy_cfg_done"); + + switch (hw->mac_type) { + default: + msec_delay(10); + break; + case em_80003es2lan: + /* Separate *_CFG_DONE_* bit for each port */ + if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) + cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1; + /* Fall Through */ + case em_82571: + case em_82572: + while (timeout) { + if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask) + break; + else + msec_delay(1); + timeout--; + } - switch (hw->mac_type) { - case em_82571: - case em_82572: - while (timeout) { - if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask) - break; - else - msec_delay(1); - timeout--; - } - - if (!timeout) { - DEBUGOUT("MNG configuration cycle has not completed.\n"); - return -E1000_ERR_RESET; - } - break; - default: - msec_delay(10); - } + if (!timeout) { + DEBUGOUT("MNG configuration cycle has not completed.\n"); + return -E1000_ERR_RESET; + } + break; + } - return E1000_SUCCESS; + return E1000_SUCCESS; } /*************************************************************************** @@ -6723,6 +7402,11 @@ if(!hw->eeprom_semaphore_present) return E1000_SUCCESS; + if (hw->mac_type == em_80003es2lan) { + /* Get the SW semaphore. */ + if (em_get_software_semaphore(hw) != E1000_SUCCESS) + return -E1000_ERR_EEPROM; + } /* Get the FW semaphore. */ timeout = hw->eeprom.word_size + 1; @@ -6768,7 +7452,72 @@ return; swsm = E1000_READ_REG(hw, SWSM); - swsm &= ~(E1000_SWSM_SWESMBI); + if (hw->mac_type == em_80003es2lan) { + /* Release both semaphores. */ + swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); + } else + swsm &= ~(E1000_SWSM_SWESMBI); + E1000_WRITE_REG(hw, SWSM, swsm); +} + +/*************************************************************************** + * + * Obtaining software semaphore bit (SMBI) before resetting PHY. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_RESET if fail to obtain semaphore. + * E1000_SUCCESS at any other case. + * + ***************************************************************************/ +int32_t +em_get_software_semaphore(struct em_hw *hw) +{ + int32_t timeout = hw->eeprom.word_size + 1; + uint32_t swsm; + + DEBUGFUNC("em_get_software_semaphore"); + + if (hw->mac_type != em_80003es2lan) + return E1000_SUCCESS; + + while(timeout) { + swsm = E1000_READ_REG(hw, SWSM); + /* If SMBI bit cleared, it is now set and we hold the semaphore */ + if(!(swsm & E1000_SWSM_SMBI)) + break; + msec_delay_irq(1); + timeout--; + } + + if(!timeout) { + DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); + return -E1000_ERR_RESET; + } + + return E1000_SUCCESS; +} + +/*************************************************************************** + * + * Release semaphore bit (SMBI). + * + * hw: Struct containing variables accessed by shared code + * + ***************************************************************************/ +void +em_release_software_semaphore(struct em_hw *hw) +{ + uint32_t swsm; + + DEBUGFUNC("em_release_software_semaphore"); + + if (hw->mac_type != em_80003es2lan) + return; + + swsm = E1000_READ_REG(hw, SWSM); + /* Release the SW semaphores.*/ + swsm &= ~E1000_SWSM_SMBI; E1000_WRITE_REG(hw, SWSM, swsm); } @@ -6787,6 +7536,7 @@ em_check_phy_reset_block(struct em_hw *hw) { uint32_t manc = 0; + if (hw->mac_type > em_82547_rev_2) manc = E1000_READ_REG(hw, MANC); return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? @@ -6807,6 +7557,7 @@ case em_82571: case em_82572: case em_82573: + case em_80003es2lan: fwsm = E1000_READ_REG(hw, FWSM); if((fwsm & E1000_FWSM_MODE_MASK) != 0) return TRUE; Index: if_em_hw.h =================================================================== RCS file: /usr/cvs/src/sys/dev/em/if_em_hw.h,v retrieving revision 1.15.2.2 diff -u -r1.15.2.2 if_em_hw.h --- if_em_hw.h 25 Nov 2005 14:11:59 -0000 1.15.2.2 +++ if_em_hw.h 13 Jul 2006 14:00:42 -0000 @@ -66,6 +66,7 @@ em_82571, em_82572, em_82573, + em_80003es2lan, em_num_macs } em_mac_type; @@ -145,6 +146,13 @@ } em_cable_length; typedef enum { + em_gg_cable_length_60 = 0, + em_gg_cable_length_60_115 = 1, + em_gg_cable_length_115_150 = 2, + em_gg_cable_length_150 = 4 +} em_gg_cable_length; + +typedef enum { em_igp_cable_length_10 = 10, em_igp_cable_length_20 = 20, em_igp_cable_length_30 = 30, @@ -214,6 +222,7 @@ em_phy_m88 = 0, em_phy_igp, em_phy_igp_2, + em_phy_gg82563, em_phy_undefined = 0xFF } em_phy_type; @@ -287,6 +296,7 @@ #define E1000_ERR_MASTER_REQUESTS_PENDING 10 #define E1000_ERR_HOST_INTERFACE_COMMAND 11 #define E1000_BLK_PHY_RESET 12 +#define E1000_ERR_SWFW_SYNC 13 /* Function prototypes */ /* Initialization */ @@ -319,6 +329,9 @@ int32_t em_check_polarity(struct em_hw *hw, uint16_t *polarity); int32_t em_check_downshift(struct em_hw *hw); int32_t em_validate_mdi_setting(struct em_hw *hw); +int32_t em_read_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *data); +int32_t em_write_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data); +int32_t em_duplex_reversal(struct em_hw *hw); /* EEPROM Functions */ int32_t em_init_eeprom_params(struct em_hw *hw); @@ -357,18 +370,6 @@ struct em_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */ uint8_t command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658*/ }; -#ifdef __BIG_ENDIAN -struct em_host_mng_dhcp_cookie{ - uint32_t signature; - uint16_t vlan_id; - uint8_t reserved0; - uint8_t status; - uint32_t reserved1; - uint8_t checksum; - uint8_t reserved3; - uint16_t reserved2; -}; -#else struct em_host_mng_dhcp_cookie{ uint32_t signature; uint8_t status; @@ -379,7 +380,6 @@ uint8_t reserved3; uint8_t checksum; }; -#endif int32_t em_mng_write_dhcp_info(struct em_hw *hw, uint8_t *buffer, uint16_t length); @@ -447,6 +447,7 @@ void em_put_hw_eeprom_semaphore(struct em_hw *hw); int32_t em_commit_shadow_ram(struct em_hw *hw); uint8_t em_arc_subsystem_valid(struct em_hw *hw); +int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop); #define E1000_BAR_TYPE(v) ((v) & E1000_BAR_TYPE_MASK) #define E1000_BAR_TYPE_MASK 0x00000001 @@ -457,10 +458,12 @@ #define E1000_BAR_MEM_TYPE_32BIT 0x00000000 #define E1000_BAR_MEM_TYPE_64BIT 0x00000004 +#ifndef E1000_READ_REG_IO #define E1000_READ_REG_IO(a, reg) \ em_read_reg_io((a), E1000_##reg) #define E1000_WRITE_REG_IO(a, reg, val) \ em_write_reg_io((a), E1000_##reg, val) +#endif /* PCI Device IDs */ #define E1000_DEV_ID_82542 0x1000 @@ -495,6 +498,7 @@ #define E1000_DEV_ID_82546GB_FIBER 0x107A #define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82546GB_PCIE 0x108A +#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 #define E1000_DEV_ID_82547EI 0x1019 #define E1000_DEV_ID_82547EI_MOBILE 0x101A #define E1000_DEV_ID_82571EB_COPPER 0x105E @@ -503,11 +507,14 @@ #define E1000_DEV_ID_82572EI_COPPER 0x107D #define E1000_DEV_ID_82572EI_FIBER 0x107E #define E1000_DEV_ID_82572EI_SERDES 0x107F +#define E1000_DEV_ID_82572EI 0x10B9 #define E1000_DEV_ID_82573E 0x108B #define E1000_DEV_ID_82573E_IAMT 0x108C #define E1000_DEV_ID_82573L 0x109A +#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5 +#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 +#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 -#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -866,7 +873,8 @@ #define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX #define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX #define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX -#define E1000_DISABLE_SERDES_LOOPBACK 0x0400 + +#define E1000_DISABLE_SERDES_LOOPBACK 0x0400 /* Register Set. (82543, 82544) * @@ -910,6 +918,7 @@ #define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ #define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ #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 */ #define E1000_TBT 0x00448 /* TX Burst Timer - RW */ #define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ @@ -962,14 +971,14 @@ #define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */ #define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */ #define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ -#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */ -#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */ -#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */ -#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */ -#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */ -#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */ -#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */ -#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */ +#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */ +#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */ +#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */ +#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */ +#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */ +#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */ +#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */ +#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */ #define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ #define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ #define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ @@ -1056,6 +1065,11 @@ #define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ #define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ +#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */ +#define E1000_MDPHYA 0x0003C /* PHY address - RW */ +#define E1000_MANC2H 0x05860 /* Managment Control To Host - RW */ +#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ + #define E1000_GCR 0x05B00 /* PCI-Ex Control */ #define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ #define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ @@ -1125,6 +1139,7 @@ #define E1000_82542_RXCW E1000_RXCW #define E1000_82542_MTA 0x00200 #define E1000_82542_TCTL E1000_TCTL +#define E1000_82542_TCTL_EXT E1000_TCTL_EXT #define E1000_82542_TIPG E1000_TIPG #define E1000_82542_TDBAL 0x00420 #define E1000_82542_TDBAH 0x00424 @@ -1272,6 +1287,8 @@ #define E1000_82542_RSSRK E1000_RSSRK #define E1000_82542_RSSIM E1000_RSSIM #define E1000_82542_RSSIR E1000_RSSIR +#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA +#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC /* Statistics counters collected by the MAC */ struct em_hw_stats { @@ -1363,6 +1380,7 @@ em_ffe_config ffe_config_state; uint32_t asf_firmware_present; uint32_t eeprom_semaphore_present; + uint32_t swfw_sync_present; unsigned long io_base; uint32_t phy_id; uint32_t phy_revision; @@ -1421,6 +1439,7 @@ boolean_t ifs_params_forced; boolean_t in_ifs_mode; boolean_t mng_reg_access_disabled; + boolean_t leave_av_bit_off; }; @@ -1453,6 +1472,8 @@ #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ #define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ #define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ +#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */ +#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ #define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ @@ -1489,6 +1510,16 @@ #define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ #define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ #define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ +#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */ +#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */ +#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */ +#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */ +#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */ +#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */ +#define E1000_STATUS_FUSE_8 0x04000000 +#define E1000_STATUS_FUSE_9 0x08000000 +#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. */ #define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ @@ -1562,9 +1593,12 @@ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ #define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ #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 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 #define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 +#define E1000_CTRL_EXT_LINK_MODE_SERDES 0x00C00000 #define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 #define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 #define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 @@ -1574,6 +1608,9 @@ #define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ #define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ #define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ +#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */ +#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ +#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 /* MDI Control */ #define E1000_MDIC_DATA_MASK 0x0000FFFF @@ -1587,6 +1624,32 @@ #define E1000_MDIC_INT_EN 0x20000000 #define E1000_MDIC_ERROR 0x40000000 +#define E1000_KUMCTRLSTA_MASK 0x0000FFFF +#define E1000_KUMCTRLSTA_OFFSET 0x001F0000 +#define E1000_KUMCTRLSTA_OFFSET_SHIFT 16 +#define E1000_KUMCTRLSTA_REN 0x00200000 + +#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL 0x00000000 +#define E1000_KUMCTRLSTA_OFFSET_CTRL 0x00000001 +#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL 0x00000002 +#define E1000_KUMCTRLSTA_OFFSET_DIAG 0x00000003 +#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS 0x00000004 +#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM 0x00000009 +#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL 0x00000010 +#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES 0x0000001E +#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES 0x0000001F + +/* FIFO Control */ +#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS 0x00000008 +#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS 0x00000800 + +/* In-Band Control */ +#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING 0x00000010 + +/* Half-Duplex Control */ +#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004 +#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT 0x00000000 + /* LED Control */ #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 @@ -1649,6 +1712,13 @@ #define E1000_ICR_MNG 0x00040000 /* Manageability event */ #define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ #define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ +#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */ +#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ +#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */ /* Interrupt Cause Set */ #define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1669,6 +1739,12 @@ #define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ +#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1689,6 +1765,12 @@ #define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ +#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ /* Interrupt Mask Clear */ #define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1709,6 +1791,12 @@ #define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_IMC_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#define E1000_IMC_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ +#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ /* Receive Control */ #define E1000_RCTL_RST 0x00000001 /* Software reset */ @@ -1778,6 +1866,12 @@ #define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ #define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ +/* SW_W_SYNC definitions */ +#define E1000_SWFW_EEP_SM 0x0001 +#define E1000_SWFW_PHY0_SM 0x0002 +#define E1000_SWFW_PHY1_SM 0x0004 +#define E1000_SWFW_MAC_CSR_SM 0x0008 + /* Receive Descriptor */ #define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ #define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */ @@ -1823,7 +1917,6 @@ #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ #define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc. still to be processed. */ - /* Transmit Configuration Word */ #define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ #define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ @@ -1857,6 +1950,11 @@ #define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ #define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ #define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ +/* Extended Transmit Control */ +#define E1000_TCTL_EXT_BST_MASK 0x000003FF /* Backoff Slot Time */ +#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ + +#define DEFAULT_80003ES2LAN_TCTL_EXT_GCEX 0x00010000 /* Receive Checksum Control */ #define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ @@ -1934,6 +2032,7 @@ #define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ #define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ +#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */ #define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ #define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address * filtering */ @@ -2019,6 +2118,23 @@ #define E1000_MDALIGN 4096 +/* PCI-Ex registers*/ + +/* PCI-Ex Control Register */ +#define E1000_GCR_RXD_NO_SNOOP 0x00000001 +#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 +#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 +#define E1000_GCR_TXD_NO_SNOOP 0x00000008 +#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 +#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 + +#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ + E1000_GCR_RXDSCW_NO_SNOOP | \ + E1000_GCR_RXDSCR_NO_SNOOP | \ + E1000_GCR_TXD_NO_SNOOP | \ + E1000_GCR_TXDSCW_NO_SNOOP | \ + E1000_GCR_TXDSCR_NO_SNOOP) + #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 /* Function Active and Power State to MNG */ #define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003 @@ -2078,12 +2194,14 @@ #define EEPROM_INIT_CONTROL1_REG 0x000A #define EEPROM_INIT_CONTROL2_REG 0x000F #define EEPROM_INIT_CONTROL3_PORT_B 0x0014 +#define EEPROM_INIT_3GIO_3 0x001A #define EEPROM_INIT_CONTROL3_PORT_A 0x0024 #define EEPROM_CFG 0x0012 #define EEPROM_FLASH_VERSION 0x0032 #define EEPROM_CHECKSUM_REG 0x003F #define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */ +#define E1000_EEPROM_CFG_DONE_PORT_1 0x00080000 /* ...for second port */ /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 @@ -2127,6 +2245,9 @@ #define EEPROM_WORD0F_ANE 0x0800 #define EEPROM_WORD0F_SWPDIO_EXT 0x00F0 +/* Mask bits for fields in Word 0x1a of the EEPROM */ +#define EEPROM_WORD1A_ASPM_MASK 0x000C + /* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */ #define EEPROM_SUM 0xBABA @@ -2142,7 +2263,10 @@ /* Collision related configuration parameters */ #define E1000_COLLISION_THRESHOLD 15 #define E1000_CT_SHIFT 4 -#define E1000_COLLISION_DISTANCE 64 +/* Collision distance is a 0-based value that applies to + * half-duplex-capable hardware only. */ +#define E1000_COLLISION_DISTANCE 63 +#define E1000_COLLISION_DISTANCE_82542 64 #define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_COLD_SHIFT 12 @@ -2166,8 +2290,11 @@ #define DEFAULT_82542_TIPG_IPGR2 10 #define DEFAULT_82543_TIPG_IPGR2 6 +#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7 #define E1000_TIPG_IPGR2_SHIFT 20 +#define DEFAULT_80003ES2LAN_TIPG_IPGT_10_100 0x00000009 +#define DEFAULT_80003ES2LAN_TIPG_IPGT_1000 0x00000008 #define E1000_TXDMAC_DPP 0x00000001 /* Adaptive IFS defines */ @@ -2408,6 +2535,79 @@ #define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 +/* Bits... + * 15-5: page + * 4-0: register offset + */ +#define GG82563_PAGE_SHIFT 5 +#define GG82563_REG(page, reg) \ + (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) +#define GG82563_MIN_ALT_REG 30 + +/* GG82563 Specific Registers */ +#define GG82563_PHY_SPEC_CTRL \ + GG82563_REG(0, 16) /* PHY Specific Control */ +#define GG82563_PHY_SPEC_STATUS \ + GG82563_REG(0, 17) /* PHY Specific Status */ +#define GG82563_PHY_INT_ENABLE \ + GG82563_REG(0, 18) /* Interrupt Enable */ +#define GG82563_PHY_SPEC_STATUS_2 \ + GG82563_REG(0, 19) /* PHY Specific Status 2 */ +#define GG82563_PHY_RX_ERR_CNTR \ + GG82563_REG(0, 21) /* Receive Error Counter */ +#define GG82563_PHY_PAGE_SELECT \ + GG82563_REG(0, 22) /* Page Select */ +#define GG82563_PHY_SPEC_CTRL_2 \ + GG82563_REG(0, 26) /* PHY Specific Control 2 */ +#define GG82563_PHY_PAGE_SELECT_ALT \ + GG82563_REG(0, 29) /* Alternate Page Select */ +#define GG82563_PHY_TEST_CLK_CTRL \ + GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */ + +#define GG82563_PHY_MAC_SPEC_CTRL \ + GG82563_REG(2, 21) /* MAC Specific Control Register */ +#define GG82563_PHY_MAC_SPEC_CTRL_2 \ + GG82563_REG(2, 26) /* MAC Specific Control 2 */ + +#define GG82563_PHY_DSP_DISTANCE \ + GG82563_REG(5, 26) /* DSP Distance */ + +/* Page 193 - Port Control Registers */ +#define GG82563_PHY_KMRN_MODE_CTRL \ + GG82563_REG(193, 16) /* Kumeran Mode Control */ +#define GG82563_PHY_PORT_RESET \ + GG82563_REG(193, 17) /* Port Reset */ +#define GG82563_PHY_REVISION_ID \ + GG82563_REG(193, 18) /* Revision ID */ +#define GG82563_PHY_DEVICE_ID \ + GG82563_REG(193, 19) /* Device ID */ +#define GG82563_PHY_PWR_MGMT_CTRL \ + GG82563_REG(193, 20) /* Power Management Control */ +#define GG82563_PHY_RATE_ADAPT_CTRL \ + GG82563_REG(193, 25) /* Rate Adaptation Control */ + +/* Page 194 - KMRN Registers */ +#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \ + GG82563_REG(194, 16) /* FIFO's Control/Status */ +#define GG82563_PHY_KMRN_CTRL \ + GG82563_REG(194, 17) /* Control */ +#define GG82563_PHY_INBAND_CTRL \ + GG82563_REG(194, 18) /* Inband Control */ +#define GG82563_PHY_KMRN_DIAGNOSTIC \ + GG82563_REG(194, 19) /* Diagnostic */ +#define GG82563_PHY_ACK_TIMEOUTS \ + GG82563_REG(194, 20) /* Acknowledge Timeouts */ +#define GG82563_PHY_ADV_ABILITY \ + GG82563_REG(194, 21) /* Advertised Ability */ +#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \ + GG82563_REG(194, 23) /* Link Partner Advertised Ability */ +#define GG82563_PHY_ADV_NEXT_PAGE \ + GG82563_REG(194, 24) /* Advertised Next Page */ +#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \ + GG82563_REG(194, 25) /* Link Partner Advertised Next page */ +#define GG82563_PHY_KMRN_MISC \ + GG82563_REG(194, 26) /* Misc. */ + /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ @@ -2720,6 +2920,113 @@ #define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 #define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 +/* GG82563 PHY Specific Status Register (Page 0, Register 16 */ +#define GG82563_PSCR_DISABLE_JABBER 0x0001 /* 1=Disable Jabber */ +#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Polarity Reversal Disabled */ +#define GG82563_PSCR_POWER_DOWN 0x0004 /* 1=Power Down */ +#define GG82563_PSCR_COPPER_TRANSMITER_DISABLE 0x0008 /* 1=Transmitter Disabled */ +#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 +#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI configuration */ +#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX configuration */ +#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Automatic crossover */ +#define GG82563_PSCR_ENALBE_EXTENDED_DISTANCE 0x0080 /* 1=Enable Extended Distance */ +#define GG82563_PSCR_ENERGY_DETECT_MASK 0x0300 +#define GG82563_PSCR_ENERGY_DETECT_OFF 0x0000 /* 00,01=Off */ +#define GG82563_PSCR_ENERGY_DETECT_RX 0x0200 /* 10=Sense on Rx only (Energy Detect) */ +#define GG82563_PSCR_ENERGY_DETECT_RX_TM 0x0300 /* 11=Sense and Tx NLP */ +#define GG82563_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force Link Good */ +#define GG82563_PSCR_DOWNSHIFT_ENABLE 0x0800 /* 1=Enable Downshift */ +#define GG82563_PSCR_DOWNSHIFT_COUNTER_MASK 0x7000 +#define GG82563_PSCR_DOWNSHIFT_COUNTER_SHIFT 12 + +/* PHY Specific Status Register (Page 0, Register 17) */ +#define GG82563_PSSR_JABBER 0x0001 /* 1=Jabber */ +#define GG82563_PSSR_POLARITY 0x0002 /* 1=Polarity Reversed */ +#define GG82563_PSSR_LINK 0x0008 /* 1=Link is Up */ +#define GG82563_PSSR_ENERGY_DETECT 0x0010 /* 1=Sleep, 0=Active */ +#define GG82563_PSSR_DOWNSHIFT 0x0020 /* 1=Downshift */ +#define GG82563_PSSR_CROSSOVER_STATUS 0x0040 /* 1=MDIX, 0=MDI */ +#define GG82563_PSSR_RX_PAUSE_ENABLED 0x0100 /* 1=Receive Pause Enabled */ +#define GG82563_PSSR_TX_PAUSE_ENABLED 0x0200 /* 1=Transmit Pause Enabled */ +#define GG82563_PSSR_LINK_UP 0x0400 /* 1=Link Up */ +#define GG82563_PSSR_SPEED_DUPLEX_RESOLVED 0x0800 /* 1=Resolved */ +#define GG82563_PSSR_PAGE_RECEIVED 0x1000 /* 1=Page Received */ +#define GG82563_PSSR_DUPLEX 0x2000 /* 1-Full-Duplex */ +#define GG82563_PSSR_SPEED_MASK 0xC000 +#define GG82563_PSSR_SPEED_10MBPS 0x0000 /* 00=10Mbps */ +#define GG82563_PSSR_SPEED_100MBPS 0x4000 /* 01=100Mbps */ +#define GG82563_PSSR_SPEED_1000MBPS 0x8000 /* 10=1000Mbps */ + +/* PHY Specific Status Register 2 (Page 0, Register 19) */ +#define GG82563_PSSR2_JABBER 0x0001 /* 1=Jabber */ +#define GG82563_PSSR2_POLARITY_CHANGED 0x0002 /* 1=Polarity Changed */ +#define GG82563_PSSR2_ENERGY_DETECT_CHANGED 0x0010 /* 1=Energy Detect Changed */ +#define GG82563_PSSR2_DOWNSHIFT_INTERRUPT 0x0020 /* 1=Downshift Detected */ +#define GG82563_PSSR2_MDI_CROSSOVER_CHANGE 0x0040 /* 1=Crossover Changed */ +#define GG82563_PSSR2_FALSE_CARRIER 0x0100 /* 1=False Carrier */ +#define GG82563_PSSR2_SYMBOL_ERROR 0x0200 /* 1=Symbol Error */ +#define GG82563_PSSR2_LINK_STATUS_CHANGED 0x0400 /* 1=Link Status Changed */ +#define GG82563_PSSR2_AUTO_NEG_COMPLETED 0x0800 /* 1=Auto-Neg Completed */ +#define GG82563_PSSR2_PAGE_RECEIVED 0x1000 /* 1=Page Received */ +#define GG82563_PSSR2_DUPLEX_CHANGED 0x2000 /* 1=Duplex Changed */ +#define GG82563_PSSR2_SPEED_CHANGED 0x4000 /* 1=Speed Changed */ +#define GG82563_PSSR2_AUTO_NEG_ERROR 0x8000 /* 1=Auto-Neg Error */ + +/* PHY Specific Control Register 2 (Page 0, Register 26) */ +#define GG82563_PSCR2_10BT_POLARITY_FORCE 0x0002 /* 1=Force Negative Polarity */ +#define GG82563_PSCR2_1000MB_TEST_SELECT_MASK 0x000C +#define GG82563_PSCR2_1000MB_TEST_SELECT_NORMAL 0x0000 /* 00,01=Normal Operation */ +#define GG82563_PSCR2_1000MB_TEST_SELECT_112NS 0x0008 /* 10=Select 112ns Sequence */ +#define GG82563_PSCR2_1000MB_TEST_SELECT_16NS 0x000C /* 11=Select 16ns Sequence */ +#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Negotiation */ +#define GG82563_PSCR2_1000BT_DISABLE 0x4000 /* 1=Disable 1000BASE-T */ +#define GG82563_PSCR2_TRANSMITER_TYPE_MASK 0x8000 +#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_B 0x0000 /* 0=Class B */ +#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_A 0x8000 /* 1=Class A */ + +/* MAC Specific Control Register (Page 2, Register 21) */ +/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ +#define GG82563_MSCR_TX_CLK_MASK 0x0007 +#define GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ 0x0004 +#define GG82563_MSCR_TX_CLK_100MBPS_25MHZ 0x0005 +#define GG82563_MSCR_TX_CLK_1000MBPS_2_5MHZ 0x0006 +#define GG82563_MSCR_TX_CLK_1000MBPS_25MHZ 0x0007 + +#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ + +/* DSP Distance Register (Page 5, Register 26) */ +#define GG82563_DSPD_CABLE_LENGTH 0x0007 /* 0 = <50M; + 1 = 50-80M; + 2 = 80-110M; + 3 = 110-140M; + 4 = >140M */ + +/* Kumeran Mode Control Register (Page 193, Register 16) */ +#define GG82563_KMCR_PHY_LEDS_EN 0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */ +#define GG82563_KMCR_FORCE_LINK_UP 0x0040 /* 1=Force Link Up */ +#define GG82563_KMCR_SUPPRESS_SGMII_EPD_EXT 0x0080 +#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT_MASK 0x0400 +#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT 0x0400 /* 1=6.25MHz, 0=0.8MHz */ +#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 + +/* Power Management Control Register (Page 193, Register 20) */ +#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 /* 1=Enalbe SERDES Electrical Idle */ +#define GG82563_PMCR_DISABLE_PORT 0x0002 /* 1=Disable Port */ +#define GG82563_PMCR_DISABLE_SERDES 0x0004 /* 1=Disable SERDES */ +#define GG82563_PMCR_REVERSE_AUTO_NEG 0x0008 /* 1=Enable Reverse Auto-Negotiation */ +#define GG82563_PMCR_DISABLE_1000_NON_D0 0x0010 /* 1=Disable 1000Mbps Auto-Neg in non D0 */ +#define GG82563_PMCR_DISABLE_1000 0x0020 /* 1=Disable 1000Mbps Auto-Neg Always */ +#define GG82563_PMCR_REVERSE_AUTO_NEG_D0A 0x0040 /* 1=Enable D0a Reverse Auto-Negotiation */ +#define GG82563_PMCR_FORCE_POWER_STATE 0x0080 /* 1=Force Power State */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_MASK 0x0300 +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_DR 0x0000 /* 00=Dr */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0U 0x0100 /* 01=D0u */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0A 0x0200 /* 10=D0a */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D3 0x0300 /* 11=D3 */ + +/* In-Band Control Register (Page 194, Register 18) */ +#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding Use */ + /* Bit definitions for valid PHY IDs. */ /* I = Integrated @@ -2734,6 +3041,7 @@ #define M88E1011_I_REV_4 0x04 #define M88E1111_I_PHY_ID 0x01410CC0 #define L1LXT971A_PHY_ID 0x001378E0 +#define GG82563_E_PHY_ID 0x01410CA0 /* Miscellaneous PHY bit definitions. */ #define PHY_PREAMBLE 0xFFFFFFFF Index: if_em_osdep.h =================================================================== RCS file: /usr/cvs/src/sys/dev/em/if_em_osdep.h,v retrieving revision 1.14.2.1 diff -u -r1.14.2.1 if_em_osdep.h --- if_em_osdep.h 25 Nov 2005 14:11:59 -0000 1.14.2.1 +++ if_em_osdep.h 13 Jul 2006 14:00:46 -0000 @@ -57,7 +57,7 @@ #define MSGOUT(S, A, B) printf(S "\n", A, B) #define DEBUGFUNC(F) DEBUGOUT(F); -#if DBG +#ifdef DBG #define DEBUGOUT(S) printf(S "\n") #define DEBUGOUT1(S,A) printf(S "\n",A) #define DEBUGOUT2(S,A,B) printf(S "\n",A,B) @@ -82,7 +82,7 @@ bus_space_handle_t mem_bus_space_handle; bus_space_tag_t io_bus_space_tag; bus_space_handle_t io_bus_space_handle; - struct device *dev; + device_t dev; }; #define E1000_WRITE_FLUSH(hw) E1000_READ_REG(hw, STATUS)