Module Name: src
Committed By: sborrill
Date: Wed Dec 23 10:37:37 UTC 2009
Modified Files:
src/sys/dev/mii [netbsd-5]: igphy.c
src/sys/dev/pci [netbsd-5]: if_wm.c if_wmreg.h
Added Files:
src/sys/dev/pci [netbsd-5]: if_wmvar.h
Log Message:
Pull up the following revisions(s) (requested by msaitoh in ticket #1203):
sys/dev/pci/if_wm.c: 1.176-1.179, 1.181-1.183
sys/dev/pci/if_wmreg.h: 1.28
sys/dev/pci/if_wmvar.h: 1.1-1.4
sys/dev/mii/igphy.c: 1.18-1.20 via patch
Many bugfixes:
- Some fixes for i80003 and ICH{8,9,10} from e1000 driver and document:
- Add setting for KABGTXD register for ICH{8,9,10}.
- ICH9 and ICH10 has no FCAL, FCAH and FCT like ICH8.
- Add special setting for FCTTV and TCTL_EXT register for i80003
- The special setting for TIPG is only for i80003.
- Some of kumeran settings are only for i80003's bugs.
- Add some ICH10 fixes.
- Fix the bug that another lock mechanism is used to access Kumeran
registers on i80003 and ICHs.
- Fix yet another i80003 ONLY workaround. The code to modifing TIPG
register is only for i80003.
- Set the Re-Transmit on Late Collision(RTLC) flag for all devices.
- Fix a typo in a printf message.
- If the difference bettween last flag and new flag is only IFF_PROMISC
or IFF_ALLMULTI, set multicast filter only to prevent link down.
Tested by Mark Davies and me. Fixes PR#29126 for wm.
- Cleanup interrupt establish error messages. Do not mix
aprint_error/aprint_normal/printf calls for a single line.
- Fix igphy's 82566 support.
- Patch for the DSP code is only for 8254[17] and we have to apply
the different patches between rev. 1 and rev. 2.
- The workaround for analog fuse is only for 82547 rev. 1.
- The workaround for smartspeed is only for 8254[17]
- Sync with Intel's original em driver:
- Check PCI-X mode as e1000 driver.
- Add dspcode for igp3 and use it when the EEPROM isn't available.
- Add some delays.
- Stop the PHY transmitter before patching the DSP code and
restart it after writing.
- Save and restore register 0x2f5b.
To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.16.10.1 src/sys/dev/mii/igphy.c
cvs rdiff -u -r1.162.4.10 -r1.162.4.11 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.24.20.2 -r1.24.20.3 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r0 -r1.2.46.1 src/sys/dev/pci/if_wmvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/mii/igphy.c
diff -u src/sys/dev/mii/igphy.c:1.16 src/sys/dev/mii/igphy.c:1.16.10.1
--- src/sys/dev/mii/igphy.c:1.16 Sun May 4 17:06:09 2008
+++ src/sys/dev/mii/igphy.c Wed Dec 23 10:37:37 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: igphy.c,v 1.16 2008/05/04 17:06:09 xtraeme Exp $ */
+/* $NetBSD: igphy.c,v 1.16.10.1 2009/12/23 10:37:37 sborrill Exp $ */
/*
* The Intel copyright applies to the analog register setup, and the
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.16 2008/05/04 17:06:09 xtraeme Exp $");
+__KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.16.10.1 2009/12/23 10:37:37 sborrill Exp $");
#include "opt_mii.h"
@@ -87,16 +87,19 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include <dev/mii/miidevs.h>
-
#include <dev/mii/igphyreg.h>
+#include <dev/pci/if_wmvar.h>
struct igphy_softc {
struct mii_softc sc_mii;
int sc_smartspeed;
+ uint32_t sc_mactype;
+ uint32_t sc_macflags;
};
static void igphy_reset(struct mii_softc *);
static void igphy_load_dspcode(struct mii_softc *);
+static void igphy_load_dspcode_igp3(struct mii_softc *);
static void igphy_smartspeed_workaround(struct mii_softc *sc);
static int igphymatch(device_t, cfdata_t, void *);
@@ -141,11 +144,19 @@
struct mii_attach_args *ma = aux;
struct mii_data *mii = ma->mii_data;
const struct mii_phydesc *mpd;
+ struct igphy_softc *igsc = (struct igphy_softc *) sc;
+ prop_dictionary_t dict;
mpd = mii_phy_match(ma, igphys);
aprint_naive(": Media interface\n");
aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
+ dict = device_properties(parent);
+ if (!prop_dictionary_get_uint32(dict, "mactype", &igsc->sc_mactype))
+ aprint_error("WARNING! Failed to get mactype\n");
+ if (!prop_dictionary_get_uint32(dict, "macflags", &igsc->sc_macflags))
+ aprint_error("WARNING! Failed to get macflags\n");
+
sc->mii_dev = self;
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
@@ -172,70 +183,178 @@
aprint_error_dev(self, "couldn't establish power handler\n");
}
+typedef struct {
+ int reg;
+ uint16_t val;
+} dspcode;
+
+static const dspcode igp1code[] = {
+ { 0x1f95, 0x0001 },
+ { 0x1f71, 0xbd21 },
+ { 0x1f79, 0x0018 },
+ { 0x1f30, 0x1600 },
+ { 0x1f31, 0x0014 },
+ { 0x1f32, 0x161c },
+ { 0x1f94, 0x0003 },
+ { 0x1f96, 0x003f },
+ { 0x2010, 0x0008 },
+ { 0, 0 },
+};
+
+static const dspcode igp1code_r2[] = {
+ { 0x1f73, 0x0099 },
+ { 0, 0 },
+};
+
+static const dspcode igp3code[] = {
+ { 0x2f5b, 0x9018},
+ { 0x2f52, 0x0000},
+ { 0x2fb1, 0x8b24},
+ { 0x2fb2, 0xf8f0},
+ { 0x2010, 0x10b0},
+ { 0x2011, 0x0000},
+ { 0x20dd, 0x249a},
+ { 0x20de, 0x00d3},
+ { 0x28b4, 0x04ce},
+ { 0x2f70, 0x29e4},
+ { 0x0000, 0x0140},
+ { 0x1f30, 0x1606},
+ { 0x1f31, 0xb814},
+ { 0x1f35, 0x002a},
+ { 0x1f3e, 0x0067},
+ { 0x1f54, 0x0065},
+ { 0x1f55, 0x002a},
+ { 0x1f56, 0x002a},
+ { 0x1f72, 0x3fb0},
+ { 0x1f76, 0xc0ff},
+ { 0x1f77, 0x1dec},
+ { 0x1f78, 0xf9ef},
+ { 0x1f79, 0x0210},
+ { 0x1895, 0x0003},
+ { 0x1796, 0x0008},
+ { 0x1798, 0xd008},
+ { 0x1898, 0xd918},
+ { 0x187a, 0x0800},
+ { 0x0019, 0x008d},
+ { 0x001b, 0x2080},
+ { 0x0014, 0x0045},
+ { 0x0000, 0x1340},
+ { 0, 0 },
+};
+
+/* DSP patch for igp1 and igp2 */
static void
igphy_load_dspcode(struct mii_softc *sc)
{
- static const struct {
- int reg;
- uint16_t val;
- } dspcode[] = {
- { 0x1f95, 0x0001 },
- { 0x1f71, 0xbd21 },
- { 0x1f79, 0x0018 },
- { 0x1f30, 0x1600 },
- { 0x1f31, 0x0014 },
- { 0x1f32, 0x161c },
- { 0x1f94, 0x0003 },
- { 0x1f96, 0x003f },
- { 0x2010, 0x0008 },
- { 0, 0 },
- };
+ struct igphy_softc *igsc = (struct igphy_softc *) sc;
+ const dspcode *code;
+ uint16_t reg;
int i;
- delay(10);
+ /* This workaround is only for 82541 and 82547 */
+ switch (igsc->sc_mactype) {
+ case WM_T_82541:
+ case WM_T_82547:
+ code = igp1code;
+ break;
+ case WM_T_82541_2:
+ case WM_T_82547_2:
+ code = igp1code_r2;
+ break;
+ default:
+ return; /* byebye */
+ }
+
+ /* Delay after phy reset to enable NVM configuration to load */
+ delay(20000);
+
+ /*
+ * Save off the current value of register 0x2F5B to be restored at
+ * the end of this routine.
+ */
+ reg = IGPHY_READ(sc, 0x2f5b);
+
+ /* Disabled the PHY transmitter */
+ IGPHY_WRITE(sc, 0x2f5b, 0x0003);
+
+ delay(20000);
PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
PHY_WRITE(sc, 0x0000, 0x0140);
- delay(5);
+ delay(5000);
- for (i = 0; dspcode[i].reg != 0; i++)
- IGPHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
+ for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++)
+ IGPHY_WRITE(sc, code[i].reg, code[i].val);
PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
PHY_WRITE(sc, 0x0000, 0x3300);
+
+ delay(20000);
+
+ /* Now enable the transmitter */
+ IGPHY_WRITE(sc, 0x2f5b, reg);
+}
+
+static void
+igphy_load_dspcode_igp3(struct mii_softc *sc)
+{
+ const dspcode *code = igp3code;
+ int i;
+
+ for (i = 0; !((code[i].reg == 0) && (code[i].val == 0)); i++)
+ IGPHY_WRITE(sc, code[i].reg, code[i].val);
}
static void
igphy_reset(struct mii_softc *sc)
{
+ struct igphy_softc *igsc = (struct igphy_softc *) sc;
uint16_t fused, fine, coarse;
mii_phy_reset(sc);
- igphy_load_dspcode(sc);
+ delay(150);
- fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS);
- if ((fused & ANALOG_SPARE_FUSE_ENABLED) == 0) {
- fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_FUSE_STATUS);
-
- fine = fused & ANALOG_FUSE_FINE_MASK;
- coarse = fused & ANALOG_FUSE_COARSE_MASK;
-
- if (coarse > ANALOG_FUSE_COARSE_THRESH) {
- coarse -= ANALOG_FUSE_COARSE_10;
- fine -= ANALOG_FUSE_FINE_1;
- } else if (coarse == ANALOG_FUSE_COARSE_THRESH)
- fine -= ANALOG_FUSE_FINE_10;
-
- fused = (fused & ANALOG_FUSE_POLY_MASK) |
- (fine & ANALOG_FUSE_FINE_MASK) |
- (coarse & ANALOG_FUSE_COARSE_MASK);
-
- IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_CONTROL, fused);
- IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_BYPASS,
- ANALOG_FUSE_ENABLE_SW_CONTROL);
+ switch (igsc->sc_mactype) {
+ case WM_T_82541:
+ case WM_T_82547:
+ case WM_T_82541_2:
+ case WM_T_82547_2:
+ igphy_load_dspcode(sc);
+ break;
+ case WM_T_ICH8:
+ case WM_T_ICH9:
+ if ((igsc->sc_macflags & WM_F_EEPROM_INVALID) != 0)
+ igphy_load_dspcode_igp3(sc);
+ break;
+ default: /* Not for ICH10, PCH and 8257[12] */
+ break;
}
- PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
+
+ if (igsc->sc_mactype == WM_T_82547) {
+ fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS);
+ if ((fused & ANALOG_SPARE_FUSE_ENABLED) == 0) {
+ fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_FUSE_STATUS);
+
+ fine = fused & ANALOG_FUSE_FINE_MASK;
+ coarse = fused & ANALOG_FUSE_COARSE_MASK;
+
+ if (coarse > ANALOG_FUSE_COARSE_THRESH) {
+ coarse -= ANALOG_FUSE_COARSE_10;
+ fine -= ANALOG_FUSE_FINE_1;
+ } else if (coarse == ANALOG_FUSE_COARSE_THRESH)
+ fine -= ANALOG_FUSE_FINE_10;
+
+ fused = (fused & ANALOG_FUSE_POLY_MASK) |
+ (fine & ANALOG_FUSE_FINE_MASK) |
+ (coarse & ANALOG_FUSE_COARSE_MASK);
+
+ IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_CONTROL, fused);
+ IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_BYPASS,
+ ANALOG_FUSE_ENABLE_SW_CONTROL);
+ }
+ }
+ PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
}
@@ -382,6 +501,19 @@
struct igphy_softc *igsc = (struct igphy_softc *) sc;
uint16_t reg, gtsr, gtcr;
+
+ /* This workaround is only for 82541 and 82547 */
+ switch (igsc->sc_mactype) {
+ case WM_T_82541:
+ case WM_T_82541_2:
+ case WM_T_82547:
+ case WM_T_82547_2:
+ break;
+ default:
+ /* byebye */
+ return;
+ }
+
if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0)
return;
Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.162.4.10 src/sys/dev/pci/if_wm.c:1.162.4.11
--- src/sys/dev/pci/if_wm.c:1.162.4.10 Fri Jun 5 18:49:42 2009
+++ src/sys/dev/pci/if_wm.c Wed Dec 23 10:37:37 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.162.4.10 2009/06/05 18:49:42 snj Exp $ */
+/* $NetBSD: if_wm.c,v 1.162.4.11 2009/12/23 10:37:37 sborrill Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.162.4.10 2009/06/05 18:49:42 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.162.4.11 2009/12/23 10:37:37 sborrill Exp $");
#include "bpfilter.h"
#include "rnd.h"
@@ -129,6 +129,7 @@
#include <dev/pci/pcidevs.h>
#include <dev/pci/if_wmreg.h>
+#include <dev/pci/if_wmvar.h>
#ifdef WM_DEBUG
#define WM_DEBUG_LINK 0x01
@@ -229,31 +230,6 @@
bus_dmamap_t rxs_dmamap; /* our DMA map */
};
-typedef enum {
- WM_T_unknown = 0,
- WM_T_82542_2_0, /* i82542 2.0 (really old) */
- WM_T_82542_2_1, /* i82542 2.1+ (old) */
- WM_T_82543, /* i82543 */
- WM_T_82544, /* i82544 */
- WM_T_82540, /* i82540 */
- WM_T_82545, /* i82545 */
- WM_T_82545_3, /* i82545 3.0+ */
- WM_T_82546, /* i82546 */
- WM_T_82546_3, /* i82546 3.0+ */
- WM_T_82541, /* i82541 */
- WM_T_82541_2, /* i82541 2.0+ */
- WM_T_82547, /* i82547 */
- WM_T_82547_2, /* i82547 2.0+ */
- WM_T_82571, /* i82571 */
- WM_T_82572, /* i82572 */
- WM_T_82573, /* i82573 */
- WM_T_82574, /* i82574 */
- WM_T_80003, /* i80003 */
- WM_T_ICH8, /* ICH8 LAN */
- WM_T_ICH9, /* ICH9 LAN */
- WM_T_ICH10, /* ICH10 LAN */
-} wm_chip_type;
-
#define WM_LINKUP_TIMEOUT 50
/*
@@ -274,6 +250,7 @@
wm_chip_type sc_type; /* chip type */
int sc_flags; /* flags; see below */
+ int sc_if_flags; /* last if_flags */
int sc_bus_speed; /* PCI/PCIX bus speed */
int sc_pcix_offset; /* PCIX capability register offset */
int sc_flowflags; /* 802.3x flow control flags */
@@ -403,22 +380,6 @@
(sc)->sc_rxtailp = &(m)->m_next; \
} while (/*CONSTCOND*/0)
-/* sc_flags */
-#define WM_F_HAS_MII 0x0001 /* has MII */
-#define WM_F_EEPROM_HANDSHAKE 0x0002 /* requires EEPROM handshake */
-#define WM_F_EEPROM_SEMAPHORE 0x0004 /* EEPROM with semaphore */
-#define WM_F_EEPROM_EERDEEWR 0x0008 /* EEPROM access via EERD/EEWR */
-#define WM_F_EEPROM_SPI 0x0010 /* EEPROM is SPI */
-#define WM_F_EEPROM_FLASH 0x0020 /* EEPROM is FLASH */
-#define WM_F_EEPROM_INVALID 0x0040 /* EEPROM not present (bad checksum) */
-#define WM_F_IOH_VALID 0x0080 /* I/O handle is valid */
-#define WM_F_BUS64 0x0100 /* bus is 64-bit */
-#define WM_F_PCIX 0x0200 /* bus is PCI-X */
-#define WM_F_CSA 0x0400 /* bus is CSA */
-#define WM_F_PCIE 0x0800 /* bus is PCI-Express */
-#define WM_F_SWFW_SYNC 0x1000 /* Software-Firmware synchronisation */
-#define WM_F_SWFWHW_SYNC 0x2000 /* Software-Firmware synchronisation */
-
#ifdef WM_EVENT_COUNTERS
#define WM_EVCNT_INCR(ev) (ev)->ev_count++
#define WM_EVCNT_ADD(ev, val) (ev)->ev_count += (val)
@@ -566,8 +527,8 @@
static int wm_gmii_mediachange(struct ifnet *);
static void wm_gmii_mediastatus(struct ifnet *, struct ifmediareq *);
-static int wm_kmrn_i80003_readreg(struct wm_softc *, int);
-static void wm_kmrn_i80003_writereg(struct wm_softc *, int, int);
+static int wm_kmrn_readreg(struct wm_softc *, int);
+static void wm_kmrn_writereg(struct wm_softc *, int, int);
static int wm_match(device_t, cfdata_t, void *);
static void wm_attach(device_t, device_t, void *);
@@ -952,6 +913,7 @@
{
struct wm_softc *sc = device_private(self);
struct pci_attach_args *pa = aux;
+ prop_dictionary_t dict;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
pci_chipset_tag_t pc = pa->pa_pc;
pci_intr_handle_t ih;
@@ -1003,6 +965,10 @@
sc->sc_type = WM_T_82542_2_0;
}
+ /* Set device properties (mactype)*/
+ dict = device_properties(sc->sc_dev);
+ prop_dictionary_set_uint32(dict, "mactype", sc->sc_type);
+
/*
* Map the device. All devices support memory-mapped acccess,
* and it is really required for normal operation.
@@ -1091,8 +1057,8 @@
if (sc->sc_ih == NULL) {
aprint_error_dev(sc->sc_dev, "unable to establish interrupt");
if (intrstr != NULL)
- aprint_normal(" at %s", intrstr);
- aprint_normal("\n");
+ aprint_error(" at %s", intrstr);
+ aprint_error("\n");
return;
}
aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
@@ -1129,8 +1095,7 @@
reg = CSR_READ(sc, WMREG_STATUS);
if (reg & STATUS_BUS64)
sc->sc_flags |= WM_F_BUS64;
- if (sc->sc_type >= WM_T_82544 &&
- (reg & STATUS_PCIX_MODE) != 0) {
+ if ((reg & STATUS_PCIX_MODE) != 0) {
pcireg_t pcix_cmd, pcix_sts, bytecnt, maxb;
sc->sc_flags |= WM_F_PCIX;
@@ -1370,18 +1335,26 @@
* that no EEPROM is attached.
*/
- /*
- * Validate the EEPROM checksum. If the checksum fails, flag this for
- * later, so we can fail future reads from the EEPROM.
- */
- if (wm_validate_eeprom_checksum(sc)) {
+ /* Check whether EEPROM is present or not */
+ if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) {
+ /* Not found */
+ sc->sc_flags |= WM_F_EEPROM_INVALID;
+ } else {
/*
- * Read twice again because some PCI-e parts fail the first
- * check due to the link being in sleep state.
+ * Validate the EEPROM checksum. If the checksum fails, flag
+ * this for later, so we can fail future reads from the EEPROM.
*/
- if (wm_validate_eeprom_checksum(sc))
- sc->sc_flags |= WM_F_EEPROM_INVALID;
+ if (wm_validate_eeprom_checksum(sc)) {
+ /*
+ * Read twice again because some PCI-e parts fail the
+ * first check due to the link being in sleep state.
+ */
+ if (wm_validate_eeprom_checksum(sc))
+ sc->sc_flags |= WM_F_EEPROM_INVALID;
+ }
}
+ /* Set device properties (macflags)*/
+ prop_dictionary_set_uint32(dict, "macflags", sc->sc_flags);
if (sc->sc_flags & WM_F_EEPROM_INVALID)
aprint_verbose_dev(sc->sc_dev, "No EEPROM\n");
@@ -1402,7 +1375,7 @@
* Read the Ethernet address from the EEPROM, if not first found
* in device properties.
*/
- ea = prop_dictionary_get(device_properties(sc->sc_dev), "mac-addr");
+ ea = prop_dictionary_get(dict, "mac-addr");
if (ea != NULL) {
KASSERT(prop_object_type(ea) == PROP_TYPE_DATA);
KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN);
@@ -1439,8 +1412,7 @@
* Read the config info from the EEPROM, and set up various
* bits in the control registers based on their contents.
*/
- pn = prop_dictionary_get(device_properties(sc->sc_dev),
- "i82543-cfg1");
+ pn = prop_dictionary_get(dict, "i82543-cfg1");
if (pn != NULL) {
KASSERT(prop_object_type(pn) == PROP_TYPE_NUMBER);
cfg1 = (uint16_t) prop_number_integer_value(pn);
@@ -1451,8 +1423,7 @@
}
}
- pn = prop_dictionary_get(device_properties(sc->sc_dev),
- "i82543-cfg2");
+ pn = prop_dictionary_get(dict, "i82543-cfg2");
if (pn != NULL) {
KASSERT(prop_object_type(pn) == PROP_TYPE_NUMBER);
cfg2 = (uint16_t) prop_number_integer_value(pn);
@@ -1464,8 +1435,7 @@
}
if (sc->sc_type >= WM_T_82544) {
- pn = prop_dictionary_get(device_properties(sc->sc_dev),
- "i82543-swdpin");
+ pn = prop_dictionary_get(dict, "i82543-swdpin");
if (pn != NULL) {
KASSERT(prop_object_type(pn) == PROP_TYPE_NUMBER);
swdpin = (uint16_t) prop_number_integer_value(pn);
@@ -2368,11 +2338,40 @@
struct ifreq *ifr = (struct ifreq *) data;
struct ifaddr *ifa = (struct ifaddr *)data;
struct sockaddr_dl *sdl;
- int s, error;
+ int diff, s, error;
s = splnet();
switch (cmd) {
+ case SIOCSIFFLAGS:
+ if ((error = ifioctl_common(ifp, cmd, data)) != 0)
+ break;
+ if (ifp->if_flags & IFF_UP) {
+ diff = (ifp->if_flags ^ sc->sc_if_flags)
+ & (IFF_PROMISC | IFF_ALLMULTI);
+ if ((diff & (IFF_PROMISC | IFF_ALLMULTI)) != 0) {
+ /*
+ * If the difference bettween last flag and
+ * new flag is only IFF_PROMISC or
+ * IFF_ALLMULTI, set multicast filter only
+ * (don't reset to prevent link down).
+ */
+ wm_set_filter(sc);
+ } else {
+ /*
+ * Reset the interface to pick up changes in
+ * any other flags that affect the hardware
+ * state.
+ */
+ wm_init(ifp);
+ }
+ } else {
+ if (ifp->if_flags & IFF_RUNNING)
+ wm_stop(ifp, 1);
+ }
+ sc->sc_if_flags = ifp->if_flags;
+ error = 0;
+ break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
/* Flow control requires full-duplex mode. */
@@ -3265,7 +3264,8 @@
*
* XXX Values could probably stand some tuning.
*/
- if (sc->sc_type != WM_T_ICH8) {
+ if ((sc->sc_type != WM_T_ICH8) && (sc->sc_type != WM_T_ICH9)
+ && (sc->sc_type != WM_T_ICH10)) {
CSR_WRITE(sc, WMREG_FCAL, FCAL_CONST);
CSR_WRITE(sc, WMREG_FCAH, FCAH_CONST);
CSR_WRITE(sc, WMREG_FCT, ETHERTYPE_FLOWCONTROL);
@@ -3279,7 +3279,11 @@
CSR_WRITE(sc, WMREG_FCRTH, FCRTH_DFLT);
CSR_WRITE(sc, WMREG_FCRTL, sc->sc_fcrtl);
}
- CSR_WRITE(sc, WMREG_FCTTV, FCTTV_DFLT);
+
+ if (sc->sc_type == WM_T_80003)
+ CSR_WRITE(sc, WMREG_FCTTV, 0xffff);
+ else
+ CSR_WRITE(sc, WMREG_FCTTV, FCTTV_DFLT);
/* Deal with VLAN enables. */
if (VLAN_ATTACHED(&sc->sc_ethercom))
@@ -3289,29 +3293,47 @@
/* Write the control registers. */
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
- if (sc->sc_type >= WM_T_80003 && (sc->sc_flags & WM_F_HAS_MII)) {
+
+ if (sc->sc_flags & WM_F_HAS_MII) {
int val;
- val = CSR_READ(sc, WMREG_CTRL_EXT);
- val &= ~CTRL_EXT_LINK_MODE_MASK;
- CSR_WRITE(sc, WMREG_CTRL_EXT, val);
-
- /* Bypass RX and TX FIFO's */
- wm_kmrn_i80003_writereg(sc, KUMCTRLSTA_OFFSET_FIFO_CTRL,
- KUMCTRLSTA_FIFO_CTRL_RX_BYPASS |
- KUMCTRLSTA_FIFO_CTRL_TX_BYPASS);
+
+ switch (sc->sc_type) {
+ case WM_T_80003:
+ case WM_T_ICH8:
+ case WM_T_ICH9:
+ case WM_T_ICH10:
+ /*
+ * 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.
+ */
+ wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_TIMEOUTS,
+ 0xFFFF);
+ val = wm_kmrn_readreg(sc,
+ KUMCTRLSTA_OFFSET_INB_PARAM);
+ val |= 0x3F;
+ wm_kmrn_writereg(sc,
+ KUMCTRLSTA_OFFSET_INB_PARAM, val);
+ break;
+ default:
+ break;
+ }
+
+ if (sc->sc_type == WM_T_80003) {
+ val = CSR_READ(sc, WMREG_CTRL_EXT);
+ val &= ~CTRL_EXT_LINK_MODE_MASK;
+ CSR_WRITE(sc, WMREG_CTRL_EXT, val);
+
+ /* Bypass RX and TX FIFO's */
+ wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_FIFO_CTRL,
+ KUMCTRLSTA_FIFO_CTRL_RX_BYPASS |
+ KUMCTRLSTA_FIFO_CTRL_TX_BYPASS);
- wm_kmrn_i80003_writereg(sc, KUMCTRLSTA_OFFSET_INB_CTRL,
- KUMCTRLSTA_INB_CTRL_DIS_PADDING |
- KUMCTRLSTA_INB_CTRL_LINK_TMOUT_DFLT);
- /*
- * 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.
- */
- wm_kmrn_i80003_writereg(sc, KUMCTRLSTA_OFFSET_TIMEOUTS, 0xFFFF);
- val = wm_kmrn_i80003_readreg(sc, KUMCTRLSTA_OFFSET_INB_PARAM);
- val |= 0x3F;
- wm_kmrn_i80003_writereg(sc, KUMCTRLSTA_OFFSET_INB_PARAM, val);
+ wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_INB_CTRL,
+ KUMCTRLSTA_INB_CTRL_DIS_PADDING |
+ KUMCTRLSTA_INB_CTRL_LINK_TMOUT_DFLT);
+ }
}
#if 0
CSR_WRITE(sc, WMREG_CTRL_EXT, sc->sc_ctrl_ext);
@@ -3343,6 +3365,13 @@
sc->sc_icr |= ICR_RXCFG;
CSR_WRITE(sc, WMREG_IMS, sc->sc_icr);
+ if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
+ || (sc->sc_type == WM_T_ICH10)) {
+ reg = CSR_READ(sc, WMREG_KABGTXD);
+ reg |= KABGTXD_BGSQLBIAS;
+ CSR_WRITE(sc, WMREG_KABGTXD, reg);
+ }
+
/* Set up the inter-packet gap. */
CSR_WRITE(sc, WMREG_TIPG, sc->sc_tipg);
@@ -3378,14 +3407,20 @@
* a collision distance suitable for FDX, but update it whe
* we resolve the media type.
*/
- sc->sc_tctl = TCTL_EN | TCTL_PSP | TCTL_CT(TX_COLLISION_THRESHOLD) |
- TCTL_COLD(TX_COLLISION_DISTANCE_FDX);
+ sc->sc_tctl = TCTL_EN | TCTL_PSP | TCTL_RTLC
+ | TCTL_CT(TX_COLLISION_THRESHOLD)
+ | TCTL_COLD(TX_COLLISION_DISTANCE_FDX);
if (sc->sc_type >= WM_T_82571)
sc->sc_tctl |= TCTL_MULR;
- if (sc->sc_type >= WM_T_80003)
- sc->sc_tctl |= TCTL_RTLC;
CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl);
+ if (sc->sc_type == WM_T_80003) {
+ reg = CSR_READ(sc, WMREG_TCTL_EXT);
+ reg &= ~TCTL_EXT_GCEX_MASK;
+ reg |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX;
+ CSR_WRITE(sc, WMREG_TCTL_EXT, reg);
+ }
+
/* Set the media. */
if ((error = mii_ifmedia_change(&sc->sc_mii)) != 0)
goto out;
@@ -4488,7 +4523,7 @@
/* We have MII. */
sc->sc_flags |= WM_F_HAS_MII;
- if (sc->sc_type >= WM_T_80003)
+ if (sc->sc_type == WM_T_80003)
sc->sc_tipg = TIPG_1000T_80003_DFLT;
else
sc->sc_tipg = TIPG_1000T_DFLT;
@@ -4965,15 +5000,15 @@
CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl);
CSR_WRITE(sc, (sc->sc_type < WM_T_82543) ? WMREG_OLD_FCRTL
: WMREG_FCRTL, sc->sc_fcrtl);
- if (sc->sc_type >= WM_T_80003) {
+ if (sc->sc_type == WM_T_80003) {
switch(IFM_SUBTYPE(sc->sc_mii.mii_media_active)) {
case IFM_1000_T:
- wm_kmrn_i80003_writereg(sc, KUMCTRLSTA_OFFSET_HD_CTRL,
+ wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_HD_CTRL,
KUMCTRLSTA_HD_CTRL_1000_DEFAULT);
sc->sc_tipg = TIPG_1000T_80003_DFLT;
break;
default:
- wm_kmrn_i80003_writereg(sc, KUMCTRLSTA_OFFSET_HD_CTRL,
+ wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_HD_CTRL,
KUMCTRLSTA_HD_CTRL_10_100_DEFAULT);
sc->sc_tipg = TIPG_10_100_80003_DFLT;
break;
@@ -4983,20 +5018,27 @@
}
/*
- * wm_kmrn_i80003_readreg:
+ * wm_kmrn_readreg:
*
* Read a kumeran register
*/
static int
-wm_kmrn_i80003_readreg(struct wm_softc *sc, int reg)
+wm_kmrn_readreg(struct wm_softc *sc, int reg)
{
- int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1);
int rv;
- if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) {
- aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
- __func__);
- return 0;
+ if (sc->sc_flags == WM_F_SWFW_SYNC) {
+ if (wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM)) {
+ aprint_error_dev(sc->sc_dev,
+ "%s: failed to get semaphore\n", __func__);
+ return 0;
+ }
+ } else if (sc->sc_flags == WM_F_SWFWHW_SYNC) {
+ if (wm_get_swfwhw_semaphore(sc)) {
+ aprint_error_dev(sc->sc_dev,
+ "%s: failed to get semaphore\n", __func__);
+ return 0;
+ }
}
CSR_WRITE(sc, WMREG_KUMCTRLSTA,
@@ -5005,30 +5047,46 @@
delay(2);
rv = CSR_READ(sc, WMREG_KUMCTRLSTA) & KUMCTRLSTA_MASK;
- wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+
+ if (sc->sc_flags == WM_F_SWFW_SYNC)
+ wm_put_swfw_semaphore(sc, SWFW_MAC_CSR_SM);
+ else if (sc->sc_flags == WM_F_SWFWHW_SYNC)
+ wm_put_swfwhw_semaphore(sc);
+
return (rv);
}
/*
- * wm_kmrn_i80003_writereg:
+ * wm_kmrn_writereg:
*
* Write a kumeran register
*/
static void
-wm_kmrn_i80003_writereg(struct wm_softc *sc, int reg, int val)
+wm_kmrn_writereg(struct wm_softc *sc, int reg, int val)
{
- int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1);
- if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) {
- aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
- __func__);
- return;
+ if (sc->sc_flags == WM_F_SWFW_SYNC) {
+ if (wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM)) {
+ aprint_error_dev(sc->sc_dev,
+ "%s: failed to get semaphore\n", __func__);
+ return;
+ }
+ } else if (sc->sc_flags == WM_F_SWFWHW_SYNC) {
+ if (wm_get_swfwhw_semaphore(sc)) {
+ aprint_error_dev(sc->sc_dev,
+ "%s: failed to get semaphore\n", __func__);
+ return;
+ }
}
CSR_WRITE(sc, WMREG_KUMCTRLSTA,
((reg << KUMCTRLSTA_OFFSET_SHIFT) & KUMCTRLSTA_OFFSET) |
(val & KUMCTRLSTA_MASK));
- wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+
+ if (sc->sc_flags == WM_F_SWFW_SYNC)
+ wm_put_swfw_semaphore(sc, SWFW_MAC_CSR_SM);
+ else if (sc->sc_flags == WM_F_SWFWHW_SYNC)
+ wm_put_swfwhw_semaphore(sc);
}
static int
@@ -5156,7 +5214,7 @@
return 0;
delay(5000);
}
- printf("%s: failed to get swfwgw semaphore ext_ctrl 0x%x\n",
+ printf("%s: failed to get swfwhw semaphore ext_ctrl 0x%x\n",
device_xname(sc->sc_dev), ext_ctrl);
return 1;
}
Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.24.20.2 src/sys/dev/pci/if_wmreg.h:1.24.20.3
--- src/sys/dev/pci/if_wmreg.h:1.24.20.2 Thu May 21 01:13:49 2009
+++ src/sys/dev/pci/if_wmreg.h Wed Dec 23 10:37:37 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmreg.h,v 1.24.20.2 2009/05/21 01:13:49 snj Exp $ */
+/* $NetBSD: if_wmreg.h,v 1.24.20.3 2009/12/23 10:37:37 sborrill Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -610,8 +610,14 @@
#define WMREG_TXDMAC 0x3000 /* Transfer DMA Control */
#define TXDMAC_DPP (1U << 0) /* disable packet prefetch */
+#define WMREG_KABGTXD 0x3004 /* AFE and Gap Transmit Ref Data */
+#define KABGTXD_BGSQLBIAS 0x00050000
+
#define WMREG_TSPMT 0x3830 /* TCP Segmentation Pad and Minimum
Threshold (Cordova) */
+
+#define WMREG_TARC0 0x3840 /* Tx arbitration count */
+
#define TSPMT_TSMT(x) (x) /* TCP seg min transfer */
#define TSPMT_TSPBP(x) ((x) << 16) /* TCP seg pkt buf padding */
Added files:
Index: src/sys/dev/pci/if_wmvar.h
diff -u /dev/null src/sys/dev/pci/if_wmvar.h:1.2.46.1
--- /dev/null Wed Dec 23 10:37:37 2009
+++ src/sys/dev/pci/if_wmvar.h Wed Dec 23 10:37:37 2009
@@ -0,0 +1,115 @@
+/* $NetBSD: if_wmvar.h,v 1.2.46.1 2009/12/23 10:37:37 sborrill Exp $ */
+
+/*
+ * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*******************************************************************************
+
+ Copyright (c) 2001-2005, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _DEV_PCI_IF_WMVAR_H_
+#define _DEV_PCI_IF_WMVAR_H_
+
+/* sc_flags */
+#define WM_F_HAS_MII 0x0001 /* has MII */
+#define WM_F_EEPROM_HANDSHAKE 0x0002 /* requires EEPROM handshake */
+#define WM_F_EEPROM_SEMAPHORE 0x0004 /* EEPROM with semaphore */
+#define WM_F_EEPROM_EERDEEWR 0x0008 /* EEPROM access via EERD/EEWR */
+#define WM_F_EEPROM_SPI 0x0010 /* EEPROM is SPI */
+#define WM_F_EEPROM_FLASH 0x0020 /* EEPROM is FLASH */
+#define WM_F_EEPROM_INVALID 0x0040 /* EEPROM not present (bad checksum) */
+#define WM_F_IOH_VALID 0x0080 /* I/O handle is valid */
+#define WM_F_BUS64 0x0100 /* bus is 64-bit */
+#define WM_F_PCIX 0x0200 /* bus is PCI-X */
+#define WM_F_CSA 0x0400 /* bus is CSA */
+#define WM_F_PCIE 0x0800 /* bus is PCI-Express */
+#define WM_F_SWFW_SYNC 0x1000 /* Software-Firmware synchronisation */
+#define WM_F_SWFWHW_SYNC 0x2000 /* Software-Firmware synchronisation */
+
+typedef enum {
+ WM_T_unknown = 0,
+ WM_T_82542_2_0, /* i82542 2.0 (really old) */
+ WM_T_82542_2_1, /* i82542 2.1+ (old) */
+ WM_T_82543, /* i82543 */
+ WM_T_82544, /* i82544 */
+ WM_T_82540, /* i82540 */
+ WM_T_82545, /* i82545 */
+ WM_T_82545_3, /* i82545 3.0+ */
+ WM_T_82546, /* i82546 */
+ WM_T_82546_3, /* i82546 3.0+ */
+ WM_T_82541, /* i82541 */
+ WM_T_82541_2, /* i82541 2.0+ */
+ WM_T_82547, /* i82547 */
+ WM_T_82547_2, /* i82547 2.0+ */
+ WM_T_82571, /* i82571 */
+ WM_T_82572, /* i82572 */
+ WM_T_82573, /* i82573 */
+ WM_T_82574, /* i82574 */
+ WM_T_80003, /* i80003 */
+ WM_T_ICH8, /* ICH8 LAN */
+ WM_T_ICH9, /* ICH9 LAN */
+ WM_T_ICH10, /* ICH10 LAN */
+} wm_chip_type;
+
+#endif /* _DEV_PCI_IF_WMVAR_H_ */