Module Name:    src
Committed By:   martin
Date:           Mon Oct  8 17:09:31 UTC 2018

Modified Files:
        src/sys/dev/ic: dwc_gmac.c dwc_gmac_reg.h dwc_gmac_var.h

Log Message:
Bring back support for enhanced descriptor format in newer core versions.
Fix a few endian bugs and check the main core version before trying to
read the hardware feature mask. Only read the hardware feature register
if core version reported is >= 3.5 (all my older hardware reports 0).
With some hints and patches from jared, and ok from aymeric


To generate a diff of this commit:
cvs rdiff -u -r1.54 -r1.55 src/sys/dev/ic/dwc_gmac.c
cvs rdiff -u -r1.18 -r1.19 src/sys/dev/ic/dwc_gmac_reg.h
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/ic/dwc_gmac_var.h

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/ic/dwc_gmac.c
diff -u src/sys/dev/ic/dwc_gmac.c:1.54 src/sys/dev/ic/dwc_gmac.c:1.55
--- src/sys/dev/ic/dwc_gmac.c:1.54	Fri Sep 28 21:51:42 2018
+++ src/sys/dev/ic/dwc_gmac.c	Mon Oct  8 17:09:31 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac.c,v 1.54 2018/09/28 21:51:42 aymeric Exp $ */
+/* $NetBSD: dwc_gmac.c,v 1.55 2018/10/08 17:09:31 martin Exp $ */
 
 /*-
  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.54 2018/09/28 21:51:42 aymeric Exp $");
+__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.55 2018/10/08 17:09:31 martin Exp $");
 
 /* #define	DWC_GMAC_DEBUG	1 */
 
