Subject: Re: Intel 82573 support
To: None <lists@yazzy.org>
From: SAITOH Masanobu <masanobu@iij.ad.jp>
List: current-users
Date: 05/08/2006 18:05:48
> > Hi,
> >
> > Is anyone working on the support for the Intel 82573 Ethernet chip?
> >
> > Jean-Luc
>
> I began working on it but after I got the nic recognized my time schedule
> disallowed futher work on it.
> However this port of FreeBSD's driver by Dheeraj Reddy worked fine on my
> current:
> http://users.ece.gatech.edu/~dheeraj/netbsd.html
>
>
> --
> Marcin M. Jessa
> http://www.yazzy.org/
I made a patch for the wm driver.
o NOT COMPLETED
o most code was taken from Dheeraj Reddy's driver.
o At least, an i82573E based machine works.
o not for -current but for netbsd-3 (sorry)
I'm busy and no time to spend to finish this work. I want someone to
take over my work.
Regards.
----------------------------------------------------------
SAITOH Masanobu (masanobu@iij.ad.jp
msaitoh@netbsd.org)
Index: if_wm.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_wm.c,v
retrieving revision 1.100.2.4
diff -u -r1.100.2.4 if_wm.c
--- if_wm.c 8 Feb 2006 21:10:28 -0000 1.100.2.4
+++ if_wm.c 8 May 2006 08:44:22 -0000
@@ -213,6 +213,9 @@
WM_T_82541_2, /* i82541 2.0+ */
WM_T_82547, /* i82547 */
WM_T_82547_2, /* i82547 2.0+ */
+ WM_T_82571,
+ WM_T_82572,
+ WM_T_82573,
} wm_chip_type;
/*
@@ -356,10 +359,12 @@
#define WM_F_HAS_MII 0x01 /* has MII */
#define WM_F_EEPROM_HANDSHAKE 0x02 /* requires EEPROM handshake */
#define WM_F_EEPROM_SPI 0x04 /* EEPROM is SPI */
+#define WM_F_EEPROM_SEMAPHORE 0x08 /* EEPROM semaphore is required */
#define WM_F_IOH_VALID 0x10 /* I/O handle is valid */
#define WM_F_BUS64 0x20 /* bus is 64-bit */
#define WM_F_PCIX 0x40 /* bus is PCI-X */
#define WM_F_CSA 0x80 /* bus is CSA */
+#define WM_F_PCIE 0x100 /* bus is PCI-Express */
#ifdef WM_EVENT_COUNTERS
#define WM_EVCNT_INCR(ev) (ev)->ev_count++
@@ -494,6 +499,14 @@
static int wm_match(struct device *, struct cfdata *, void *);
static void wm_attach(struct device *, struct device *, void *);
+static int wm_is_onboard_nvm_eeprom(struct wm_softc *);
+static int32_t wm_get_auto_rd_done(struct wm_softc *);
+static int32_t wm_get_hw_eeprom_semaphore(struct wm_softc *);
+static void wm_put_hw_eeprom_semaphore(struct wm_softc *);
+static void wm_standby_eeprom(struct wm_softc *);
+static int32_t wm_read_eeprom_eerd(struct wm_softc *, int32_t, int32_t,
+ uint16_t *);
+static int32_t wm_poll_eerd_eewr_done(struct wm_softc *, int);
CFATTACH_DECL(wm, sizeof(struct wm_softc),
wm_match, wm_attach, NULL, NULL);
@@ -604,10 +617,18 @@
"Intel i82546GB Gigabit Ethernet (SERDES)",
WM_T_82546_3, WMP_F_SERDES },
#endif
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_PCIE,
+ "Intel PRO/1000MT (82546GB)",
+ WM_T_82546_3, WMP_F_1000T },
+
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541EI,
"Intel i82541EI 1000BASE-T Ethernet",
WM_T_82541, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541ER_LOM,
+ "Intel i82541ER (LOM) 1000BASE-T Ethernet",
+ WM_T_82541, WMP_F_1000T },
+
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541EI_MOBILE,
"Intel i82541EI Mobile 1000BASE-T Ethernet",
WM_T_82541, WMP_F_1000T },
@@ -632,9 +653,50 @@
"Intel i82547EI 1000BASE-T Ethernet",
WM_T_82547, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547EI_MOBILE,
+ "Intel i82547EI Moblie 1000BASE-T Ethernet",
+ WM_T_82547, WMP_F_1000T },
+
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547GI,
"Intel i82547GI 1000BASE-T Ethernet",
WM_T_82547_2, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_COPPER,
+ "Intel PRO/1000 PT (82571EB)",
+ WM_T_82571, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_FIBER,
+ "Intel PRO/1000 PF (82571EB)",
+ WM_T_82571, WMP_F_1000X },
+#if 0
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_SERDES,
+ "Intel PRO/1000 PB (82571EB)",
+ WM_T_82571, WMP_F_SERDES },
+#endif
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_COPPER,
+ "Intel i82572EI 1000baseT Ethernet",
+ WM_T_82572, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_FIBER,
+ "Intel i82572EI 1000baseX Ethernet",
+ WM_T_82572, WMP_F_1000X },
+#if 0
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_SERDES,
+ "Intel i82572EI Gigabit Ethernet (SERDES)",
+ WM_T_82572, WMP_F_SERDES },
+#endif
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573E,
+ "Intel i82573E",
+ WM_T_82573, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573E_IAMT,
+ "Intel i82573E",
+ WM_T_82573, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L,
+ "Intel i82573L Gigabit Ethernet",
+ WM_T_82573, WMP_F_1000T },
+
{ 0, 0,
NULL,
0, 0 },
@@ -883,6 +945,23 @@
reg = CSR_READ(sc, WMREG_STATUS);
if (reg & STATUS_BUS64)
sc->sc_flags |= WM_F_BUS64;
+ if (sc->sc_type >= WM_T_82571) {
+ uint32_t reg;
+ int timeout = 800;
+
+ sc->sc_flags |= WM_F_PCIE;
+ /* disable PCI-Express master access */
+ reg = CSR_READ(sc, WMREG_CTRL) | CTRL_GIO_M_DIS;
+ CSR_WRITE(sc, WMREG_CTRL, reg);
+
+ while(timeout) {
+ if(!(CSR_READ(sc, WMREG_STATUS) & STATUS_GIO_MASTER_ENA))
+ break;
+ else
+ delay(100);
+ timeout--;
+ }
+ }
if (sc->sc_type >= WM_T_82544 &&
(reg & STATUS_PCIX_MODE) != 0) {
pcireg_t pcix_cmd, pcix_sts, bytecnt, maxb;
@@ -933,6 +1012,8 @@
if (wmp->wmp_product == PCI_PRODUCT_INTEL_82546EB_QUAD) {
sc->sc_bus_speed = (sc->sc_flags & WM_F_PCIX) ? 120
: 66;
+ } else if (sc->sc_flags & WM_F_PCIE) {
+ sc->sc_bus_speed = 2500;
} else if (sc->sc_flags & WM_F_PCIX) {
switch (reg & STATUS_PCIXSPD_MASK) {
case STATUS_PCIXSPD_50_66:
@@ -953,9 +1034,14 @@
}
} else
sc->sc_bus_speed = (reg & STATUS_PCI66) ? 66 : 33;
- aprint_verbose("%s: %d-bit %dMHz %s bus\n", sc->sc_dev.dv_xname,
- (sc->sc_flags & WM_F_BUS64) ? 64 : 32, sc->sc_bus_speed,
- (sc->sc_flags & WM_F_PCIX) ? "PCIX" : "PCI");
+ if (sc->sc_flags & WM_F_PCIE) {
+ aprint_verbose("%s: %s bus\n", sc->sc_dev.dv_xname,
+ "PCI-Express");
+ } else {
+ aprint_verbose("%s: %d-bit %dMHz %s bus\n", sc->sc_dev.dv_xname,
+ (sc->sc_flags & WM_F_BUS64) ? 64 : 32, sc->sc_bus_speed,
+ (sc->sc_flags & WM_F_PCIX) ? "PCIX" : "PCI");
+ }
}
/*
@@ -1034,6 +1120,9 @@
sc->sc_rxsoft[i].rxs_mbuf = NULL;
}
+ if (sc->sc_type >= WM_T_82571)
+ sc->sc_flags |= WM_F_EEPROM_SEMAPHORE;
+
/*
* Reset the chip to a known state.
*/
@@ -1060,6 +1149,12 @@
} else
sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 8 : 6;
} else {
+ if (sc->sc_type >= WM_T_82571) {
+ int rv;
+ rv = wm_get_auto_rd_done(sc);
+ }
+ if (wm_is_onboard_nvm_eeprom(sc) == 0)
+ printf("XXXXXXXXXXXXXXX FLASH XXXXXXXXXXXXXXX\n");
/* Assume everything else is SPI. */
reg = CSR_READ(sc, WMREG_EECD);
sc->sc_flags |= WM_F_EEPROM_SPI;
@@ -1329,6 +1424,48 @@
return;
}
+/*******************************************************************************
+ *
+ * Check for EEPROM Auto Read bit done.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_RESET if fail to reset MAC
+ * E1000_SUCCESS at any other case.
+ *
+ ******************************************************************************/
+static int32_t
+wm_get_auto_rd_done(struct wm_softc *sc)
+{
+ int32_t timeout = 1000;
+
+ DPRINTF(WM_DEBUG_GMII, ("wm_get_auto_rd_done"));
+
+ switch (sc->sc_type) {
+ default:
+ delay(5*1000);
+ break;
+ case WM_T_82571:
+ case WM_T_82572:
+ case WM_T_82573:
+ while(timeout) {
+ if (CSR_READ(sc, WMREG_EECD) & EECD_EE_AUTORD)
+ break;
+ else
+ delay(1*1000);
+ timeout--;
+ }
+
+ if(!timeout) {
+ DPRINTF(WM_DEBUG_GMII, ("Auto read by HW from EEPROM has not completed.\n"));
+ return -1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
/*
* wm_shutdown:
*
@@ -2459,6 +2596,9 @@
wm_reset(struct wm_softc *sc)
{
int i;
+#if 0
+ uint32_t reg;
+#endif
/*
* Allocate on-chip memory according to the MTU size.
@@ -2479,6 +2619,29 @@
}
CSR_WRITE(sc, WMREG_PBA, sc->sc_pba);
+ /* Must acquire the MDIO ownership before MAC reset.
+ * Ownership defaults to firmware after a reset. */
+ if(sc->sc_type == WM_T_82573) {
+ uint32_t extcnf_ctrl;
+ int timeout = 10;
+
+ extcnf_ctrl = CSR_READ(sc, WMREG_EXTCNF_CTRL);
+ extcnf_ctrl |= EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+
+ do {
+ CSR_WRITE(sc, WMREG_EXTCNF_CTRL, extcnf_ctrl);
+ extcnf_ctrl = CSR_READ(sc, WMREG_EXTCNF_CTRL);
+
+ if(extcnf_ctrl & EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
+ break;
+ else
+ extcnf_ctrl |= EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+
+ delay(2*1000);
+ timeout--;
+ } while(timeout);
+ }
+
switch (sc->sc_type) {
case WM_T_82544:
case WM_T_82540:
@@ -2511,20 +2674,41 @@
default:
/* Everything else can safely use the documented method. */
+#if 1
CSR_WRITE(sc, WMREG_CTRL, CTRL_RST);
+#else
+ reg = CSR_READ(sc, WMREG_CTRL);
+ CSR_WRITE(sc, WMREG_CTRL, reg | CTRL_RST);
+ printf("new reset");
+#endif
break;
}
delay(10000);
- for (i = 0; i < 1000; i++) {
- if ((CSR_READ(sc, WMREG_CTRL) & CTRL_RST) == 0)
+ if (sc->sc_type == WM_T_82573) {
+ uint32_t ctrl_ext;
+ int32_t ret_val;
+
+ delay(10);
+ ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT);
+ ctrl_ext |= CTRL_EXT_EE_RST;
+ CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
+ CSR_WRITE_FLUSH(sc);
+ ret_val = wm_get_auto_rd_done(sc);
+ if(ret_val)
+ /* We don't want to continue accessing MAC registers. */
return;
- delay(20);
- }
+ } else {
+ for (i = 0; i < 1000; i++) {
+ if ((CSR_READ(sc, WMREG_CTRL) & CTRL_RST) == 0)
+ return;
+ delay(20);
+ }
- if (CSR_READ(sc, WMREG_CTRL) & CTRL_RST)
- log(LOG_ERR, "%s: reset failed to complete\n",
- sc->sc_dev.dv_xname);
+ if (CSR_READ(sc, WMREG_CTRL) & CTRL_RST)
+ log(LOG_ERR, "%s: reset failed to complete\n",
+ sc->sc_dev.dv_xname);
+ }
}
/*
@@ -2872,6 +3056,30 @@
ifp->if_timer = 0;
}
+/***************************************************************************
+* Description: Determines if the onboard NVM is FLASH or EEPROM.
+*
+* hw - Struct containing variables accessed by shared code
+****************************************************************************/
+static int
+wm_is_onboard_nvm_eeprom(struct wm_softc *sc)
+{
+ uint32_t eecd = 0;
+
+ if(sc->sc_type == WM_T_82573) {
+ eecd = CSR_READ(sc, WMREG_EECD);
+
+ /* Isolate bits 15 & 16 */
+ eecd = ((eecd >> 15) & 0x03);
+
+ /* If both bits are set, device is Flash type */
+ if(eecd == 0x03) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
/*
* wm_acquire_eeprom:
*
@@ -2883,32 +3091,102 @@
uint32_t reg;
int x;
- if (sc->sc_flags & WM_F_EEPROM_HANDSHAKE) {
- reg = CSR_READ(sc, WMREG_EECD);
+ if (wm_get_hw_eeprom_semaphore(sc))
+ return 1;
- /* Request EEPROM access. */
- reg |= EECD_EE_REQ;
- CSR_WRITE(sc, WMREG_EECD, reg);
+ reg = CSR_READ(sc, WMREG_EECD);
- /* ..and wait for it to be granted. */
- for (x = 0; x < 100; x++) {
- reg = CSR_READ(sc, WMREG_EECD);
- if (reg & EECD_EE_GNT)
- break;
- delay(5);
- }
- if ((reg & EECD_EE_GNT) == 0) {
- aprint_error("%s: could not acquire EEPROM GNT\n",
- sc->sc_dev.dv_xname);
- reg &= ~EECD_EE_REQ;
+ if (sc->sc_type != WM_T_82573) {
+ if (sc->sc_flags & WM_F_EEPROM_HANDSHAKE) {
+ /* Request EEPROM access. */
+ reg |= EECD_EE_REQ;
CSR_WRITE(sc, WMREG_EECD, reg);
- return (1);
+
+ /* ..and wait for it to be granted. */
+ for (x = 0; x < 100; x++) {
+ reg = CSR_READ(sc, WMREG_EECD);
+ if (reg & EECD_EE_GNT)
+ break;
+ delay(5);
+ }
+ if ((reg & EECD_EE_GNT) == 0) {
+ aprint_error("%s: could not acquire EEPROM GNT\n",
+ sc->sc_dev.dv_xname);
+ reg &= ~EECD_EE_REQ;
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ return (1);
+ }
}
}
+ /* Setup EEPROM for Read/Write */
+
+ if (!(sc->sc_flags & WM_F_EEPROM_SPI)) { /* micorwire */
+ /* Clear SK and DI */
+ reg &= ~(EECD_DI | EECD_SK);
+ CSR_WRITE(sc, WMREG_EECD, reg);
+
+ /* Set CS */
+ reg |= EECD_CS;
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ } else {
+ /* Clear SK and CS */
+ reg &= ~(EECD_CS | EECD_SK);
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ delay(1);
+ }
+
return (0);
}
+/******************************************************************************
+ * Returns EEPROM to a "standby" state
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+wm_standby_eeprom(struct wm_softc *sc)
+{
+ uint32_t eecd;
+
+ eecd = CSR_READ(sc, WMREG_EECD);
+
+ if (!(sc->sc_flags & WM_F_EEPROM_SPI)) {
+ eecd &= ~(EECD_CS | EECD_SK);
+ CSR_WRITE(sc, WMREG_EECD, eecd);
+ CSR_WRITE_FLUSH(sc);
+ delay(100); /* XXX */
+
+ /* Clock high */
+ eecd |= EECD_SK;
+ CSR_WRITE(sc, WMREG_EECD, eecd);
+ CSR_WRITE_FLUSH(sc);
+ delay(100); /* XXX */
+
+ /* Select EEPROM */
+ eecd |= EECD_CS;
+ CSR_WRITE(sc, WMREG_EECD, eecd);
+ CSR_WRITE_FLUSH(sc);
+ delay(100); /* XXX */
+
+ /* Clock low */
+ eecd &= ~EECD_SK;
+ CSR_WRITE(sc, WMREG_EECD, eecd);
+ CSR_WRITE_FLUSH(sc);
+ delay(100); /* XXX */
+ } else { /* SPI */
+ /* Toggle CS to flush commands */
+ eecd |= EECD_CS;
+ CSR_WRITE(sc, WMREG_EECD, eecd);
+ CSR_WRITE_FLUSH(sc);
+ delay(100); /* XXX */
+ eecd &= ~EECD_CS;
+ CSR_WRITE(sc, WMREG_EECD, eecd);
+ CSR_WRITE_FLUSH(sc);
+ delay(100); /* XXX */
+ }
+}
+
/*
* wm_release_eeprom:
*
@@ -2919,11 +3197,23 @@
{
uint32_t reg;
- if (sc->sc_flags & WM_F_EEPROM_HANDSHAKE) {
+ reg = CSR_READ(sc, WMREG_EECD);
+
+ if (sc->sc_flags & WM_F_EEPROM_SPI) {
+ reg |= EECD_CS; /* Pull CS high */
+ reg &= ~EECD_SK;/* Lower SCK */
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ } else {
+ /* XXX null */
+ }
+
+ if (sc->sc_type & WM_T_82544) {
reg = CSR_READ(sc, WMREG_EECD);
reg &= ~EECD_EE_REQ;
CSR_WRITE(sc, WMREG_EECD, reg);
}
+
+ wm_put_hw_eeprom_semaphore(sc);
}
/*
@@ -2945,6 +3235,7 @@
else
reg &= ~EECD_DI;
CSR_WRITE(sc, WMREG_EECD, reg);
+ CSR_WRITE_FLUSH(sc);
delay(2);
CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
delay(2);
@@ -3018,6 +3309,68 @@
return (0);
}
+/******************************************************************************
+ * Reads a 16 bit word from the EEPROM using the EERD register.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of word in the EEPROM to read
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+static int32_t
+wm_read_eeprom_eerd(struct wm_softc *sc,
+ int32_t offset,
+ int32_t words,
+ uint16_t *data)
+{
+ uint32_t i, eerd = 0;
+ int32_t error = 0;
+
+ for (i = 0; i < words; i++) {
+ eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
+ E1000_EEPROM_RW_REG_START;
+
+ CSR_WRITE(sc, WMREG_EERD, eerd);
+ error = wm_poll_eerd_eewr_done(sc, E1000_EEPROM_POLL_READ);
+
+ if(error) {
+ break;
+ }
+ data[i] = (CSR_READ(sc, WMREG_EERD) >> E1000_EEPROM_RW_REG_DATA);
+
+ }
+
+ return error;
+}
+
+/******************************************************************************
+ * Polls the status bit (bit 1) of the EERD to determine when the read is done.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static int32_t
+wm_poll_eerd_eewr_done(struct wm_softc *sc, int eerd)
+{
+ uint32_t attempts = 100000;
+ uint32_t i, reg = 0;
+ int32_t done = -1;
+
+ for(i = 0; i < attempts; i++) {
+ if(eerd == E1000_EEPROM_POLL_READ)
+ reg = CSR_READ(sc, WMREG_EERD);
+ else
+ reg = CSR_READ(sc, WMREG_EEWR);
+
+ if(reg & E1000_EEPROM_RW_REG_DONE) {
+ done = 0;
+ break;
+ }
+ delay(5);
+ }
+
+ return done;
+}
+
/*
* wm_spi_eeprom_ready:
*
@@ -3029,7 +3382,7 @@
uint32_t val;
int usec;
- for (usec = 0; usec < SPI_MAX_RETRIES; delay(5), usec += 5) {
+ for (usec = 0; usec < SPI_MAX_RETRIES; delay(5), wm_standby_eeprom(sc), usec += 5) {
wm_eeprom_sendbits(sc, SPI_OPC_RDSR, 8);
wm_eeprom_recvbits(sc, &val, 8);
if ((val & SPI_SR_RDY) == 0)
@@ -3063,10 +3416,14 @@
if (wm_spi_eeprom_ready(sc))
return (1);
+ wm_standby_eeprom(sc);
+
/* Toggle CS to flush commands. */
CSR_WRITE(sc, WMREG_EECD, reg | EECD_CS);
+ CSR_WRITE_FLUSH(sc);
delay(2);
CSR_WRITE(sc, WMREG_EECD, reg);
+ CSR_WRITE_FLUSH(sc);
delay(2);
opc = SPI_OPC_READ;
@@ -3099,8 +3456,21 @@
{
int rv;
- if (wm_acquire_eeprom(sc))
- return (1);
+ if ((wm_is_onboard_nvm_eeprom(sc) == 1) ||
+ (sc->sc_type != WM_T_82573))
+ if (wm_acquire_eeprom(sc)) {
+ return (1);
+ }
+
+ if (sc->sc_type == WM_T_82573) {
+ int32_t rv;
+
+ rv = wm_read_eeprom_eerd(sc, word, wordcnt, data);
+ if ((wm_is_onboard_nvm_eeprom(sc) == 1) ||
+ (sc->sc_type != WM_T_82573))
+ wm_release_eeprom(sc);
+ return rv;
+ }
if (sc->sc_flags & WM_F_EEPROM_SPI)
rv = wm_read_eeprom_spi(sc, word, wordcnt, data);
@@ -3853,3 +4223,73 @@
CSR_WRITE(sc, (sc->sc_type < WM_T_82543) ? WMREG_OLD_FCRTL
: WMREG_FCRTL, sc->sc_fcrtl);
}
+
+/***************************************************************************
+ *
+ * Using the combination of SMBI and SWESMBI semaphore bits when resetting
+ * adapter or Eeprom access.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_EEPROM if fail to access EEPROM.
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+static int32_t
+wm_get_hw_eeprom_semaphore(struct wm_softc *sc)
+{
+ int32_t timeout;
+ uint32_t swsm;
+
+ DPRINTF(WM_DEBUG_GMII, ("wm_get_hw_eeprom_semaphore"));
+
+ if((sc->sc_flags & WM_F_EEPROM_SEMAPHORE) == 0)
+ return 0;
+
+ /* Get the FW semaphore. */
+ timeout = 1000 + 1; /* XXX */
+ while(timeout) {
+ swsm = CSR_READ(sc, WMREG_SWSM);
+ swsm |= SWSM_SWESMBI;
+ CSR_WRITE(sc, WMREG_SWSM, swsm);
+ /* if we managed to set the bit we got the semaphore. */
+ swsm = CSR_READ(sc, WMREG_SWSM);
+ if(swsm & SWSM_SWESMBI)
+ break;
+
+ delay(50);
+ timeout--;
+ }
+
+ if(!timeout) {
+ /* Release semaphores */
+ wm_put_hw_eeprom_semaphore(sc);
+ DPRINTF(WM_DEBUG_GMII, ("Driver can't access the Eeprom - SWESMBI bit is set.\n"));
+ return 1;
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+ * This function clears HW semaphore bits.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - None.
+ *
+ ***************************************************************************/
+static void
+wm_put_hw_eeprom_semaphore(struct wm_softc *sc)
+{
+ uint32_t swsm;
+
+ DPRINTF(WM_DEBUG_GMII, ("wm_put_hw_eeprom_semaphore"));
+
+ if((sc->sc_flags & WM_F_EEPROM_SEMAPHORE) == 0)
+ return;
+
+ swsm = CSR_READ(sc, WMREG_SWSM);
+ swsm &= ~(SWSM_SWESMBI);
+ CSR_WRITE(sc, WMREG_SWSM, swsm);
+}
Index: if_wmreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_wmreg.h,v
retrieving revision 1.14.4.1
diff -u -r1.14.4.1 if_wmreg.h
--- if_wmreg.h 28 Aug 2005 09:49:37 -0000 1.14.4.1
+++ if_wmreg.h 8 May 2006 08:44:22 -0000
@@ -174,6 +174,7 @@
#define CTRL_FD (1U << 0) /* full duplex */
#define CTRL_BEM (1U << 1) /* big-endian mode */
#define CTRL_PRIOR (1U << 2) /* 0 = receive, 1 = fair */
+#define CTRL_GIO_M_DIS (1U << 2) /* 1 = disable master access */
#define CTRL_LRST (1U << 3) /* link reset */
#define CTRL_ASDE (1U << 5) /* auto speed detect enable */
#define CTRL_SLU (1U << 6) /* set link up */
@@ -222,6 +223,7 @@
#define STATUS_PCIXSPD_66_100 STATUS_PCIXSPD(1)
#define STATUS_PCIXSPD_100_133 STATUS_PCIXSPD(2)
#define STATUS_PCIXSPD_MASK STATUS_PCIXSPD(3)
+#define STATUS_GIO_MASTER_ENA (1U << 19) /* PCI-e master enable */
#define WMREG_EECD 0x0010 /* EEPROM Control Register */
#define EECD_SK (1U << 0) /* clock */
@@ -236,11 +238,14 @@
#define EECD_EE_PRES (1U << 8) /* EEPROM present */
#define EECD_EE_SIZE (1U << 9) /* EEPROM size
(0 = 64 word, 1 = 256 word) */
+#define EECD_EE_AUTORD (1U << 9) /* EEPROM Auto Read done */
#define EECD_EE_ABITS (1U << 10) /* EEPROM address bits
(based on type) */
#define EECD_EE_TYPE (1U << 13) /* EEPROM type
(0 = Microwire, 1 = SPI) */
+#define WMREG_EERD 0x0014
+
#define UWIRE_OPC_ERASE 0x04 /* MicroWire "erase" opcode */
#define UWIRE_OPC_WRITE 0x05 /* MicroWire "write" opcode */
#define UWIRE_OPC_READ 0x06 /* MicroWire "read" opcode */
@@ -545,6 +550,18 @@
#define WMREG_AIT 0x0458 /* Adaptive IFS Throttle */
+#define WMREG_EXTCNF_CTRL 0x0F00 /* Extended Configuration Control */
+
+/* Extended Configuration Control and Size */
+#define EXTCNF_CTRL_PCIE_WRITE_ENABLE 0x00000001
+#define EXTCNF_CTRL_PHY_WRITE_ENABLE 0x00000002
+#define EXTCNF_CTRL_D_UD_ENABLE 0x00000004
+#define EXTCNF_CTRL_D_UD_LATENCY 0x00000008
+#define EXTCNF_CTRL_D_UD_OWNER 0x00000010
+#define EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
+#define EXTCNF_CTRL_MDIO_HW_OWNERSHIP 0x00000040
+#define EXTCNF_CTRL_EXT_CNF_POINTER 0x1FFF0000
+
#define WMREG_VFTA 0x0600
#define WM_MC_TABSIZE 128
@@ -560,6 +577,8 @@
#define PBA_40K 0x0028
#define PBA_48K 0x0030 /* 48K, default Rx allocation */
+#define WMREG_EEWR 0x102c
+
#define WMREG_TXDMAC 0x3000 /* Transfer DMA Control */
#define TXDMAC_DPP (1U << 0) /* disable packet prefetch */
@@ -578,3 +597,16 @@
#define WMREG_XOFFRXC 0x4050 /* XOFF Rx Count - R/clr */
#define WMREG_XOFFTXC 0x4054 /* XOFF Tx Count - R/clr */
#define WMREG_FCRUC 0x4058 /* Flow Control Rx Unsupported Count - R/clr */
+
+#define WMREG_SWSM 0x5B50 /* SW Semaphore */
+/* SW Semaphore Register */
+#define SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
+#define SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
+#define SWSM_WMNG 0x00000004 /* Wake MNG Clock */
+#define SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
+
+#define E1000_EEPROM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
+#define E1000_EEPROM_RW_REG_START 1 /* First bit for telling part to start operation */
+#define E1000_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
+#define E1000_EEPROM_POLL_READ 0 /* Flag for polling for read complete */
+#define E1000_EEPROM_RW_REG_DATA 16 /* Offset to data in EEPROM read/write registers */
Index: pcidevs
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pcidevs,v
retrieving revision 1.701.2.28
diff -u -r1.701.2.28 pcidevs
--- pcidevs 8 Apr 2006 23:29:19 -0000 1.701.2.28
+++ pcidevs 8 May 2006 08:44:23 -0000
@@ -1687,11 +1687,13 @@
product INTEL 82545EM_FIBER 0x1011 i82545EM 1000baseX Ethernet
product INTEL 82546EB_FIBER 0x1012 i82546EB 1000baseX Ethernet
product INTEL 82541EI 0x1013 i82541EI Gigabit Ethernet
+product INTEL 82541ER_LOM 0x1014 i82541ER (LOM) Gigabit Ethernet
product INTEL 82540EM_LOM 0x1015 i82540EM (LOM) Gigabit Ethernet
product INTEL 82540EP_LOM 0x1016 i82540EP (LOM) Gigabit Ethernet
product INTEL 82540EP 0x1017 i82540EP Gigabit Ethernet
product INTEL 82541EI_MOBILE 0x1018 i82541EI Mobile Gigabit Ethernet
product INTEL 82547EI 0x1019 i82547EI Gigabit Ethernet
+product INTEL 82547EI_MOBILE 0x101a i82547EI Mobile GigE
product INTEL 82546EB_QUAD 0x101d i82546EB 1000baseT Ethernet
product INTEL 82540EP_LP 0x101e i82540EP Gigabit Ethernet
product INTEL 82545GM_COPPER 0x1026 i82545GM 1000baseT Ethernet
@@ -1717,6 +1719,9 @@
product INTEL PRO_100_VM_6 0x1050 PRO/100 VM Network Controller with 82562ET/EZ PHY
product INTEL 82801EB_LAN 0x1051 82801EB/ER 10/100 Ethernet
product INTEL PRO_100_M 0x1059 PRO/100 M Network Controller
+product INTEL 82571EB_COPPER 0x105E PRO/1000 PT (82571EB)
+product INTEL 82571EB_FIBER 0x105F PRO/1000 PF (82571EB)
+product INTEL 82571EB_SERDES 0x1060 PRO/1000 PB (82571EB)
product INTEL 82801FB_LAN 0x1064 82801FB 10/100 Ethernet
product INTEL 82547GI 0x1075 i82547GI Gigabit Ethernet
product INTEL 82541GI 0x1076 i82541GI Gigabit Ethernet
@@ -1726,6 +1731,14 @@
product INTEL 82546GB_FIBER 0x107a i82546GB 1000baseX Ethernet
product INTEL 82546GB_SERDES 0x107b i82546GB Gigabit Ethernet (SERDES)
product INTEL 82541PI 0x107c i82541PI Gigabit Ethernet
+product INTEL 82572EI_COPPER 0x107d i82572EI 1000baseT Ethernet
+product INTEL 82572EI_FIBER 0x107e i82572EI 1000baseX Ethernet
+product INTEL 82572EI_SERDES 0x107f i82572EI Gigabit Ethernet (SERDES)
+product INTEL 82546GB_PCIE 0x108A PRO/1000MT (82546GB)
+product INTEL 82573E 0x108b i82573E Gigabit Ethernet
+product INTEL 82573E_IAMT 0x108c i82573E Gigabit Ethernet
+product INTEL 82573L 0x109a i82573L Gigabit Ethernet
+product INTEL 82546GB_QUAD_COPPER 0x1099 PRO/1000MT QP (82546GB)
product INTEL 82815_DC100_HUB 0x1100 82815 Hub
product INTEL 82815_DC100_AGP 0x1101 82815 AGP
product INTEL 82815_DC100_GRAPH 0x1102 82815 Graphics