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_ */