Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Support 64-bit DMA addressing on the DP83820, us...



details:   https://anonhg.NetBSD.org/src/rev/d3d231e31d68
branches:  trunk
changeset: 745618:d3d231e31d68
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sun Mar 08 02:44:12 2020 +0000

description:
Support 64-bit DMA addressing on the DP83820, used only when a 64-bit
DMA tag is available.

diffstat:

 sys/dev/pci/if_sip.c    |  243 +++++++++++++++++++++++++++++++----------------
 sys/dev/pci/if_sipreg.h |   29 ++++-
 2 files changed, 182 insertions(+), 90 deletions(-)

diffs (truncated from 520 to 300 lines):

diff -r 47bfb38841ff -r d3d231e31d68 sys/dev/pci/if_sip.c
--- a/sys/dev/pci/if_sip.c      Sun Mar 08 02:42:00 2020 +0000
+++ b/sys/dev/pci/if_sip.c      Sun Mar 08 02:44:12 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_sip.c,v 1.178 2020/02/07 00:04:28 thorpej Exp $     */
+/*     $NetBSD: if_sip.c,v 1.179 2020/03/08 02:44:12 thorpej Exp $     */
 
 /*-
  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@@ -73,7 +73,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.178 2020/02/07 00:04:28 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.179 2020/03/08 02:44:12 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -208,9 +208,14 @@
        struct ethercom sc_ethercom;    /* ethernet common data */
 
        const struct sip_product *sc_model; /* which model are we? */
-       int sc_gigabit;                 /* 1: 83820, 0: other */
+       bool sc_gigabit;                /* 1: 83820, 0: other */
+       bool sc_dma64;                  /* using 64-bit DMA addresses */
        int sc_rev;                     /* chip revision */
 
+       unsigned int sc_bufptr_idx;
+       unsigned int sc_cmdsts_idx;
+       unsigned int sc_extsts_idx;     /* DP83820 only */
+
        void *sc_ih;                    /* interrupt cookie */
 
        struct mii_data sc_mii;         /* MII/media information */
@@ -471,6 +476,24 @@
 #define        SIP_CDRXADDR(sc, x)     ((sc)->sc_cddma + SIP_CDRXOFF((x)))
 
 static inline void
+sip_set_rxdp(struct sip_softc *sc, bus_addr_t addr)
+{
+       if (sc->sc_gigabit)
+               bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RXDP_HI,
+                   BUS_ADDR_HI32(addr));
+       bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RXDP, BUS_ADDR_LO32(addr));
+}
+
+static inline void
+sip_set_txdp(struct sip_softc *sc, bus_addr_t addr)
+{
+       if (sc->sc_gigabit)
+               bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXDP_HI,
+                   BUS_ADDR_HI32(addr));
+       bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXDP, BUS_ADDR_LO32(addr));
+}
+
+static inline void
 sip_cdtxsync(struct sip_softc *sc, const int x0, const int n0, const int ops)
 {
        int x, n;
@@ -499,26 +522,51 @@
            SIP_CDRXOFF(x), sizeof(struct sip_desc), ops);
 }
 
