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;