--- dev/re/if_re.c.orig 2008-04-15 09:46:15.000000000 +0900 +++ dev/re/if_re.c 2008-05-19 15:57:17.000000000 +0900 @@ -155,11 +155,6 @@ /* "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); @@ -170,38 +165,25 @@ * Various supported device vendors/types and their names. */ static struct rl_type re_devs[] = { - { DLINK_VENDORID, DLINK_DEVICEID_528T, RL_HWREV_8169S, - "D-Link DGE-528(T) Gigabit Ethernet Adapter" }, - { DLINK_VENDORID, DLINK_DEVICEID_528T, RL_HWREV_8169_8110SB, - "D-Link DGE-528(T) Rev.B1 Gigabit Ethernet Adapter" }, - { RT_VENDORID, RT_DEVICEID_8139, RL_HWREV_8139CPLUS, - "RealTek 8139C+ 10/100BaseTX" }, - { RT_VENDORID, RT_DEVICEID_8101E, RL_HWREV_8101E, - "RealTek 8101E PCIe 10/100baseTX" }, - { RT_VENDORID, RT_DEVICEID_8168, RL_HWREV_8168_SPIN1, - "RealTek 8168/8111B PCIe Gigabit Ethernet" }, - { RT_VENDORID, RT_DEVICEID_8168, RL_HWREV_8168_SPIN2, - "RealTek 8168/8111B PCIe Gigabit Ethernet" }, - { RT_VENDORID, RT_DEVICEID_8168, RL_HWREV_8168_SPIN3, - "RealTek 8168/8111B PCIe Gigabit Ethernet" }, - { RT_VENDORID, RT_DEVICEID_8169, RL_HWREV_8169, - "RealTek 8169 Gigabit Ethernet" }, - { RT_VENDORID, RT_DEVICEID_8169, RL_HWREV_8169S, - "RealTek 8169S Single-chip Gigabit Ethernet" }, - { RT_VENDORID, RT_DEVICEID_8169, RL_HWREV_8169_8110SB, - "RealTek 8169SB/8110SB Single-chip Gigabit Ethernet" }, - { RT_VENDORID, RT_DEVICEID_8169, RL_HWREV_8169_8110SC, - "RealTek 8169SC/8110SC Single-chip Gigabit Ethernet" }, - { RT_VENDORID, RT_DEVICEID_8169SC, RL_HWREV_8169_8110SC, - "RealTek 8169SC/8110SC Single-chip Gigabit Ethernet" }, - { RT_VENDORID, RT_DEVICEID_8169, RL_HWREV_8110S, - "RealTek 8110S Single-chip Gigabit Ethernet" }, - { COREGA_VENDORID, COREGA_DEVICEID_CGLAPCIGT, RL_HWREV_8169S, - "Corega CG-LAPCIGT (RTL8169S) Gigabit Ethernet" }, - { LINKSYS_VENDORID, LINKSYS_DEVICEID_EG1032, RL_HWREV_8169S, - "Linksys EG1032 (RTL8169S) Gigabit Ethernet" }, - { USR_VENDORID, USR_DEVICEID_997902, RL_HWREV_8169S, - "US Robotics 997902 (RTL8169S) Gigabit Ethernet" } + { DLINK_VENDORID, DLINK_DEVICEID_528T, 0, + "D-Link DGE-528(T) Gigabit Ethernet Adapter" }, + { RT_VENDORID, RT_DEVICEID_8139, 0, + "RealTek 8139C+ 10/100BaseTX" }, + { RT_VENDORID, RT_DEVICEID_8101E, 0, + "RealTek 8101E PCIe 10/100baseTX" }, + { RT_VENDORID, RT_DEVICEID_8168, 0, + "RealTek 8168/8168B/8168C/8168CP/8111B/8111C/8111CP PCIe " + "Gigabit Ethernet" }, + { RT_VENDORID, RT_DEVICEID_8169, 0, + "RealTek 8169/8169S/8169SB(L)/8110S/8110SB(L) Gigabit Ethernet" }, + { RT_VENDORID, RT_DEVICEID_8169SC, 0, + "RealTek 8169SC/8110SC Single-chip Gigabit Ethernet" }, + { COREGA_VENDORID, COREGA_DEVICEID_CGLAPCIGT, 0, + "Corega CG-LAPCIGT (RTL8169S) Gigabit Ethernet" }, + { LINKSYS_VENDORID, LINKSYS_DEVICEID_EG1032, 0, + "Linksys EG1032 (RTL8169S) Gigabit Ethernet" }, + { USR_VENDORID, USR_DEVICEID_997902, 0, + "US Robotics 997902 (RTL8169S) Gigabit Ethernet" } }; static struct rl_hwrev re_hwrevs[] = { @@ -219,12 +201,15 @@ { RL_HWREV_8110S, RL_8169, "8110S"}, { RL_HWREV_8169_8110SB, RL_8169, "8169SB"}, { RL_HWREV_8169_8110SC, RL_8169, "8169SC"}, + { RL_HWREV_8169_8110SBL, RL_8169, "8169SBL"}, { RL_HWREV_8100, RL_8139, "8100"}, { RL_HWREV_8101, RL_8139, "8101"}, { RL_HWREV_8100E, RL_8169, "8100E"}, { RL_HWREV_8101E, RL_8169, "8101E"}, { RL_HWREV_8168_SPIN2, RL_8169, "8168"}, { RL_HWREV_8168_SPIN3, RL_8169, "8168"}, + { RL_HWREV_8168C, RL_8169, "8168C/8111C"}, + { RL_HWREV_8168CP, RL_8169, "8168CP/8111CP"}, { 0, 0, NULL } }; @@ -270,6 +255,8 @@ static void re_eeprom_putbyte (struct rl_softc *, int); static void re_eeprom_getword (struct rl_softc *, int, u_int16_t *); static void re_read_eeprom (struct rl_softc *, caddr_t, int, int); +static int re_read_vpd_word (struct rl_softc *, uint32_t, uint32_t, + uint32_t *); static int re_gmii_readreg (device_t, int, int); static int re_gmii_writereg (device_t, int, int, int); @@ -286,14 +273,6 @@ 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), @@ -432,6 +411,30 @@ } static int +re_read_vpd_word(sc, vpdc, offset, word) + struct rl_softc *sc; + uint32_t vpdc, offset, *word; +{ + int i; + + pci_write_config(sc->rl_dev, vpdc + PCIR_VPD_ADDR, offset, 2); + for (i = RL_TIMEOUT; i > 0; i--) { + DELAY(10); + if ((pci_read_config(sc->rl_dev, vpdc + PCIR_VPD_ADDR, 2) & + 0x8000) == 0x8000) + break; + } + if (i == 0) { + device_printf(sc->rl_dev, "VPD read timeout!\n"); + *word = 0; + return (ETIMEDOUT); + } + + *word = pci_read_config(sc->rl_dev, vpdc + PCIR_VPD_DATA, 4); + return (0); +} + +static int re_gmii_readreg(dev, phy, reg) device_t dev; int phy, reg; @@ -632,7 +635,6 @@ struct ifmultiaddr *ifma; u_int32_t rxfilt; int mcnt = 0; - u_int32_t hwrev; RL_LOCK_ASSERT(sc); @@ -688,22 +690,12 @@ * parts. This means we have to write the hash pattern in reverse * order for those devices. */ - - hwrev = CSR_READ_4(sc, RL_TXCFG) & RL_TXCFG_HWREV; - - switch (hwrev) { - case RL_HWREV_8100E: - case RL_HWREV_8101E: - case RL_HWREV_8168_SPIN1: - case RL_HWREV_8168_SPIN2: - case RL_HWREV_8168_SPIN3: + 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])); - break; - default: + } else { CSR_WRITE_4(sc, RL_MAR0, hashes[0]); CSR_WRITE_4(sc, RL_MAR4, hashes[1]); - break; } } @@ -784,7 +776,7 @@ sc->rl_testmode = 1; re_reset(sc); re_init_locked(sc); - sc->rl_link = 1; + sc->rl_flags |= RL_FLAG_LINK; if (sc->rl_type == RL_8169) phyaddr = 1; else @@ -895,7 +887,7 @@ /* Turn interface off, release resources */ sc->rl_testmode = 0; - sc->rl_link = 0; + sc->rl_flags &= ~RL_FLAG_LINK; ifp->if_flags &= ~IFF_PROMISC; re_stop(sc); if (m0 != NULL) @@ -1143,7 +1135,7 @@ struct ifnet *ifp; struct rl_hwrev *hw_rev; int hwrev; - u_int16_t re_did = 0; + u_int16_t devid, re_did = 0; int error = 0, rid, i; int msic, reg; uint8_t cfg; @@ -1160,14 +1152,24 @@ */ pci_enable_busmaster(dev); - rid = RL_RID; - sc->rl_res = bus_alloc_resource_any(dev, RL_RES, &rid, - RF_ACTIVE); + devid = pci_get_device(dev); + sc->rl_res_id = PCIR_BAR(1); + sc->rl_res_type = SYS_RES_MEMORY; + 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); if (sc->rl_res == NULL) { - device_printf(dev, "couldn't map ports/memory\n"); - error = ENXIO; - goto fail; + 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; + } } sc->rl_btag = rman_get_bustag(sc->rl_res); @@ -1184,20 +1186,20 @@ if (msic == RL_MSI_MESSAGES) { device_printf(dev, "Using %d MSI messages\n", msic); - sc->rl_msi = 1; + sc->rl_flags |= RL_FLAG_MSI; /* Explicitly set MSI enable bit. */ CSR_WRITE_1(sc, RL_EECMD, RL_EE_MODE); cfg = CSR_READ_1(sc, RL_CFG2); cfg |= RL_CFG2_MSI; CSR_WRITE_1(sc, RL_CFG2, cfg); - CSR_WRITE_1(sc, RL_EECMD, 0); + CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF); } else pci_release_msi(dev); } } /* Allocate interrupt */ - if (sc->rl_msi == 0) { + if ((sc->rl_flags & RL_FLAG_MSI) == 0) { rid = 0; sc->rl_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); @@ -1220,6 +1222,17 @@ } } + if ((sc->rl_flags & RL_FLAG_MSI) == 0) { + CSR_WRITE_1(sc, RL_EECMD, RL_EE_MODE); + cfg = CSR_READ_1(sc, RL_CFG2); + if ((cfg & RL_CFG2_MSI) != 0) { + device_printf(dev, "turning off MSI enable bit.\n"); + cfg &= ~RL_CFG2_MSI; + CSR_WRITE_1(sc, RL_CFG2, cfg); + } + CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF); + } + /* Reset the adapter. */ RL_LOCK(sc); re_reset(sc); @@ -1227,6 +1240,8 @@ hw_rev = re_hwrevs; hwrev = CSR_READ_4(sc, RL_TXCFG) & RL_TXCFG_HWREV; + device_printf(dev, "Chip rev. 0x%08x\n", hwrev & 0x7c800000); + device_printf(dev, "MAC rev. 0x%08x\n", hwrev & 0x00700000); while (hw_rev->rl_desc != NULL) { if (hw_rev->rl_rev == hwrev) { sc->rl_type = hw_rev->rl_type; @@ -1235,23 +1250,89 @@ hw_rev++; } if (hw_rev->rl_desc == NULL) { - device_printf(dev, "Unknown H/W revision: %08x\n", hwrev); + device_printf(dev, "Unknown H/W revision: 0x%08x\n", hwrev); error = ENXIO; goto fail; } - sc->rl_eewidth = RL_9356_ADDR_LEN; - re_read_eeprom(sc, (caddr_t)&re_did, 0, 1); - if (re_did != 0x8129) - sc->rl_eewidth = RL_9346_ADDR_LEN; + switch (hw_rev->rl_rev) { + case RL_HWREV_8139CPLUS: + sc->rl_flags |= RL_FLAG_NOJUMBO; + break; + case RL_HWREV_8100E: + case RL_HWREV_8101E: + sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE; + break; + case RL_HWREV_8168_SPIN1: + case RL_HWREV_8168_SPIN2: + case RL_HWREV_8168_SPIN3: + sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | + RL_FLAG_MACSTAT; + break; + case RL_HWREV_8168C: + case RL_HWREV_8168CP: + sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | + RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT; + /* + * These controllers support jumbo frame but it seems + * that enabling it requires touching additional magic + * registers. Depending on MAC revisions some + * controllers need to disable checksum offload. So + * disable jumbo frame until I have better idea what + * it really requires to make it support. + * RTL8168C/CP : supports up to 6KB jumbo frame. + * RTL8111C/CP : supports up to 9KB jumbo frame. + */ + sc->rl_flags |= RL_FLAG_NOJUMBO; + break; + case RL_HWREV_8169_8110SB: + case RL_HWREV_8169_8110SC: + case RL_HWREV_8169_8110SBL: + sc->rl_flags |= RL_FLAG_PHYWAKE; + break; + default: + break; + } + + if ((sc->rl_flags & RL_FLAG_PAR) != 0) { + /* XXX Should have a way to get station address from EEPROM. */ + uint32_t vpdc, word; + int verr; + int offset; + + if (pci_find_extcap(sc->rl_dev, PCIY_VPD, &vpdc) == 0) { + printf("VPD offset 0\n"); + for (offset = 0; offset < 0x20; offset += 4) { + verr = re_read_vpd_word(sc, vpdc, offset, &word); + if (verr != 0) + break; + printf("0x%04x : 0x%08x\n", offset, word); + } + printf("VPD offset 0x100\n"); + for (offset = 0x100; offset < 0x120; offset += 4) { + verr = re_read_vpd_word(sc, vpdc, offset, &word); + if (verr != 0) + break; + printf("0x%04x : 0x%08x\n", offset, word); + } + } else + device_printf(sc->rl_dev, "VPD not found!\n"); + for (i = 0; i < ETHER_ADDR_LEN; i++) + eaddr[i] = CSR_READ_1(sc, RL_IDR0 + i); + } else { + sc->rl_eewidth = RL_9356_ADDR_LEN; + re_read_eeprom(sc, (caddr_t)&re_did, 0, 1); + if (re_did != 0x8129) + sc->rl_eewidth = RL_9346_ADDR_LEN; - /* - * Get station address from the EEPROM. - */ - re_read_eeprom(sc, (caddr_t)as, RL_EE_EADDR, 3); - for (i = 0; i < ETHER_ADDR_LEN / 2; i++) - as[i] = le16toh(as[i]); - bcopy(as, eaddr, sizeof(eaddr)); + /* + * Get station address from the EEPROM. + */ + re_read_eeprom(sc, (caddr_t)as, RL_EE_EADDR, 3); + for (i = 0; i < ETHER_ADDR_LEN / 2; i++) + as[i] = le16toh(as[i]); + bcopy(as, eaddr, sizeof(eaddr)); + } if (sc->rl_type == RL_8169) { /* Set RX length mask and number of descriptors. */ @@ -1266,11 +1347,6 @@ sc->rl_ldata.rl_tx_desc_cnt = RL_8139_TX_DESC_CNT; sc->rl_ldata.rl_rx_desc_cnt = RL_8139_RX_DESC_CNT; } - if (hw_rev->rl_desc == NULL) { - device_printf(dev, "Unsupported revision : 0x%08x\n", hwrev); - error = ENXIO; - goto fail; - } error = re_allocmem(dev, sc); if (error) @@ -1283,6 +1359,12 @@ goto fail; } + /* Take PHY out of power down mode. */ + if ((sc->rl_flags & RL_FLAG_PHYWAKE) != 0) { + re_gmii_writereg(dev, 1, 0x1f, 0); + re_gmii_writereg(dev, 1, 0x0e, 0); + } + /* Do MII setup */ if (mii_phy_probe(dev, &sc->rl_miibus, re_ifmedia_upd, re_ifmedia_sts)) { @@ -1291,29 +1373,6 @@ goto fail; } - /* Take PHY out of power down mode. */ - if (sc->rl_type == RL_8169) { - uint32_t rev; - - rev = CSR_READ_4(sc, RL_TXCFG); - /* HWVERID 0, 1 and 2 : bit26-30, bit23 */ - rev &= 0x7c800000; - if (rev != 0) { - /* RTL8169S single chip */ - switch (rev) { - case RL_HWREV_8169_8110SB: - case RL_HWREV_8169_8110SC: - case RL_HWREV_8168_SPIN2: - case RL_HWREV_8168_SPIN3: - re_gmii_writereg(dev, 1, 0x1f, 0); - re_gmii_writereg(dev, 1, 0x0e, 0); - break; - default: - break; - } - } - } - ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; @@ -1372,7 +1431,7 @@ #endif /* Hook interrupt last to avoid having to lock softc */ - if (sc->rl_msi == 0) + if ((sc->rl_flags & RL_FLAG_MSI) == 0) error = bus_setup_intr(dev, sc->rl_irq[0], INTR_TYPE_NET | INTR_MPSAFE, re_intr, NULL, sc, &sc->rl_intrhand[0]); @@ -1465,7 +1524,7 @@ } if (ifp != NULL) if_free(ifp); - if (sc->rl_msi == 0) { + if ((sc->rl_flags & RL_FLAG_MSI) == 0) { if (sc->rl_irq[0] != NULL) { bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_irq[0]); @@ -1482,7 +1541,8 @@ pci_release_msi(dev); } if (sc->rl_res) - bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res); + bus_release_resource(dev, sc->rl_res_type, sc->rl_res_id, + sc->rl_res); /* Unload and free the RX DMA ring memory and map */ @@ -1849,21 +1909,44 @@ /* Do RX checksumming if enabled */ if (ifp->if_capenable & IFCAP_RXCSUM) { - - /* Check IP header checksum */ - if (rxstat & RL_RDESC_STAT_PROTOID) - m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; - if (!(rxstat & RL_RDESC_STAT_IPSUMBAD)) - m->m_pkthdr.csum_flags |= CSUM_IP_VALID; - - /* Check TCP/UDP checksum */ - if ((RL_TCPPKT(rxstat) && - !(rxstat & RL_RDESC_STAT_TCPSUMBAD)) || - (RL_UDPPKT(rxstat) && - !(rxstat & RL_RDESC_STAT_UDPSUMBAD))) { - m->m_pkthdr.csum_flags |= - CSUM_DATA_VALID|CSUM_PSEUDO_HDR; - m->m_pkthdr.csum_data = 0xffff; + if ((sc->rl_flags & RL_FLAG_DESCV2) == 0) { + /* Check IP header checksum */ + if (rxstat & RL_RDESC_STAT_PROTOID) + m->m_pkthdr.csum_flags |= + CSUM_IP_CHECKED; + if (!(rxstat & RL_RDESC_STAT_IPSUMBAD)) + m->m_pkthdr.csum_flags |= + CSUM_IP_VALID; + + /* Check TCP/UDP checksum */ + if ((RL_TCPPKT(rxstat) && + !(rxstat & RL_RDESC_STAT_TCPSUMBAD)) || + (RL_UDPPKT(rxstat) && + !(rxstat & RL_RDESC_STAT_UDPSUMBAD))) { + m->m_pkthdr.csum_flags |= + CSUM_DATA_VALID|CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + } else { + /* + * RTL8168C/RTL816CP/RTL8111C/RTL8111CP + */ + if ((rxstat & RL_RDESC_STAT_PROTOID) && + (rxvlan & RL_RDESC_IPV4)) + m->m_pkthdr.csum_flags |= + CSUM_IP_CHECKED; + if (!(rxstat & RL_RDESC_STAT_IPSUMBAD) && + (rxvlan & RL_RDESC_IPV4)) + m->m_pkthdr.csum_flags |= + CSUM_IP_VALID; + if (((rxstat & RL_RDESC_STAT_TCP) && + !(rxstat & RL_RDESC_STAT_TCPSUMBAD)) || + ((rxstat & RL_RDESC_STAT_UDP) && + !(rxstat & RL_RDESC_STAT_UDPSUMBAD))) { + m->m_pkthdr.csum_flags |= + CSUM_DATA_VALID|CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } } } maxpkt--; @@ -1987,13 +2070,13 @@ mii = device_get_softc(sc->rl_miibus); mii_tick(mii); - if (sc->rl_link) { + if ((sc->rl_flags & RL_FLAG_LINK) != 0) { if (!(mii->mii_media_status & IFM_ACTIVE)) - sc->rl_link = 0; + sc->rl_flags &= ~RL_FLAG_LINK; } else { if (mii->mii_media_status & IFM_ACTIVE && IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->rl_link = 1; + sc->rl_flags |= RL_FLAG_LINK; if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask); @@ -2165,7 +2248,8 @@ * offload is enabled, we always manually pad short frames out * to the minimum ethernet frame size. */ - if ((*m_head)->m_pkthdr.len < RL_IP4CSUMTX_PADLEN && + if ((sc->rl_flags & RL_FLAG_DESCV2) == 0 && + (*m_head)->m_pkthdr.len < RL_IP4CSUMTX_PADLEN && ((*m_head)->m_pkthdr.csum_flags & CSUM_IP) != 0) { padlen = RL_MIN_FRAMELEN - (*m_head)->m_pkthdr.len; if (M_WRITABLE(*m_head) == 0) { @@ -2241,6 +2325,7 @@ * attempt. This is according to testing done with an 8169 * chip. This is a requirement. */ + vlanctl = 0; csum_flags = 0; if (((*m_head)->m_pkthdr.csum_flags & CSUM_TSO) != 0) csum_flags = RL_TDESC_CMD_LGSEND | @@ -2253,11 +2338,23 @@ * does't make effects. */ if (((*m_head)->m_pkthdr.csum_flags & RE_CSUM_FEATURES) != 0) { - csum_flags |= RL_TDESC_CMD_IPCSUM; - if (((*m_head)->m_pkthdr.csum_flags & CSUM_TCP) != 0) - csum_flags |= RL_TDESC_CMD_TCPCSUM; - if (((*m_head)->m_pkthdr.csum_flags & CSUM_UDP) != 0) - csum_flags |= RL_TDESC_CMD_UDPCSUM; + if ((sc->rl_flags & RL_FLAG_DESCV2) == 0) { + csum_flags |= RL_TDESC_CMD_IPCSUM; + if (((*m_head)->m_pkthdr.csum_flags & + CSUM_TCP) != 0) + csum_flags |= RL_TDESC_CMD_TCPCSUM; + if (((*m_head)->m_pkthdr.csum_flags & + CSUM_UDP) != 0) + csum_flags |= RL_TDESC_CMD_UDPCSUM; + } else { + vlanctl |= RL_TDESC_CMD_IPCSUMV2; + if (((*m_head)->m_pkthdr.csum_flags & + CSUM_TCP) != 0) + vlanctl |= RL_TDESC_CMD_TCPCSUMV2; + if (((*m_head)->m_pkthdr.csum_flags & + CSUM_UDP) != 0) + vlanctl |= RL_TDESC_CMD_UDPCSUMV2; + } } } @@ -2266,16 +2363,14 @@ * appear in all descriptors of a multi-descriptor * transmission attempt. */ - vlanctl = 0; if ((*m_head)->m_flags & M_VLANTAG) - vlanctl = - htole32(htons((*m_head)->m_pkthdr.ether_vtag) | - RL_TDESC_VLANCTL_TAG); + vlanctl |= htons((*m_head)->m_pkthdr.ether_vtag) | + RL_TDESC_VLANCTL_TAG; si = prod; for (i = 0; i < nsegs; i++, prod = RL_TX_DESC_NXT(sc, prod)) { desc = &sc->rl_ldata.rl_tx_list[prod]; - desc->rl_vlanctl = vlanctl; + desc->rl_vlanctl = htole32(vlanctl); desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(segs[i].ds_addr)); desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(segs[i].ds_addr)); cmdstat = segs[i].ds_len; @@ -2341,7 +2436,7 @@ RL_LOCK(sc); if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != - IFF_DRV_RUNNING || sc->rl_link == 0) { + IFF_DRV_RUNNING || (sc->rl_flags & RL_FLAG_LINK) == 0) { RL_UNLOCK(sc); return; } @@ -2451,8 +2546,13 @@ cfg |= RL_CPLUSCMD_RXCSUM_ENB; if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) cfg |= RL_CPLUSCMD_VLANSTRIP; - CSR_WRITE_2(sc, RL_CPLUS_CMD, - cfg | RL_CPLUSCMD_RXENB | RL_CPLUSCMD_TXENB); + if ((sc->rl_flags & RL_FLAG_MACSTAT) != 0) { + cfg |= RL_CPLUSCMD_MACSTAT_DIS; + /* XXX magic. */ + cfg |= 0x0001; + } else + cfg |= RL_CPLUSCMD_RXENB | RL_CPLUSCMD_TXENB; + CSR_WRITE_2(sc, RL_CPLUS_CMD, cfg); /* * Init our MAC address. Even though the chipset @@ -2594,7 +2694,7 @@ ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - sc->rl_link = 0; + sc->rl_flags &= ~RL_FLAG_LINK; sc->rl_watchdog_timer = 0; callout_reset(&sc->rl_stat_callout, hz, re_tick, sc); } @@ -2656,7 +2756,7 @@ error = EINVAL; break; } - if (sc->rl_type == RL_8139CPLUS && + if ((sc->rl_flags & RL_FLAG_NOJUMBO) != 0 && ifr->ifr_mtu > RL_MAX_FRAMELEN) { error = EINVAL; break; @@ -2671,7 +2771,7 @@ if ((ifp->if_flags & IFF_UP) != 0) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { if (((ifp->if_flags ^ sc->rl_if_flags) - & IFF_PROMISC) != 0) + & (IFF_PROMISC | IFF_ALLMULTI)) != 0) re_setmulti(sc); } else re_init_locked(sc); @@ -2952,7 +3052,7 @@ CSR_WRITE_1(sc, RL_CFG3, v); /* Config register write done. */ - CSR_WRITE_1(sc, RL_EECMD, 0); + CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF); v = CSR_READ_1(sc, RL_CFG5); v &= ~(RL_CFG5_WOL_BCAST | RL_CFG5_WOL_MCAST | RL_CFG5_WOL_UCAST); @@ -2999,7 +3099,7 @@ CSR_WRITE_1(sc, RL_CFG3, v); /* Config register write done. */ - CSR_WRITE_1(sc, RL_EECMD, 0); + CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF); v = CSR_READ_1(sc, RL_CFG5); v &= ~(RL_CFG5_WOL_BCAST | RL_CFG5_WOL_MCAST | RL_CFG5_WOL_UCAST); --- pci/if_rlreg.h.orig 2008-04-07 09:37:44.000000000 +0900 +++ pci/if_rlreg.h 2008-05-19 15:25:56.000000000 +0900 @@ -161,6 +161,8 @@ #define RL_HWREV_8101E 0x34000000 #define RL_HWREV_8168_SPIN2 0x38000000 #define RL_HWREV_8168_SPIN3 0x38400000 +#define RL_HWREV_8168C 0x3C000000 +#define RL_HWREV_8168CP 0x3C800000 #define RL_HWREV_8139 0x60000000 #define RL_HWREV_8139A 0x70000000 #define RL_HWREV_8139AG 0x70800000 @@ -171,6 +173,7 @@ #define RL_HWREV_8139CPLUS 0x74800000 #define RL_HWREV_8101 0x74c00000 #define RL_HWREV_8100 0x78800000 +#define RL_HWREV_8169_8110SBL 0x7CC00000 #define RL_TXDMA_16BYTES 0x00000000 #define RL_TXDMA_32BYTES 0x00000100 @@ -442,6 +445,15 @@ #define RL_CPLUSCMD_PCI_DAC 0x0010 /* PCI dual-address cycle only */ #define RL_CPLUSCMD_RXCSUM_ENB 0x0020 /* enable RX checksum offload */ #define RL_CPLUSCMD_VLANSTRIP 0x0040 /* enable VLAN tag stripping */ +#define RL_CPLUSCMD_MACSTAT_DIS 0x0080 /* 8168B/C/CP */ +#define RL_CPLUSCMD_ASF 0x0100 /* 8168C/CP */ +#define RL_CPLUSCMD_DBG_SEL 0x0200 /* 8168C/CP */ +#define RL_CPLUSCMD_FORCE_TXFC 0x0400 /* 8168C/CP */ +#define RL_CPLUSCMD_FORCE_RXFC 0x0800 /* 8168C/CP */ +#define RL_CPLUSCMD_FORCE_HDPX 0x1000 /* 8168C/CP */ +#define RL_CPLUSCMD_NORMAL_MODE 0x2000 /* 8168C/CP */ +#define RL_CPLUSCMD_DBG_ENB 0x4000 /* 8168C/CP */ +#define RL_CPLUSCMD_BIST_ENB 0x8000 /* 8168C/CP */ /* C+ early transmit threshold */ @@ -598,6 +610,10 @@ #define RL_TDESC_VLANCTL_TAG 0x00020000 /* Insert VLAN tag */ #define RL_TDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */ +/* RTL8169C/RTL8169CP/RTL8111C/RTL8111CP */ +#define RL_TDESC_CMD_UDPCSUMV2 0x80000000 +#define RL_TDESC_CMD_TCPCSUMV2 0x40000000 +#define RL_TDESC_CMD_IPCSUMV2 0x20000000 /* * Error bits are valid only on the last descriptor of a frame @@ -635,6 +651,8 @@ #define RL_RDESC_STAT_RUNT 0x00080000 /* runt packet received */ #define RL_RDESC_STAT_CRCERR 0x00040000 /* CRC error */ #define RL_RDESC_STAT_PROTOID 0x00030000 /* Protocol type */ +#define RL_RDESC_STAT_UDP 0x00020000 /* UDP, 8168C/CP, 8111C/CP */ +#define RL_RDESC_STAT_TCP 0x00010000 /* TCP, 8168C/CP, 8111C/CP */ #define RL_RDESC_STAT_IPSUMBAD 0x00008000 /* IP header checksum bad */ #define RL_RDESC_STAT_UDPSUMBAD 0x00004000 /* UDP checksum bad */ #define RL_RDESC_STAT_TCPSUMBAD 0x00002000 /* TCP checksum bad */ @@ -646,6 +664,9 @@ #define RL_RDESC_VLANCTL_TAG 0x00010000 /* VLAN tag available (rl_vlandata valid)*/ #define RL_RDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */ +/* RTL8169C/RTL8169CP/RTL8111C/RTL8111CP */ +#define RL_RDESC_IPV6 0x80000000 +#define RL_RDESC_IPV4 0x40000000 #define RL_PROTOID_NONIP 0x00000000 #define RL_PROTOID_TCPIP 0x00010000 @@ -775,6 +796,8 @@ bus_space_tag_t rl_btag; /* bus space tag */ device_t rl_dev; struct resource *rl_res; + int rl_res_id; + int rl_res_type; struct resource *rl_irq[RL_MSI_MESSAGES]; void *rl_intrhand[RL_MSI_MESSAGES]; device_t rl_miibus; @@ -805,8 +828,15 @@ struct task rl_inttask; int rl_txstart; - int rl_link; - int rl_msi; + int rl_flags; +#define RL_FLAG_MSI 0x0001 +#define RL_FLAG_INVMAR 0x0004 +#define RL_FLAG_PHYWAKE 0x0008 +#define RL_FLAG_PAR 0x0010 +#define RL_FLAG_DESCV2 0x0020 +#define RL_FLAG_MACSTAT 0x0040 +#define RL_FLAG_NOJUMBO 0x0080 +#define RL_FLAG_LINK 0x8000 }; #define RL_LOCK(_sc) mtx_lock(&(_sc)->rl_mtx)