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/0172a9ab2fbd
branches: trunk
changeset: 1008008:0172a9ab2fbd
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 96dc2d5bdbc1 -r 0172a9ab2fbd 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