@@ -100,6 +100,53 @@ static void dwc_gmac_rx_intr(struct dwc_
 static void dwc_gmac_setmulti(struct dwc_gmac_softc *sc);
 static int dwc_gmac_ifflags_cb(struct ethercom *);
 static uint32_t	bitrev32(uint32_t x);
+static void dwc_gmac_desc_set_owned_by_dev(struct dwc_gmac_dev_dmadesc *);
+static int  dwc_gmac_desc_is_owned_by_dev(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_set_len(struct dwc_gmac_dev_dmadesc *, int);
+static uint32_t dwc_gmac_desc_std_get_len(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_tx_init_flags(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_rx_init_flags(struct dwc_gmac_dev_dmadesc *);
+static int  dwc_gmac_desc_std_rx_has_error(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_set_len(struct dwc_gmac_dev_dmadesc *, int);
+static uint32_t dwc_gmac_desc_enh_get_len(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_tx_init_flags(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_rx_init_flags(struct dwc_gmac_dev_dmadesc *);
+static int  dwc_gmac_desc_enh_rx_has_error(struct dwc_gmac_dev_dmadesc *);
+
+static const struct dwc_gmac_desc_methods desc_methods_standard = {
+	.tx_init_flags = dwc_gmac_desc_std_tx_init_flags,
+	.tx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
+	.tx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
+	.tx_set_len = dwc_gmac_desc_std_set_len,
+	.tx_set_first_frag = dwc_gmac_desc_std_tx_set_first_frag,
+	.tx_set_last_frag = dwc_gmac_desc_std_tx_set_last_frag,
+	.rx_init_flags = dwc_gmac_desc_std_rx_init_flags,
+	.rx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
+	.rx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
+	.rx_set_len = dwc_gmac_desc_std_set_len,
+	.rx_get_len = dwc_gmac_desc_std_get_len,
+	.rx_has_error = dwc_gmac_desc_std_rx_has_error
+};
+
+static const struct dwc_gmac_desc_methods desc_methods_enhanced = {
+	.tx_init_flags = dwc_gmac_desc_enh_tx_init_flags,
+	.tx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
+	.tx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
+	.tx_set_len = dwc_gmac_desc_enh_set_len,
+	.tx_set_first_frag = dwc_gmac_desc_enh_tx_set_first_frag,
+	.tx_set_last_frag = dwc_gmac_desc_enh_tx_set_last_frag,
+	.rx_init_flags = dwc_gmac_desc_enh_rx_init_flags,
+	.rx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
+	.rx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
+	.rx_set_len = dwc_gmac_desc_enh_set_len,
+	.rx_get_len = dwc_gmac_desc_enh_get_len,
+	.rx_has_error = dwc_gmac_desc_enh_rx_has_error
+};
+
 
 #define	TX_DESC_OFFSET(N)	((AWGE_RX_RING_COUNT+(N)) \
 				    *sizeof(struct dwc_gmac_dev_dmadesc))
@@ -122,7 +169,7 @@ static uint32_t	bitrev32(uint32_t x);
 
 #define	AWIN_DEF_MAC_INTRMASK	\
 	(AWIN_GMAC_MAC_INT_TSI | AWIN_GMAC_MAC_INT_ANEG |	\
-	AWIN_GMAC_MAC_INT_LINKCHG | AWIN_GMAC_MAC_INT_RGSMII)
+	AWIN_GMAC_MAC_INT_LINKCHG)
 
 #ifdef DWC_GMAC_DEBUG
 static void dwc_gmac_dump_dma(struct dwc_gmac_softc *sc);
@@ -141,7 +188,7 @@ int
 dwc_gmac_attach(struct dwc_gmac_softc *sc, uint32_t mii_clk)
 {
 	uint8_t enaddr[ETHER_ADDR_LEN];
-	uint32_t maclo, machi;
+	uint32_t maclo, machi, ver, hwft;
 	struct mii_data * const mii = &sc->sc_mii;
 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
 	prop_dictionary_t dict;
@@ -185,6 +232,9 @@ dwc_gmac_attach(struct dwc_gmac_softc *s
 		enaddr[5] = (machi >> 8) & 0x0ff;
 	}
 
+	ver = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_VERSION);
+	aprint_normal_dev(sc->sc_dev, "Core version: %08x\n", ver);
+
 	/*
 	 * Init chip and do initial setup
 	 */
@@ -194,6 +244,21 @@ dwc_gmac_attach(struct dwc_gmac_softc *s
 	aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n",
 	    ether_sprintf(enaddr));
 
+	hwft = 0;
+	if (ver >= 0x35) {
+		hwft = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+		    AWIN_GMAC_DMA_HWFEATURES);
+		aprint_normal_dev(sc->sc_dev,
+		    "HW feature mask: %x\n", hwft);
+	}
+	if (hwft & GMAC_DMA_FEAT_ENHANCED_DESC) {
+		aprint_normal_dev(sc->sc_dev,
+		    "Using enhanced descriptor format\n");
+		sc->sc_descm = &desc_methods_enhanced;
+	} else {
+		sc->sc_descm = &desc_methods_standard;
+	}
+
 	/*
 	 * Allocate Tx and Rx rings
 	 */
@@ -444,10 +509,9 @@ dwc_gmac_alloc_rx_ring(struct dwc_gmac_s
 		next = RX_NEXT(i);
 		desc->ddesc_next = htole32(ring->r_physaddr
 		    + next * sizeof(*desc));
-		desc->ddesc_cntl = htole32(
-		    __SHIFTIN(AWGE_MAX_PACKET,DDESC_CNTL_SIZE1MASK) |
-		    DDESC_CNTL_RXCHAIN);
-		desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
+		sc->sc_descm->rx_init_flags(desc);
+		sc->sc_descm->rx_set_len(desc, AWGE_MAX_PACKET);
+		sc->sc_descm->rx_set_owned_by_dev(desc);
 	}
 
 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
@@ -473,10 +537,9 @@ dwc_gmac_reset_rx_ring(struct dwc_gmac_s
 	mutex_enter(&ring->r_mtx);
 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
 		desc = &sc->sc_rxq.r_desc[i];
-		desc->ddesc_cntl = htole32(
-		    __SHIFTIN(AWGE_MAX_PACKET,DDESC_CNTL_SIZE1MASK) |
-		    DDESC_CNTL_RXCHAIN);
-		desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
+		sc->sc_descm->rx_init_flags(desc);
+		sc->sc_descm->rx_set_len(desc, AWGE_MAX_PACKET);
+		sc->sc_descm->rx_set_owned_by_dev(desc);
 	}
 
 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
@@ -891,11 +954,11 @@ dwc_gmac_start_locked(struct ifnet *ifp)
 		dwc_gmac_txdesc_sync(sc, start, sc->sc_txq.t_cur,
 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
 
-		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
-		    AWIN_GMAC_DMA_TXPOLL, ~0U);
 #ifdef DWC_GMAC_DEBUG
 		dwc_dump_status(sc);
 #endif
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+		    AWIN_GMAC_DMA_TXPOLL, ~0U);
 	}
 }
 
@@ -942,7 +1005,6 @@ dwc_gmac_queue(struct dwc_gmac_softc *sc
 	struct dwc_gmac_dev_dmadesc *desc = NULL;
 	struct dwc_gmac_tx_data *data = NULL;
 	bus_dmamap_t map;
-	uint32_t flags, len, status;
 	int error, i, first;
 
 #ifdef DWC_GMAC_DEBUG
@@ -966,38 +1028,37 @@ dwc_gmac_queue(struct dwc_gmac_softc *sc
 		return ENOBUFS;
 	}
 
-	flags = DDESC_CNTL_TXFIRST|DDESC_CNTL_TXCHAIN;
-	status = 0;
 	for (i = 0; i < map->dm_nsegs; i++) {
 		data = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
 		desc = &sc->sc_txq.t_desc[sc->sc_txq.t_cur];
 
 		desc->ddesc_data = htole32(map->dm_segs[i].ds_addr);
-		len = __SHIFTIN(map->dm_segs[i].ds_len, DDESC_CNTL_SIZE1MASK);
 
 #ifdef DWC_GMAC_DEBUG
 		aprint_normal_dev(sc->sc_dev, "enqueing desc #%d data %08lx "
-		    "len %lu (flags: %08x, len: %08x)\n", sc->sc_txq.t_cur,
+		    "len %lu\n", sc->sc_txq.t_cur,
 		    (unsigned long)map->dm_segs[i].ds_addr,
-		    (unsigned long)map->dm_segs[i].ds_len,
-		    flags, len);
+		    (unsigned long)map->dm_segs[i].ds_len);
 #endif
 
-		desc->ddesc_cntl = htole32(len|flags);
-		flags &= ~DDESC_CNTL_TXFIRST;
+		sc->sc_descm->tx_init_flags(desc);
+		sc->sc_descm->tx_set_len(desc, map->dm_segs[i].ds_len);
+
+		if (i == 0)
+			sc->sc_descm->tx_set_first_frag(desc);
 
 		/*
 		 * Defer passing ownership of the first descriptor
 		 * until we are done.
 		 */
-		desc->ddesc_status = htole32(status);
-		status |= DDESC_STATUS_OWNEDBYDEV;
+		if (i != 0)
+			sc->sc_descm->tx_set_owned_by_dev(desc);
 
 		sc->sc_txq.t_queued++;
 		sc->sc_txq.t_cur = TX_NEXT(sc->sc_txq.t_cur);
 	}
 
-	desc->ddesc_cntl |= htole32(DDESC_CNTL_TXLAST|DDESC_CNTL_TXINT);
+	sc->sc_descm->tx_set_last_frag(desc);
 
 	data->td_m = m0;
 	data->td_active = map;
@@ -1006,8 +1067,10 @@ dwc_gmac_queue(struct dwc_gmac_softc *sc
 	    BUS_DMASYNC_PREWRITE);
 
 	/* Pass first to device */
-	sc->sc_txq.t_desc[first].ddesc_status =
-	    htole32(DDESC_STATUS_OWNEDBYDEV);
+	sc->sc_descm->tx_set_owned_by_dev(&sc->sc_txq.t_desc[first]);
+
+	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+	    BUS_DMASYNC_PREWRITE);
 
 	return 0;
 }