-#if 0
-#ifdef DP83820
-       uint32_t        sipd_bufptr;    /* pointer to DMA segment */
-       uint32_t        sipd_cmdsts;    /* command/status word */
-#else
-       uint32_t        sipd_cmdsts;    /* command/status word */
-       uint32_t        sipd_bufptr;    /* pointer to DMA segment */
-#endif /* DP83820 */
-#endif /* 0 */
-
-static inline volatile uint32_t *
-sipd_cmdsts(struct sip_softc *sc, struct sip_desc *sipd)
+static void
+sip_init_txring(struct sip_softc *sc)
 {
-       return &sipd->sipd_cbs[(sc->sc_gigabit) ? 1 : 0];
+       struct sip_desc *sipd;
+       bus_addr_t next_desc;
+       int i;
+
+       memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
+       for (i = 0; i < sc->sc_ntxdesc; i++) {
+               sipd = &sc->sc_txdescs[i];
+               next_desc = SIP_CDTXADDR(sc, sip_nexttx(sc, i));
+               if (sc->sc_dma64) {
+                       sipd->sipd_words[GSIP64_DESC_LINK_LO] =
+                           htole32(BUS_ADDR_LO32(next_desc));
+                       sipd->sipd_words[GSIP64_DESC_LINK_HI] =
+                           htole32(BUS_ADDR_HI32(next_desc));
+               } else {
+                       /* SIP_DESC_LINK == GSIP_DESC_LINK */
+                       sipd->sipd_words[SIP_DESC_LINK] = htole32(next_desc);
+               }
+       }
+       sip_cdtxsync(sc, 0, sc->sc_ntxdesc,
+           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+       sc->sc_txfree = sc->sc_ntxdesc;
+       sc->sc_txnext = 0;
+       sc->sc_txwin = 0;
 }
 
-static inline volatile uint32_t *
-sipd_bufptr(struct sip_softc *sc, struct sip_desc *sipd)
+static inline void
+sip_init_txdesc(struct sip_softc *sc, int x, bus_addr_t bufptr, uint32_t cmdsts)
 {
-       return &sipd->sipd_cbs[(sc->sc_gigabit) ? 0 : 1];
+       struct sip_desc *sipd = &sc->sc_txdescs[x];
+
+       if (sc->sc_dma64) {
+               sipd->sipd_words[GSIP64_DESC_BUFPTR_LO] =
+                   htole32(BUS_ADDR_LO32(bufptr));
+               sipd->sipd_words[GSIP64_DESC_BUFPTR_HI] =
+                   htole32(BUS_ADDR_HI32(bufptr));
+       } else {
+               sipd->sipd_words[sc->sc_bufptr_idx] = htole32(bufptr);
+       }
+       sipd->sipd_words[sc->sc_extsts_idx] = 0;
+       membar_producer();
+       sipd->sipd_words[sc->sc_cmdsts_idx] = htole32(cmdsts);
+       /* sip_cdtxsync() will be done later. */
 }
 
 static inline void
@@ -526,12 +574,27 @@
 {
        struct sip_rxsoft *rxs = &sc->sc_rxsoft[x];
        struct sip_desc *sipd = &sc->sc_rxdescs[x];
-
-       sipd->sipd_link = htole32(SIP_CDRXADDR(sc, sip_nextrx(sc, x)));
-       *sipd_bufptr(sc, sipd) = htole32(rxs->rxs_dmamap->dm_segs[0].ds_addr);
-       *sipd_cmdsts(sc, sipd) = htole32(CMDSTS_INTR |
-           (sc->sc_parm->p_rxbuf_len & sc->sc_bits.b_cmdsts_size_mask));
-       sipd->sipd_extsts = 0;
+       const bus_addr_t next_desc = SIP_CDRXADDR(sc, sip_nextrx(sc, x));
+
+       if (sc->sc_dma64) {
+               sipd->sipd_words[GSIP64_DESC_LINK_LO] =
+                   htole32(BUS_ADDR_LO32(next_desc));
+               sipd->sipd_words[GSIP64_DESC_LINK_HI] =
+                   htole32(BUS_ADDR_HI32(next_desc));
+               sipd->sipd_words[GSIP64_DESC_BUFPTR_LO] =
+                   htole32(BUS_ADDR_LO32(rxs->rxs_dmamap->dm_segs[0].ds_addr));
+               sipd->sipd_words[GSIP64_DESC_BUFPTR_HI] =
+                   htole32(BUS_ADDR_HI32(rxs->rxs_dmamap->dm_segs[0].ds_addr));
+       } else {
+               sipd->sipd_words[SIP_DESC_LINK] = htole32(next_desc);
+               sipd->sipd_words[sc->sc_bufptr_idx] =
+                   htole32(rxs->rxs_dmamap->dm_segs[0].ds_addr);
+       }
+       sipd->sipd_words[sc->sc_extsts_idx] = 0;
+       membar_producer();
+       sipd->sipd_words[sc->sc_cmdsts_idx] =
+           htole32(CMDSTS_INTR | (sc->sc_parm->p_rxbuf_len &
+                                  sc->sc_bits.b_cmdsts_size_mask));
        sip_cdrxsync(sc, x, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 }
 
@@ -670,25 +733,26 @@
        pci_product_id_t        sip_product;
        const char              *sip_name;
        const struct sip_variant *sip_variant;
-       int                     sip_gigabit;
+       bool                    sip_gigabit;
 } sipcom_products[] = {
        { PCI_VENDOR_NS,        PCI_PRODUCT_NS_DP83820,
          "NatSemi DP83820 Gigabit Ethernet",
-         &sipcom_variant_dp83820, 1 },
+         &sipcom_variant_dp83820, true },
+
        { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_900,
          "SiS 900 10/100 Ethernet",
-         &sipcom_variant_sis900, 0 },
+         &sipcom_variant_sis900, false },
        { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_7016,
          "SiS 7016 10/100 Ethernet",
-         &sipcom_variant_sis900, 0 },
+         &sipcom_variant_sis900, false },
 
        { PCI_VENDOR_NS,        PCI_PRODUCT_NS_DP83815,
          "NatSemi DP83815 10/100 Ethernet",
-         &sipcom_variant_dp83815, 0 },
+         &sipcom_variant_dp83815, false },
 
        { 0,                    0,
          NULL,
-         NULL, 0 },
+         NULL, false },
 };
 
 static const struct sip_product *
