--- if_re.c.orig +++ if_re.c @@ -155,6 +155,11 @@ /* "device miibus" required. See GENERIC if you get errors here. */ #include "miibus_if.h" +/* + * Default to using PIO access for this driver. + */ +#define RE_USEIOSPACE + /* Tunables. */ static int msi_disable = 1; TUNABLE_INT("hw.re.msi_disable", &msi_disable); @@ -275,6 +280,14 @@ static int re_diag (struct rl_softc *); #endif +#ifdef RE_USEIOSPACE +#define RL_RES SYS_RES_IOPORT +#define RL_RID RL_PCI_LOIO +#else +#define RL_RES SYS_RES_MEMORY +#define RL_RID RL_PCI_LOMEM +#endif + static device_method_t re_methods[] = { /* Device interface */ DEVMETHOD(device_probe, re_probe), @@ -613,20 +626,17 @@ re_setmulti(struct rl_softc *sc) { struct ifnet *ifp; - int h = 0; - u_int32_t hashes[2] = { 0, 0 }; struct ifmultiaddr *ifma; - u_int32_t rxfilt; - int mcnt = 0; + uint32_t hashes[2] = { 0, 0 }; + uint32_t h, rxfilt; RL_LOCK_ASSERT(sc); ifp = sc->rl_ifp; + rxfilt = RL_RXCFG_CONFIG | RL_RXCFG_RX_INDIV | RL_RXCFG_RX_BROAD; - rxfilt = CSR_READ_4(sc, RL_RXCFG); - rxfilt &= ~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_MULTI); - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { + if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) { if (ifp->if_flags & IFF_PROMISC) rxfilt |= RL_RXCFG_RX_ALLPHYS; /* @@ -635,17 +645,12 @@ * promiscuous mode. */ rxfilt |= RL_RXCFG_RX_MULTI; - CSR_WRITE_4(sc, RL_RXCFG, rxfilt); CSR_WRITE_4(sc, RL_MAR0, 0xFFFFFFFF); CSR_WRITE_4(sc, RL_MAR4, 0xFFFFFFFF); + CSR_WRITE_4(sc, RL_RXCFG, rxfilt); return; } - /* first, zot all the existing hash bits */ - CSR_WRITE_4(sc, RL_MAR0, 0); - CSR_WRITE_4(sc, RL_MAR4, 0); - - /* now program new ones */ IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) @@ -656,31 +661,28 @@ hashes[0] |= (1 << h); else hashes[1] |= (1 << (h - 32)); - mcnt++; } IF_ADDR_UNLOCK(ifp); - if (mcnt) + if (hashes[0] != 0 || hashes[1] != 0) { + /* + * For some unfathomable reason, RealTek decided to + * reverse the order of the multicast hash registers + * in the PCI Express parts. This means we have to + * write the hash pattern in reverse order for those + * devices. + */ + if ((sc->rl_flags & RL_FLAG_INVMAR) != 0) { + h = bswap32(hashes[0]); + hashes[0] = bswap32(hashes[1]); + hashes[1] = h; + } rxfilt |= RL_RXCFG_RX_MULTI; - else - rxfilt &= ~RL_RXCFG_RX_MULTI; + } + CSR_WRITE_4(sc, RL_MAR0, hashes[0]); + CSR_WRITE_4(sc, RL_MAR4, hashes[1]); CSR_WRITE_4(sc, RL_RXCFG, rxfilt); - - /* - * For some unfathomable reason, RealTek decided to reverse - * the order of the multicast hash registers in the PCI Express - * parts. This means we have to write the hash pattern in reverse - * order for those devices. - */ - - if ((sc->rl_flags & RL_FLAG_INVMAR) != 0) { - CSR_WRITE_4(sc, RL_MAR0, bswap32(hashes[1])); - CSR_WRITE_4(sc, RL_MAR4, bswap32(hashes[0])); - } else { - CSR_WRITE_4(sc, RL_MAR0, hashes[0]); - CSR_WRITE_4(sc, RL_MAR4, hashes[1]); - } } static void @@ -700,11 +702,13 @@ if (i == RL_TIMEOUT) device_printf(sc->rl_dev, "reset never completed!\n"); - if ((sc->rl_flags & RL_FLAG_PHY8169) != 0) - CSR_WRITE_1(sc, 0x82, 1); - if ((sc->rl_flags & RL_FLAG_PHY8110S) != 0) { - CSR_WRITE_1(sc, 0x82, 1); + switch (sc->rl_flags & (RL_FLAG_PHY8110S | RL_FLAG_PHY8169)) { + case RL_FLAG_PHY8110S: re_gmii_writereg(sc->rl_dev, 1, 0x0B, 0); + /* FALLTHROUGH */ + case RL_FLAG_PHY8169: + CSR_WRITE_1(sc, 0x82, 1); + break; } } @@ -1113,9 +1117,9 @@ struct ifnet *ifp; struct rl_hwrev *hw_rev; int hwrev; - u_int16_t devid, re_did = 0; int error = 0, rid, i; int msic, reg; + uint16_t re_did = 0; uint8_t cfg; sc = device_get_softc(dev); @@ -1130,26 +1134,14 @@ */ pci_enable_busmaster(dev); - devid = pci_get_device(dev); - /* Prefer memory space register mapping over IO space. */ - sc->rl_res_id = PCIR_BAR(1); - sc->rl_res_type = SYS_RES_MEMORY; - /* RTL8168/8101E seems to use different BARs. */ - if (devid == RT_DEVICEID_8168 || devid == RT_DEVICEID_8101E) - sc->rl_res_id = PCIR_BAR(2); - sc->rl_res = bus_alloc_resource_any(dev, sc->rl_res_type, - &sc->rl_res_id, RF_ACTIVE); + rid = RL_RID; + sc->rl_res = bus_alloc_resource_any(dev, RL_RES, &rid, + RF_ACTIVE); if (sc->rl_res == NULL) { - sc->rl_res_id = PCIR_BAR(0); - sc->rl_res_type = SYS_RES_IOPORT; - sc->rl_res = bus_alloc_resource_any(dev, sc->rl_res_type, - &sc->rl_res_id, RF_ACTIVE); - if (sc->rl_res == NULL) { - device_printf(dev, "couldn't map ports/memory\n"); - error = ENXIO; - goto fail; - } + device_printf(dev, "couldn't map ports/memory\n"); + error = ENXIO; + goto fail; } sc->rl_btag = rman_get_bustag(sc->rl_res); @@ -1291,8 +1283,10 @@ case RL_HWREV_8169S: sc->rl_flags |= RL_FLAG_PHY8169; break; - case RL_HWREV_8169_8110SB: case RL_HWREV_8169_8110SC: + sc->rl_flags |= 0x10000; + /* FALLTHROUGH */ + case RL_HWREV_8169_8110SB: case RL_HWREV_8169_8110SBL: sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHY8169; break; @@ -1565,8 +1559,7 @@ pci_release_msi(dev); } if (sc->rl_res) - bus_release_resource(dev, sc->rl_res_type, sc->rl_res_id, - sc->rl_res); + bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res); /* Unload and free the RX DMA ring memory and map */ @@ -2498,7 +2491,7 @@ { struct ifnet *ifp = sc->rl_ifp; struct mii_data *mii; - u_int32_t rxcfg = 0; + uint32_t reg; uint16_t cfg; union { uint32_t align_dummy; @@ -2534,6 +2527,23 @@ } else cfg |= RL_CPLUSCMD_RXENB | RL_CPLUSCMD_TXENB; CSR_WRITE_2(sc, RL_CPLUS_CMD, cfg); + if ((sc->rl_flags & 0x10000) != 0) { + reg = 0x000FFF00; + switch (CSR_READ_4(sc, RL_TXCFG) & 0xFC800000) { + case 0x18000000: /* 8169/8110SCd */ + reg |= 0x000000FF; + /* FALLTHROUGH */ + case 0x98000000: /* 8169/8110SCe */ + if ((CSR_READ_1(sc, RL_CFG2) & RL_CFG2_PCI66MHZ) == 0) + reg |= 0x00900000; + CSR_WRITE_4(sc, 0x7C, reg); + break; + default: + break; + } + /* Disable interrupt mitigation. */ + CSR_WRITE_2(sc, 0xE2, 0); + } /* * Disable TSO if interface MTU size is greater than MSS * allowed in controller. @@ -2583,7 +2593,7 @@ CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB); /* - * Set the initial TX and RX configuration. + * Set the initial TX configuration. */ if (sc->rl_testmode) { if (sc->rl_type == RL_8169) @@ -2597,31 +2607,10 @@ CSR_WRITE_1(sc, RL_EARLY_TX_THRESH, 16); - CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG); - - /* Set the individual bit to receive frames for this host only. */ - rxcfg = CSR_READ_4(sc, RL_RXCFG); - rxcfg |= RL_RXCFG_RX_INDIV; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - rxcfg |= RL_RXCFG_RX_ALLPHYS; - else - rxcfg &= ~RL_RXCFG_RX_ALLPHYS; - CSR_WRITE_4(sc, RL_RXCFG, rxcfg); - /* - * Set capture broadcast bit to capture broadcast frames. + * Set the initial RX configuration and + * program the multicast filter, if necessary. */ - if (ifp->if_flags & IFF_BROADCAST) - rxcfg |= RL_RXCFG_RX_BROAD; - else - rxcfg &= ~RL_RXCFG_RX_BROAD; - CSR_WRITE_4(sc, RL_RXCFG, rxcfg); - - /* - * Program the multicast filter, if necessary. - */ re_setmulti(sc); #ifdef DEVICE_POLLING