summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2009-06-23 14:09:52 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2009-06-23 14:09:52 +0000
commit7b2295ee61a875208a4befaaa4c8783a4f024e1f (patch)
tree21b1996de3140741a1f1841a47a46a07530f07e4
parent84eaa5d8dd89f9d25ed7820ac0739d7e6a6dc7d4 (diff)
Add support for the 82574L chips and the bme1000 phy which is also used on
some newer ICH* chips. All the hard work done by Dariusz Swiderski sfires (at) sfires.net, tested by myself, sthen@ and many more. Eyeballed and OK dlg@ kettenis@
-rw-r--r--sys/dev/pci/if_em.c7
-rw-r--r--sys/dev/pci/if_em_hw.c103
-rw-r--r--sys/dev/pci/if_em_hw.h12
3 files changed, 100 insertions, 22 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index 44a016b5385..bffd520de72 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.212 2009/06/05 16:27:40 naddy Exp $ */
+/* $OpenBSD: if_em.c,v 1.213 2009/06/23 14:09:51 claudio Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -116,6 +116,7 @@ const struct pci_matchid em_devices[] = {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L_PL_1 },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L_PL_2 },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573V_PM },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82574L },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_COPPER },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_SERDES },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_CPR },
@@ -329,6 +330,7 @@ em_attach(struct device *parent, struct device *self, void *aux)
}
case em_82571:
case em_82572:
+ case em_82574:
case em_82575:
case em_ich9lan:
case em_80003es2lan: /* Limit Jumbo Frame size */
@@ -695,6 +697,9 @@ em_init(void *arg)
/* Jumbo frames not supported */
pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */
break;
+ case em_82574: /* Total Packet Buffer is 40k */
+ pba = E1000_PBA_30K; /* 30K for Rx, 10K for Tx */
+ break;
case em_ich8lan:
pba = E1000_PBA_8K;
break;
diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c
index da9cb2fd9f2..894c3788ab7 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.33 2009/06/04 05:08:43 claudio Exp $ */
+/* $OpenBSD: if_em_hw.c,v 1.34 2009/06/23 14:09:51 claudio Exp $ */
/* if_em_hw.c
* Shared functions for accessing and configuring the MAC
@@ -220,6 +220,12 @@ em_set_phy_type(struct em_hw *hw)
case IFE_C_E_PHY_ID:
hw->phy_type = em_phy_ife;
break;
+ case BME1000_E_PHY_ID:
+ if (hw->phy_revision == 1) {
+ hw->phy_type = em_phy_bm;
+ break;
+ }
+ /* FALLTHROUGH */
case GG82563_E_PHY_ID:
if (hw->mac_type == em_80003es2lan) {
hw->phy_type = em_phy_gg82563;
@@ -440,6 +446,9 @@ em_set_mac_type(struct em_hw *hw)
case E1000_DEV_ID_82573V_PM:
hw->mac_type = em_82573;
break;
+ case E1000_DEV_ID_82574L:
+ hw->mac_type = em_82574;
+ break;
case E1000_DEV_ID_82575EB_PT:
case E1000_DEV_ID_82575EB_PF:
case E1000_DEV_ID_82575GB_QP:
@@ -492,6 +501,7 @@ em_set_mac_type(struct em_hw *hw)
case em_82571:
case em_82572:
case em_82573:
+ case em_82574:
hw->eeprom_semaphore_present = TRUE;
/* FALLTHROUGH */
case em_82541:
@@ -543,6 +553,7 @@ em_set_media_type(struct em_hw *hw)
case em_ich8lan:
case em_ich9lan:
case em_82573:
+ case em_82574:
/* The STATUS_TBIMODE bit is reserved or reused for the this
* device.
*/
@@ -626,7 +637,7 @@ em_reset_hw(struct em_hw *hw)
/* Must acquire the MDIO ownership before MAC reset.
* Ownership defaults to firmware after a reset. */
- if (hw->mac_type == em_82573) {
+ if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) {
timeout = 10;
extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
@@ -723,6 +734,7 @@ em_reset_hw(struct em_hw *hw)
msec_delay(20);
break;
case em_82573:
+ case em_82574:
if (em_is_onboard_nvm_eeprom(hw) == FALSE) {
usec_delay(10);
ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
@@ -826,6 +838,7 @@ em_initialize_hardware_bits(struct em_hw *hw)
E1000_WRITE_REG(hw, TARC1, reg_tarc1);
break;
case em_82573:
+ case em_82574:
reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
reg_ctrl = E1000_READ_REG(hw, CTRL);
@@ -1023,7 +1036,7 @@ em_init_hw(struct em_hw *hw)
E1000_WRITE_REG(hw, TXDCTL, ctrl);
}
- if (hw->mac_type == em_82573) {
+ if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) {
em_enable_tx_pkt_filtering(hw);
}
@@ -1063,7 +1076,7 @@ em_init_hw(struct em_hw *hw)
break;
}
- if (hw->mac_type == em_82573) {
+ if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) {
uint32_t gcr = E1000_READ_REG(hw, GCR);
gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
E1000_WRITE_REG(hw, GCR, gcr);
@@ -1175,6 +1188,7 @@ em_setup_link(struct em_hw *hw)
case em_ich8lan:
case em_ich9lan:
case em_82573:
+ case em_82574:
hw->fc = E1000_FC_FULL;
break;
default:
@@ -1801,8 +1815,10 @@ em_copper_link_mgp_setup(struct em_hw *hw)
if (ret_val)
return ret_val;
- phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-
+ /* For BM PHY this bit is downshift enable */
+ if (hw->phy_type != em_phy_bm)
+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+
/* Options:
* MDI/MDI-X = 0 (default)
* 0 - Auto for all speeds
@@ -1837,11 +1853,17 @@ em_copper_link_mgp_setup(struct em_hw *hw)
phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
if (hw->disable_polarity_correction == 1)
phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+
+ /* Enable downshift on BM (disabled by default) */
+ if (hw->phy_type == em_phy_bm)
+ phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
+
ret_val = em_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if (ret_val)
return ret_val;
- if (hw->phy_revision < M88E1011_I_REV_4) {
+ if ((hw->phy_type == em_phy_m88) &&
+ (hw->phy_revision < M88E1011_I_REV_4)) {
/* Force TX_CLK in the Extended PHY Specific Control Register
* to 25MHz clock.
*/
@@ -1873,6 +1895,22 @@ em_copper_link_mgp_setup(struct em_hw *hw)
}
}
+ if ((hw->phy_type == em_phy_bm) && (hw->phy_revision == 1)) {
+ /*
+ * Set PHY page 0, register 29 to 0x0003
+ * The next two writes are supposed to lower BER for gig
+ * conection
+ */
+ ret_val = em_write_phy_reg(hw, BM_REG_BIAS1, 0x0003);
+ if (ret_val)
+ return ret_val;
+
+ /* Set PHY page 0, register 30 to 0x0000 */
+ ret_val = em_write_phy_reg(hw, BM_REG_BIAS2, 0x0000);
+ if (ret_val)
+ return ret_val;
+ }
+
/* SW Reset the PHY so all changes take effect */
ret_val = em_phy_reset(hw);
if (ret_val) {
@@ -2054,7 +2092,8 @@ em_setup_copper_link(struct em_hw *hw)
ret_val = em_copper_link_igp_setup(hw);
if (ret_val)
return ret_val;
- } else if (hw->phy_type == em_phy_m88) {
+ } else if (hw->phy_type == em_phy_m88 ||
+ hw->phy_type == em_phy_bm) {
ret_val = em_copper_link_mgp_setup(hw);
if (ret_val)
return ret_val;
@@ -2411,7 +2450,8 @@ em_phy_force_speed_duplex(struct em_hw *hw)
E1000_WRITE_REG(hw, CTRL, ctrl);
if ((hw->phy_type == em_phy_m88) ||
- (hw->phy_type == em_phy_gg82563)) {
+ (hw->phy_type == em_phy_gg82563) ||
+ (hw->phy_type == em_phy_bm)) {
ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
return ret_val;
@@ -2493,7 +2533,8 @@ em_phy_force_speed_duplex(struct em_hw *hw)
}
if ((i == 0) &&
((hw->phy_type == em_phy_m88) ||
- (hw->phy_type == em_phy_gg82563))) {
+ (hw->phy_type == em_phy_gg82563) ||
+ (hw->phy_type == em_phy_bm))) {
/* We didn't get link. Reset the DSP and wait again for link. */
ret_val = em_phy_reset_dsp(hw);
if (ret_val) {
@@ -2518,7 +2559,8 @@ em_phy_force_speed_duplex(struct em_hw *hw)
}
}
- if (hw->phy_type == em_phy_m88) {
+ if (hw->phy_type == em_phy_m88 ||
+ hw->phy_type == em_phy_bm) {
/* Because we reset the PHY above, we need to re-force TX_CLK in the
* Extended PHY Specific Control Register to 25MHz clock. This value
* defaults back to a 2.5MHz clock when the PHY is reset.
@@ -3563,7 +3605,15 @@ em_read_phy_reg(struct em_hw *hw,
return ret_val;
}
}
- }
+ } else if ((hw->phy_type == em_phy_bm) && (hw->phy_revision == 1)) {
+ if (reg_addr > MAX_PHY_MULTI_PAGE_REG) {
+ ret_val = em_write_phy_reg_ex(hw, BM_PHY_PAGE_SELECT,
+ (uint16_t)((uint16_t)reg_addr >> PHY_PAGE_SHIFT));
+ if (ret_val)
+ return ret_val;
+ }
+ }
+
ret_val = em_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
phy_data);
@@ -3701,7 +3751,14 @@ em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr,
return ret_val;
}
}
- }
+ } else if ((hw->phy_type == em_phy_bm) && (hw->phy_revision == 1)) {
+ if (reg_addr > MAX_PHY_MULTI_PAGE_REG) {
+ ret_val = em_write_phy_reg_ex(hw, BM_PHY_PAGE_SELECT,
+ (uint16_t)((uint16_t)reg_addr >> PHY_PAGE_SHIFT));
+ if (ret_val)
+ return ret_val;
+ }
+ }
ret_val = em_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
phy_data);
@@ -4118,6 +4175,9 @@ em_detect_gig_phy(struct em_hw *hw)
case em_82573:
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;
case em_80003es2lan:
if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
break;
@@ -4263,6 +4323,7 @@ em_init_eeprom_params(struct em_hw *hw)
eeprom->use_eewr = FALSE;
break;
case em_82573:
+ case em_82574:
eeprom->type = em_eeprom_spi;
eeprom->opcode_bits = 8;
eeprom->delay_usec = 1;
@@ -4515,7 +4576,7 @@ em_acquire_eeprom(struct em_hw *hw)
return -E1000_ERR_SWFW_SYNC;
eecd = E1000_READ_REG(hw, EECD);
- if (hw->mac_type != em_82573) {
+ if ((hw->mac_type != em_82573) &&(hw->mac_type != em_82574)) {
/* Request EEPROM Access */
if (hw->mac_type > em_82544) {
eecd |= E1000_EECD_REQ;
@@ -4923,7 +4984,7 @@ em_is_onboard_nvm_eeprom(struct em_hw *hw)
if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
return FALSE;
- if (hw->mac_type == em_82573) {
+ if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) {
eecd = E1000_READ_REG(hw, EECD);
/* Isolate bits 15 & 16 */
@@ -4954,7 +5015,7 @@ em_validate_eeprom_checksum(struct em_hw *hw)
DEBUGFUNC("em_validate_eeprom_checksum");
- if ((hw->mac_type == em_82573) &&
+ if (((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) &&
(em_is_onboard_nvm_eeprom(hw) == FALSE)) {
/* Check bit 4 of word 10h. If it is 0, firmware is done updating
* 10h-12h. Checksum may need to be fixed. */
@@ -5080,7 +5141,7 @@ em_write_eeprom(struct em_hw *hw,
return -E1000_ERR_EEPROM;
}
- /* 82573 writes only through eewr */
+ /* 82573/4 writes only through eewr */
if (eeprom->use_eewr == TRUE)
return em_write_eeprom_eewr(hw, offset, words, data);
@@ -5280,7 +5341,7 @@ em_commit_shadow_ram(struct em_hw *hw)
uint8_t high_byte = 0;
boolean_t sector_write_failed = FALSE;
- if (hw->mac_type == em_82573) {
+ if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) {
/* The flop register will be used to determine if flash type is STM */
flop = E1000_READ_REG(hw, FLOP);
for (i=0; i < attempts; i++) {
@@ -5826,7 +5887,7 @@ em_clear_vfta(struct em_hw *hw)
if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan)
return;
- if (hw->mac_type == em_82573) {
+ if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) {
if (hw->mng_cookie.vlan_id != 0) {
/* The VFTA is a 4096b bit-field, each identifying a single VLAN
* ID. The following operations determine which 32b entry
@@ -6129,6 +6190,7 @@ em_get_bus_info(struct em_hw *hw)
case em_82571:
case em_82572:
case em_82573:
+ case em_82574:
case em_82575:
case em_80003es2lan:
hw->bus_type = em_bus_type_pci_express;
@@ -7279,6 +7341,7 @@ em_get_auto_rd_done(struct em_hw *hw)
case em_82571:
case em_82572:
case em_82573:
+ case em_82574:
case em_82575:
case em_80003es2lan:
case em_ich8lan:
@@ -7300,7 +7363,7 @@ em_get_auto_rd_done(struct em_hw *hw)
/* 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)
+ if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574))
msec_delay(25);
return E1000_SUCCESS;
diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h
index 9aec75750bc..edf4f749110 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.29 2009/06/04 05:08:43 claudio Exp $ */
+/* $OpenBSD: if_em_hw.h,v 1.30 2009/06/23 14:09:51 claudio Exp $ */
/* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */
/* if_em_hw.h
@@ -67,6 +67,7 @@ typedef enum {
em_82571,
em_82572,
em_82573,
+ em_82574,
em_82575,
em_80003es2lan,
em_ich8lan,
@@ -228,6 +229,7 @@ typedef enum {
em_phy_gg82563,
em_phy_igp_3,
em_phy_ife,
+ em_phy_bm, /* phy used in i82574L, ICH10 and some ICH9 */
em_phy_undefined = 0xFF
} em_phy_type;
@@ -518,6 +520,7 @@ int32_t em_check_phy_reset_block(struct em_hw *hw);
#define E1000_DEV_ID_82576_SERDES 0x10E7
#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
#define E1000_DEV_ID_82576_NS 0x150A
+#define E1000_DEV_ID_82574L 0x10D3
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
@@ -2596,6 +2599,12 @@ struct em_host_command_info {
#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
+/* BME1000 PHY Specific Control Register */
+#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */
+#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */
+#define BM_REG_BIAS1 29
+#define BM_REG_BIAS2 30
+
#define IGP01E1000_IEEE_REGS_PAGE 0x0000
#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300
#define IGP01E1000_IEEE_FORCE_GIGA 0x0140
@@ -3169,6 +3178,7 @@ struct em_host_command_info {
#define M88E1111_I_PHY_ID 0x01410CC0
#define L1LXT971A_PHY_ID 0x001378E0
#define GG82563_E_PHY_ID 0x01410CA0
+#define BME1000_E_PHY_ID 0x01410CB0
/* Bits...
* 15-5: page