@@ -1087,7 +1150,6 @@ dwc_gmac_tx_intr(struct dwc_gmac_softc *
 	struct ifnet *ifp = &sc->sc_ec.ec_if;
 	struct dwc_gmac_tx_data *data;
 	struct dwc_gmac_dev_dmadesc *desc;
-	uint32_t status;
 	int i, nsegs;
 
 	mutex_enter(&sc->sc_txq.t_mtx);
@@ -1108,8 +1170,7 @@ dwc_gmac_tx_intr(struct dwc_gmac_softc *
 		    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
 
 		desc = &sc->sc_txq.t_desc[i];
-		status = le32toh(desc->ddesc_status);
-		if (status & DDESC_STATUS_OWNEDBYDEV)
+		if (sc->sc_descm->tx_is_owned_by_dev(desc))
 			break;
 
 		data = &sc->sc_txq.t_data[i];
@@ -1149,7 +1210,6 @@ dwc_gmac_rx_intr(struct dwc_gmac_softc *
 	struct dwc_gmac_dev_dmadesc *desc;
 	struct dwc_gmac_rx_data *data;
 	bus_addr_t physaddr;
-	uint32_t status;
 	struct mbuf *m, *mnew;
 	int i, len, error;
 
@@ -1161,21 +1221,20 @@ dwc_gmac_rx_intr(struct dwc_gmac_softc *
 		desc = &sc->sc_rxq.r_desc[i];
 		data = &sc->sc_rxq.r_data[i];
 
-		status = le32toh(desc->ddesc_status);
-		if (status & DDESC_STATUS_OWNEDBYDEV)
+		if (sc->sc_descm->rx_is_owned_by_dev(desc))
 			break;
 
-		if (status & (DDESC_STATUS_RXERROR|DDESC_STATUS_RXTRUNCATED)) {
+		if (sc->sc_descm->rx_has_error(desc)) {
 #ifdef DWC_GMAC_DEBUG
 			aprint_normal_dev(sc->sc_dev,
 			    "RX error: descriptor status %08x, skipping\n",
-			    status);
+			    le32toh(desc->ddesc_status0));
 #endif
 			ifp->if_ierrors++;
 			goto skip;
 		}
 
-		len = __SHIFTOUT(status, DDESC_STATUS_FRMLENMSK);
+		len = sc->sc_descm->rx_get_len(desc);
 
 #ifdef DWC_GMAC_DEBUG
 		aprint_normal_dev(sc->sc_dev,
@@ -1241,10 +1300,11 @@ dwc_gmac_rx_intr(struct dwc_gmac_softc *
 skip:
 		bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
 		    data->rd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
-		desc->ddesc_cntl = htole32(
-		    __SHIFTIN(AWGE_MAX_PACKET,DDESC_CNTL_SIZE1MASK) |
-		    DDESC_CNTL_RXCHAIN);
-		desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
+
+		sc->sc_descm->rx_init_flags(desc);
+		sc->sc_descm->rx_set_len(desc, AWGE_MAX_PACKET);
+		sc->sc_descm->rx_set_owned_by_dev(desc);
+
 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
 		    RX_DESC_OFFSET(i), sizeof(*desc),
 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
@@ -1398,6 +1458,131 @@ dwc_gmac_intr(struct dwc_gmac_softc *sc)
 	return rv;
 }
 
+static void
+dwc_gmac_desc_set_owned_by_dev(struct dwc_gmac_dev_dmadesc *desc)
+{
+
+	desc->ddesc_status0 |= htole32(DDESC_STATUS_OWNEDBYDEV);
+}
+
+static int
+dwc_gmac_desc_is_owned_by_dev(struct dwc_gmac_dev_dmadesc *desc)
+{
+
+	return !!(le32toh(desc->ddesc_status0) & DDESC_STATUS_OWNEDBYDEV);
+}
+
+static void
+dwc_gmac_desc_std_set_len(struct dwc_gmac_dev_dmadesc *desc, int len)
+{
+	uint32_t cntl = le32toh(desc->ddesc_cntl1);
+
+	desc->ddesc_cntl1 = htole32((cntl & ~DDESC_CNTL_SIZE1MASK) |
+		__SHIFTIN(len, DDESC_CNTL_SIZE1MASK));
+}
+
+static uint32_t
+dwc_gmac_desc_std_get_len(struct dwc_gmac_dev_dmadesc *desc)
+{
+
+	return __SHIFTOUT(le32toh(desc->ddesc_status0), DDESC_STATUS_FRMLENMSK);
+}
+
+static void
+dwc_gmac_desc_std_tx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
+{
+
+	desc->ddesc_status0 = 0;
+	desc->ddesc_cntl1 = htole32(DDESC_CNTL_TXCHAIN);
+}
+
+static void
+dwc_gmac_desc_std_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *desc)
+{
+	uint32_t cntl = le32toh(desc->ddesc_cntl1);
+
+	desc->ddesc_cntl1 = htole32(cntl | DDESC_CNTL_TXFIRST);
+}
+
+static void
+dwc_gmac_desc_std_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *desc)
+{
+	uint32_t cntl = le32toh(desc->ddesc_cntl1);
+
+	desc->ddesc_cntl1 = htole32(cntl |
+		DDESC_CNTL_TXLAST | DDESC_CNTL_TXINT);
+}
+
+static void
+dwc_gmac_desc_std_rx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
+{
+
+	desc->ddesc_status0 = 0;
+	desc->ddesc_cntl1 = htole32(DDESC_CNTL_TXCHAIN);
+}
+
+static int
+dwc_gmac_desc_std_rx_has_error(struct dwc_gmac_dev_dmadesc *desc) {
+	return !!(le32toh(desc->ddesc_status0) &
+		(DDESC_STATUS_RXERROR | DDESC_STATUS_RXTRUNCATED));
+}
+
+static void
+dwc_gmac_desc_enh_set_len(struct dwc_gmac_dev_dmadesc *desc, int len)
+{
+	uint32_t tdes1 = le32toh(desc->ddesc_cntl1);
+
+	desc->ddesc_cntl1 = htole32((tdes1 & ~DDESC_DES1_SIZE1MASK) |
+		__SHIFTIN(len, DDESC_DES1_SIZE1MASK));
+}
+
+static uint32_t
+dwc_gmac_desc_enh_get_len(struct dwc_gmac_dev_dmadesc *desc)
+{
+
+	return __SHIFTOUT(le32toh(desc->ddesc_status0), DDESC_RDES0_FL);
+}
+
+static void
+dwc_gmac_desc_enh_tx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
+{
+
+	desc->ddesc_status0 = htole32(DDESC_TDES0_TCH);
+	desc->ddesc_cntl1 = 0;
+}
+
+static void
+dwc_gmac_desc_enh_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *desc)
+{
+	uint32_t tdes0 = le32toh(desc->ddesc_status0);
+
+	desc->ddesc_status0 = htole32(tdes0 | DDESC_TDES0_FS);
+}
+
+static void
+dwc_gmac_desc_enh_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *desc)
+{
+	uint32_t tdes0 = le32toh(desc->ddesc_status0);
+
+	desc->ddesc_status0 = htole32(tdes0 | DDESC_TDES0_LS | DDESC_TDES0_IC);
+}
+
+static void
+dwc_gmac_desc_enh_rx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
+{
+
+	desc->ddesc_status0 = 0;
+	desc->ddesc_cntl1 = htole32(DDESC_RDES1_RCH);
+}
+
+static int
+dwc_gmac_desc_enh_rx_has_error(struct dwc_gmac_dev_dmadesc *desc)
+{
+
+	return !!(le32toh(desc->ddesc_status0) &
+		(DDESC_RDES0_ES | DDESC_RDES0_LE));
+}
+
 #ifdef DWC_GMAC_DEBUG
 static void
 dwc_gmac_dump_dma(struct dwc_gmac_softc *sc)
@@ -1442,7 +1627,7 @@ dwc_gmac_dump_tx_desc(struct dwc_gmac_so
 		    "data: %08x next: %08x\n",
 		    i, sc->sc_txq.t_physaddr +
 			i*sizeof(struct dwc_gmac_dev_dmadesc),
-		    le32toh(desc->ddesc_status), le32toh(desc->ddesc_cntl),
+		    le32toh(desc->ddesc_status0), le32toh(desc->ddesc_cntl1),
 		    le32toh(desc->ddesc_data), le32toh(desc->ddesc_next));
 	}
 }
