Module Name: src Committed By: thorpej Date: Fri Mar 13 00:41:24 UTC 2020
Modified Files: src/sys/dev/pci: if_ste.c Log Message: - Add the D-Link products, identified by subsystem ID. - On some variations, the internal PHY is ghosted at #0 and #1. Work around this by ignoring PHY #0 accesses unless we don't find one, and then look for one there as a fall-back if we don't detect anything else. - Fix access width when setting the TxDMAUrgentThresh register. - Support MBUFTRACE. To generate a diff of this commit: cvs rdiff -u -r1.60 -r1.61 src/sys/dev/pci/if_ste.c 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/pci/if_ste.c diff -u src/sys/dev/pci/if_ste.c:1.60 src/sys/dev/pci/if_ste.c:1.61 --- src/sys/dev/pci/if_ste.c:1.60 Fri Feb 7 00:04:28 2020 +++ src/sys/dev/pci/if_ste.c Fri Mar 13 00:41:24 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ste.c,v 1.60 2020/02/07 00:04:28 thorpej Exp $ */ +/* $NetBSD: if_ste.c,v 1.61 2020/03/13 00:41:24 thorpej Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ste.c,v 1.60 2020/02/07 00:04:28 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ste.c,v 1.61 2020/03/13 00:41:24 thorpej Exp $"); #include <sys/param.h> @@ -156,6 +156,8 @@ struct ste_softc { uint16_t sc_IntEnable; /* prototype IntEnable register */ uint16_t sc_MacCtrl0; /* prototype MacCtrl0 register */ uint8_t sc_ReceiveMode; /* prototype ReceiveMode register */ + + bool sc_enable_phy0; /* access to phy #0 allowed */ }; #define STE_CDTXADDR(sc, x) ((sc)->sc_cddma + STE_CDTXOFF((x))) @@ -245,37 +247,83 @@ static const struct mii_bitbang_ops ste_ /* * Devices supported by this driver. */ -static const struct ste_product { +struct ste_product { pci_vendor_id_t ste_vendor; pci_product_id_t ste_product; const char *ste_name; -} ste_products[] = { + const struct ste_product *ste_subs; +}; + +static const struct ste_product ste_dlink_products[] = { + { PCI_VENDOR_DLINK, 0x1002, + "D-Link DFE-550TX 10/100 Ethernet", + NULL }, + + { PCI_VENDOR_DLINK, 0x1003, + "D-Link DFE-550FX Ethernet", + NULL }, + + { PCI_VENDOR_DLINK, 0x1012, + "D-Link DFE-580TX 4-port 10/100 Ethernet", + NULL }, + + { PCI_VENDOR_DLINK, 0x1040, + "D-Link DFE-530TXS 10/100 Ethernet", + NULL }, + + { 0, 0, + NULL, + NULL }, +}; + +static const struct ste_product ste_products[] = { { PCI_VENDOR_SUNDANCETI, PCI_PRODUCT_SUNDANCETI_IP100A, - "IC Plus Corp. IP00A 10/100 Fast Ethernet Adapter" }, + "IC Plus Corp. IP00A 10/100 Fast Ethernet Adapter", + NULL }, { PCI_VENDOR_SUNDANCETI, PCI_PRODUCT_SUNDANCETI_ST201, - "Sundance ST-201 10/100 Ethernet" }, + "Sundance ST-201 10/100 Ethernet", + NULL }, { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DL1002, - "D-Link DL-1002 10/100 Ethernet" }, + "D-Link DL-1002 10/100 Ethernet", + ste_dlink_products }, { 0, 0, + NULL, NULL }, }; static const struct ste_product * -ste_lookup(const struct pci_attach_args *pa) +ste_lookup_table(pcireg_t pci_id, const struct ste_product * const products) { const struct ste_product *sp; - for (sp = ste_products; sp->ste_name != NULL; sp++) { - if (PCI_VENDOR(pa->pa_id) == sp->ste_vendor && - PCI_PRODUCT(pa->pa_id) == sp->ste_product) + for (sp = products; sp->ste_name != NULL; sp++) { + if (PCI_VENDOR(pci_id) == sp->ste_vendor && + PCI_PRODUCT(pci_id) == sp->ste_product) return (sp); } return (NULL); } +static const struct ste_product * +ste_lookup(const struct pci_attach_args *pa) +{ + const struct ste_product *sp; + + sp = ste_lookup_table(pa->pa_id, ste_products); + if (sp && sp->ste_subs) { + const pcireg_t subsys = + pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); + const struct ste_product *ssp = + ste_lookup_table(subsys, sp->ste_subs); + if (ssp) + sp = ssp; + } + return (sp); +} + static int ste_match(device_t parent, cfdata_t cf, void *aux) { @@ -471,6 +519,18 @@ ste_attach(device_t parent, device_t sel mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&mii->mii_phys) == NULL) { + /* + * It seems that some variants of this chip "ghost" the + * single PHY at #0 and #1. We will try probing the MII + * first while ignoring #0 access. If we find the PHY, + * great! If not, un-ignore #0 and try probing *just* + * #0 to see if we can find it. + */ + sc->sc_enable_phy0 = true; + mii_attach(sc->sc_dev, mii, 0xffffffff, 0, + MII_OFFSET_ANY, 0); + } + if (LIST_FIRST(&mii->mii_phys) == NULL) { ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); } else @@ -643,6 +703,7 @@ ste_start(struct ifnet *ifp) device_xname(sc->sc_dev)); break; } + MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner); if (m0->m_pkthdr.len > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { @@ -1029,6 +1090,7 @@ ste_rxintr(struct ste_softc *sc) MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) goto dropit; + MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); m->m_data += 2; memcpy(mtod(m, void *), mtod(ds->ds_mbuf, void *), len); @@ -1171,7 +1233,7 @@ ste_setthresh(struct ste_softc *sc) bus_space_write_2(sc->sc_st, sc->sc_sh, STE_TxStartThresh, sc->sc_txthresh); /* Urgent threshold: set to sc_txthresh / 2 */ - bus_space_write_2(sc->sc_st, sc->sc_sh, STE_TxDMAUrgentThresh, + bus_space_write_1(sc->sc_st, sc->sc_sh, STE_TxDMAUrgentThresh, sc->sc_txthresh >> 6); /* Burst threshold: use default value (256 bytes) */ } @@ -1480,6 +1542,7 @@ ste_add_rxbuf(struct ste_softc *sc, int if (m == NULL) return (ENOBUFS); + MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); @@ -1611,6 +1674,10 @@ ste_set_filter(struct ste_softc *sc) static int ste_mii_readreg(device_t self, int phy, int reg, uint16_t *val) { + struct ste_softc *sc = device_private(self); + + if (phy == 0 && !sc->sc_enable_phy0) + return EIO; return mii_bitbang_readreg(self, &ste_mii_bitbang_ops, phy, reg, val); } @@ -1623,6 +1690,10 @@ ste_mii_readreg(device_t self, int phy, static int ste_mii_writereg(device_t self, int phy, int reg, uint16_t val) { + struct ste_softc *sc = device_private(self); + + if (phy == 0 && !sc->sc_enable_phy0) + return EIO; return mii_bitbang_writereg(self, &ste_mii_bitbang_ops, phy, reg, val); }