Module Name:    src
Committed By:   aymeric
Date:           Mon Sep 17 20:25:49 UTC 2018

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

Log Message:
Add support for the enhanced descriptors feature.

This makes "recent" dwc gmac controllers, as found e.g. on the Cyclone V, work.
The change was also tested working on an Allwinner A20 which doesn't have the
feature.

No negative reaction on port-arm.


To generate a diff of this commit:
cvs rdiff -u -r1.52 -r1.53 src/sys/dev/ic/dwc_gmac.c
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/ic/dwc_gmac_reg.h
cvs rdiff -u -r1.9 -r1.10 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.52 src/sys/dev/ic/dwc_gmac.c:1.53
--- src/sys/dev/ic/dwc_gmac.c:1.52	Wed Jul 18 23:10:27 2018
+++ src/sys/dev/ic/dwc_gmac.c	Mon Sep 17 20:25:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac.c,v 1.52 2018/07/18 23:10:27 sevan Exp $ */
+/* $NetBSD: dwc_gmac.c,v 1.53 2018/09/17 20:25:49 aymeric 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.52 2018/07/18 23:10:27 sevan Exp $");
+__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.53 2018/09/17 20:25:49 aymeric 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 int  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 int  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);
@@ -194,6 +241,12 @@ dwc_gmac_attach(struct dwc_gmac_softc *s
 	aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n",
 	    ether_sprintf(enaddr));
 
+	if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_HWFEATURES) &
+	    GMAC_DMA_FEAT_ENHANCED_DESC)
+		sc->sc_descm = &desc_methods_enhanced;
+	else
+		sc->sc_descm = &desc_methods_standard;
+
 	/*
 	 * Allocate Tx and Rx rings
 	 */
@@ -444,10 +497,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 +525,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 +942,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 +993,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 +1016,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 +1055,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 +1138,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 +1158,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 +1198,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 +1209,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 +1288,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 +1446,107 @@ 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 |= DDESC_STATUS_OWNEDBYDEV;
+}
+
+static int
+dwc_gmac_desc_is_owned_by_dev(struct dwc_gmac_dev_dmadesc *desc) {
+	return !!(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 int
+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 = 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 = 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 int
+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 = 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 = 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 +1591,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 +1610,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.16 src/sys/dev/ic/dwc_gmac_reg.h:1.17
--- src/sys/dev/ic/dwc_gmac_reg.h:1.16	Sat Jun 16 00:15:00 2018
+++ src/sys/dev/ic/dwc_gmac_reg.h	Mon Sep 17 20:25:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac_reg.h,v 1.16 2018/06/16 00:15:00 jmcneill Exp $ */
+/* $NetBSD: dwc_gmac_reg.h,v 1.17 2018/09/17 20:25:49 aymeric 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.9 src/sys/dev/ic/dwc_gmac_var.h:1.10
--- src/sys/dev/ic/dwc_gmac_var.h:1.9	Sat Jun 30 16:27:48 2018
+++ src/sys/dev/ic/dwc_gmac_var.h	Mon Sep 17 20:25:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac_var.h,v 1.9 2018/06/30 16:27:48 jmcneill Exp $ */
+/* $NetBSD: dwc_gmac_var.h,v 1.10 2018/09/17 20:25:49 aymeric 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);
+	int  (*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