@@ -1461,7 +1646,7 @@ dwc_gmac_dump_rx_desc(struct dwc_gmac_so
 		    "data: %08x next: %08x\n",
 		    i, sc->sc_rxq.r_physaddr +
 			i*sizeof(struct dwc_gmac_dev_dmadesc),
-		    le32toh(desc->ddesc_status), le32toh(desc->ddesc_cntl),
+		    le32toh(desc->ddesc_status0), le32toh(desc->ddesc_cntl1),
 		    le32toh(desc->ddesc_data), le32toh(desc->ddesc_next));
 	}
 }

Index: src/sys/dev/ic/dwc_gmac_reg.h
diff -u src/sys/dev/ic/dwc_gmac_reg.h:1.18 src/sys/dev/ic/dwc_gmac_reg.h:1.19
--- src/sys/dev/ic/dwc_gmac_reg.h:1.18	Fri Sep 28 21:51:42 2018
+++ src/sys/dev/ic/dwc_gmac_reg.h	Mon Oct  8 17:09:31 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac_reg.h,v 1.18 2018/09/28 21:51:42 aymeric Exp $ */
+/* $NetBSD: dwc_gmac_reg.h,v 1.19 2018/10/08 17:09:31 martin Exp $ */
 
 /*-
  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -164,8 +164,10 @@
 
 #define	GMAC_DMA_INT_MASK	__BITS(0,16)	  /* all possible intr bits */
 