@@ -812,24 +876,30 @@
                }
                printf("\n");
        }
+       
+       /*
+        * The T64ADDR bit is loaded by the chip from the EEPROM and
+        * is read-only.
+        */
+       if (reg & CFG_T64ADDR)
+               sc->sc_cfg |= CFG_T64ADDR;
 
        /*
-        * XXX Need some PCI flags indicating support for
-        * XXX 64-bit addressing.
+        * We can use 64-bit DMA addressing regardless of what
+        * sort of slot we're in.
         */
-#if 0
-       if (reg & CFG_M64ADDR)
+       if (pci_dma64_available(pa)) {
+               sc->sc_dmat = pa->pa_dmat64;
                sc->sc_cfg |= CFG_M64ADDR;
-       if (reg & CFG_T64ADDR)
-               sc->sc_cfg |= CFG_T64ADDR;
-#endif
+               sc->sc_dma64 = true;
+       }
 
        if (reg & (CFG_TBI_EN | CFG_EXT_125)) {
                const char *sep = "";
                printf("%s: using ", device_xname(sc->sc_dev));
                if (reg & CFG_EXT_125) {
                        sc->sc_cfg |= CFG_EXT_125;
-                       printf("%s125MHz clock", sep);
+                       printf("%sexternal 125MHz clock", sep);
                        sep = ", ";
                }
                if (reg & CFG_TBI_EN) {
@@ -1004,15 +1074,32 @@
        }
        sc->sc_dev = self;
        sc->sc_gigabit = sip->sip_gigabit;
+       sc->sc_dma64 = false;
        pmf_self_suspensor_init(self, &sc->sc_suspensor, &sc->sc_qual);
        sc->sc_pc = pc;
 
        if (sc->sc_gigabit) {
+               if (sc->sc_dma64) {
+                       sc->sc_bufptr_idx = GSIP64_DESC_BUFPTR_LO;
+                       sc->sc_cmdsts_idx = GSIP64_DESC_CMDSTS;
+                       sc->sc_extsts_idx = GSIP64_DESC_EXTSTS;
+               } else {
+                       sc->sc_bufptr_idx = GSIP_DESC_BUFPTR;
+                       sc->sc_cmdsts_idx = GSIP_DESC_CMDSTS;
+                       sc->sc_extsts_idx = GSIP_DESC_EXTSTS;
+               }
                sc->sc_rxintr = gsip_rxintr;
                sc->sc_parm = &gsip_parm;
        } else {
                sc->sc_rxintr = sip_rxintr;
                sc->sc_parm = &sip_parm;
+               sc->sc_bufptr_idx = SIP_DESC_BUFPTR;
+               sc->sc_cmdsts_idx = SIP_DESC_CMDSTS;
+               /*
+                * EXTSTS doesn't really exist on non-GigE parts,
+                * but we initialize the index for simplicity later.
+                */
+               sc->sc_extsts_idx = GSIP_DESC_EXTSTS;
        }
        tx_dmamap_size = sc->sc_parm->p_tx_dmamap_size;
        ntxsegs_alloc = sc->sc_parm->p_ntxsegs_alloc;
@@ -1376,7 +1463,7 @@
 sipcom_set_extsts(struct sip_softc *sc, int lasttx, struct mbuf *m0,
     uint64_t capenable)
 {
-       uint32_t extsts;
+       uint32_t extsts = 0;
 #ifdef DEBUG
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 #endif
@@ -1397,7 +1484,7 @@
         * unconditional swap instead of htons() inside.
         */
        if (vlan_has_tag(m0)) {
-               sc->sc_txdescs[lasttx].sipd_extsts |=
+               sc->sc_txdescs[lasttx].sipd_words[sc->sc_extsts_idx] |=
                    htole32(EXTSTS_VPKT |
                                (bswap16(vlan_get_tag(m0)) &
                                 EXTSTS_VTCI));
@@ -1413,7 +1500,6 @@
         *
         * Byte-swap constants so the compiler can optimize.
         */
-       extsts = 0;
        if (m0->m_pkthdr.csum_flags & M_CSUM_IPv4) {
                KDASSERT(ifp->if_capenable & IFCAP_CSUM_IPv4_Tx);
                SIP_EVCNT_INCR(&sc->sc_ev_txipsum);
@@ -1428,7 +1514,7 @@
                SIP_EVCNT_INCR(&sc->sc_ev_txudpsum);
                extsts |= htole32(EXTSTS_UDPPKT);
        }
-       sc->sc_txdescs[sc->sc_txnext].sipd_extsts |= extsts;
+       sc->sc_txdescs[sc->sc_txnext].sipd_words[sc->sc_extsts_idx] |= extsts;
 }
 



Home | Main Index | Thread Index | Old Index