Module Name:    src
Committed By:   matt
Date:           Mon Oct 28 17:49:33 UTC 2013

Modified Files:
        src/sys/dev/usb: xhci.c xhcivar.h

Log Message:
Add support for scratchpad buffers (required for some XHCI devices).
Fix an endian issue.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/usb/xhci.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/usb/xhcivar.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/usb/xhci.c
diff -u src/sys/dev/usb/xhci.c:1.4 src/sys/dev/usb/xhci.c:1.5
--- src/sys/dev/usb/xhci.c:1.4	Fri Oct 18 08:39:22 2013
+++ src/sys/dev/usb/xhci.c	Mon Oct 28 17:49:33 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhci.c,v 1.4 2013/10/18 08:39:22 apb Exp $	*/
+/*	$NetBSD: xhci.c,v 1.5 2013/10/28 17:49:33 matt Exp $	*/
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.4 2013/10/18 08:39:22 apb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.5 2013/10/28 17:49:33 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -703,14 +703,6 @@ xhci_init(struct xhci_softc *sc)
 	if (i >= 100)
 		return USBD_IOERROR;
 
-	device_printf(sc->sc_dev, "maxspbuf %d\n", XHCI_HCS2_MAXSPBUF(hcs2));
-	if (XHCI_HCS2_MAXSPBUF(hcs2) != 0) {
-		/* XXX */
-		aprint_error_dev(sc->sc_dev,
-		    "TODO implement scratchpad allocation\n");
-		return USBD_INVAL;
-	}
-
 	pagesize = xhci_op_read_4(sc, XHCI_PAGESIZE);
 	device_printf(sc->sc_dev, "PAGESIZE 0x%08x\n", pagesize);
 	pagesize = ffs(pagesize);
@@ -721,13 +713,40 @@ xhci_init(struct xhci_softc *sc)
 	device_printf(sc->sc_dev, "sc_maxslots 0x%08x\n",
 	    (uint32_t)sc->sc_maxslots);
 
+	usbd_status err;
+
+	sc->sc_maxspbuf = XHCI_HCS2_MAXSPBUF(hcs2);
+	device_printf(sc->sc_dev, "sc_maxspbuf %d\n", sc->sc_maxspbuf);
+	if (sc->sc_maxspbuf != 0) {
+		err = usb_allocmem(&sc->sc_bus,
+		    sizeof(uint64_t) * sc->sc_maxspbuf, sizeof(uint64_t),
+		    &sc->sc_spbufarray_dma);
+		if (err)
+			return err;
+		
+		sc->sc_spbuf_dma = kmem_zalloc(sizeof(*sc->sc_spbuf_dma) * sc->sc_maxspbuf, KM_SLEEP);
+		uint64_t *spbufarray = KERNADDR(&sc->sc_spbufarray_dma, 0);
+		for (i = 0; i < sc->sc_maxspbuf; i++) {
+			usb_dma_t * const dma = &sc->sc_spbuf_dma[i];
+			/* allocate contexts */
+			err = usb_allocmem(&sc->sc_bus, sc->sc_pgsz,
+			    sc->sc_pgsz, dma);
+			if (err)
+				return err;
+			spbufarray[i] = htole64(DMAADDR(dma, 0));
+			usb_syncmem(dma, 0, sc->sc_pgsz,
+			    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+		}
+
+		usb_syncmem(&sc->sc_spbufarray_dma, 0, 
+		    sizeof(uint64_t) * sc->sc_maxspbuf, BUS_DMASYNC_PREWRITE);
+	}
+
 	config = xhci_op_read_4(sc, XHCI_CONFIG);
 	config &= ~0xFF;
 	config |= sc->sc_maxslots & 0xFF;
 	xhci_op_write_4(sc, XHCI_CONFIG, config);
 
-	usbd_status err;
-
 	err = xhci_ring_init(sc, &sc->sc_cr, XHCI_COMMAND_RING_TRBS,
 	    XHCI_COMMAND_RING_SEGMENTS_ALIGN);
 	if (err) {
@@ -767,6 +786,13 @@ xhci_init(struct xhci_softc *sc)
 		align = XHCI_DEVICE_CONTEXT_BASE_ADDRESS_ARRAY_ALIGN;
 		err = usb_allocmem(&sc->sc_bus, size, align, dma);
 		memset(KERNADDR(dma, 0), 0, size);
+		if (sc->sc_maxspbuf != 0) {
+			/*
+			 * DCBA entry 0 hold the scratchbuf array pointer.
+			 */
+			*(uint64_t *)KERNADDR(dma, 0) =
+			    htole64(DMAADDR(&sc->sc_spbufarray_dma, 0));
+		}
 		usb_syncmem(dma, 0, size, BUS_DMASYNC_PREWRITE);
 		device_printf(sc->sc_dev, "dcbaa: %s %016jx %p %zx\n",
 		    usbd_errstr(err),
@@ -1792,7 +1818,7 @@ xhci_set_dcba(struct xhci_softc * const 
 	device_printf(sc->sc_dev, "dcbaa %p dc %016"PRIx64" slot %d\n",
 	    &dcbaa[si], dcba, si);
 
-	dcbaa[si] = dcba;
+	dcbaa[si] = htole64(dcba);
 	usb_syncmem(&sc->sc_dcbaa_dma, si * sizeof(uint64_t), sizeof(uint64_t),
 	    BUS_DMASYNC_PREWRITE);
 }

Index: src/sys/dev/usb/xhcivar.h
diff -u src/sys/dev/usb/xhcivar.h:1.1 src/sys/dev/usb/xhcivar.h:1.2
--- src/sys/dev/usb/xhcivar.h:1.1	Sat Sep 14 00:40:31 2013
+++ src/sys/dev/usb/xhcivar.h	Mon Oct 28 17:49:33 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhcivar.h,v 1.1 2013/09/14 00:40:31 jakllsch Exp $	*/
+/*	$NetBSD: xhcivar.h,v 1.2 2013/10/28 17:49:33 matt Exp $	*/
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -85,6 +85,7 @@ struct xhci_softc {
 	int sc_maxslots;
 	int sc_maxintrs;
 	int sc_maxports;
+	int sc_maxspbuf;
 
 	/* XXX suboptimal */
 	int sc_hs_port_start;
@@ -99,6 +100,8 @@ struct xhci_softc {
 
 	usb_dma_t sc_eventst_dma;
 	usb_dma_t sc_dcbaa_dma;
+	usb_dma_t sc_spbufarray_dma;
+	usb_dma_t *sc_spbuf_dma;
 
 	//struct usb_dma_reserve sc_dma_reserve;
 

Reply via email to