+#define GMAC_DMA_FEAT_ENHANCED_DESC	__BIT(24)
+
 struct dwc_gmac_dev_dmadesc {
-	uint32_t ddesc_status;
+	uint32_t ddesc_status0;		/* Status / TDES0 */
 /* both: */
 #define	DDESC_STATUS_OWNEDBYDEV		__BIT(31)
 
@@ -189,7 +191,7 @@ struct dwc_gmac_dev_dmadesc {
 #define	DDESC_STATUS_RXDRIBBLING	__BIT(2)
 #define	DDESC_STATUS_RXCRC		__BIT(1)
 
-	uint32_t ddesc_cntl;
+	uint32_t ddesc_cntl1;		/* Control / TDES1 */
 
 /* for TX descriptors */
 #define	DDESC_CNTL_TXINT		__BIT(31)
@@ -221,3 +223,25 @@ struct dwc_gmac_dev_dmadesc {
 	uint32_t ddesc_data;	/* pointer to buffer data */
 	uint32_t ddesc_next;	/* link to next descriptor */
 };
+
+/* Common to enhanced descriptors */
+
+#define DDESC_DES0_OWN			__BIT(31)
+
+#define DDESC_DES1_SIZE2MASK		__BITS(28,16)
+#define DDESC_DES1_SIZE1MASK		__BITS(12,0)
+
+/* For enhanced TX descriptors */
+
+#define DDESC_TDES0_IC			__BIT(30)
+#define DDESC_TDES0_LS			__BIT(29)
+#define DDESC_TDES0_FS			__BIT(28)
+#define DDESC_TDES0_TCH			__BIT(20)
+
+/* For enhanced RX descriptors */
+
+#define DDESC_RDES0_FL			__BITS(29,16)
+#define DDESC_RDES0_ES			__BIT(15)
+#define DDESC_RDES0_LE			__BIT(12)
+
+#define DDESC_RDES1_RCH			__BIT(14)

Index: src/sys/dev/ic/dwc_gmac_var.h
diff -u src/sys/dev/ic/dwc_gmac_var.h:1.11 src/sys/dev/ic/dwc_gmac_var.h:1.12
--- src/sys/dev/ic/dwc_gmac_var.h:1.11	Fri Sep 28 21:51:42 2018
+++ src/sys/dev/ic/dwc_gmac_var.h	Mon Oct  8 17:09:31 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac_var.h,v 1.11 2018/09/28 21:51:42 aymeric Exp $ */
+/* $NetBSD: dwc_gmac_var.h,v 1.12 2018/10/08 17:09:31 martin Exp $ */
 
 /*-
  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -46,7 +46,23 @@
 
 #define		AWGE_MAX_PACKET		0x7ff
 
+struct dwc_gmac_dev_dmadesc;
 
+struct dwc_gmac_desc_methods {
+	void (*tx_init_flags)(struct dwc_gmac_dev_dmadesc *);
+	void (*tx_set_owned_by_dev)(struct dwc_gmac_dev_dmadesc *);
+	int  (*tx_is_owned_by_dev)(struct dwc_gmac_dev_dmadesc *);
+	void (*tx_set_len)(struct dwc_gmac_dev_dmadesc *, int);
+	void (*tx_set_first_frag)(struct dwc_gmac_dev_dmadesc *);
+	void (*tx_set_last_frag)(struct dwc_gmac_dev_dmadesc *);
+
+	void (*rx_init_flags)(struct dwc_gmac_dev_dmadesc *);
+	void (*rx_set_owned_by_dev)(struct dwc_gmac_dev_dmadesc *);
+	int  (*rx_is_owned_by_dev)(struct dwc_gmac_dev_dmadesc *);
+	void (*rx_set_len)(struct dwc_gmac_dev_dmadesc *, int);
+	uint32_t  (*rx_get_len)(struct dwc_gmac_dev_dmadesc *);
+	int  (*rx_has_error)(struct dwc_gmac_dev_dmadesc *);
+};
 
 struct dwc_gmac_rx_data {
 	bus_dmamap_t	rd_map;
@@ -89,6 +105,7 @@ struct dwc_gmac_softc {
 	bus_dma_segment_t sc_dma_ring_seg;	/* and TX ring */
 	struct dwc_gmac_rx_ring sc_rxq;
 	struct dwc_gmac_tx_ring sc_txq;
+	const struct dwc_gmac_desc_methods *sc_descm;
 	short sc_if_flags;			/* shadow of ether flags */
 	uint16_t sc_mii_clk;
 	bool sc_stopping;

Reply via email to