summaryrefslogtreecommitdiff
path: root/sys/dev/usb/xhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/xhci.c')
-rw-r--r--sys/dev/usb/xhci.c275
1 files changed, 169 insertions, 106 deletions
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index d47f8031ea5..4928be70f30 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xhci.c,v 1.45 2014/12/08 13:32:34 mpi Exp $ */
+/* $OpenBSD: xhci.c,v 1.46 2014/12/15 17:10:44 mpi Exp $ */
/*
* Copyright (c) 2014 Martin Pieuchot
@@ -52,7 +52,7 @@ int xhcidebug = 3;
#define DEVNAME(sc) ((sc)->sc_bus.bdev.dv_xname)
#define TRBOFF(r, trb) ((char *)(trb) - (char *)((r).trbs))
-#define DEQPTR(r) (DMAADDR(&(r).dma, sizeof(struct xhci_trb) * (r).index))
+#define DEQPTR(r) ((r).dma.paddr + (sizeof(struct xhci_trb) * (r).index))
struct pool *xhcixfer;
@@ -67,7 +67,7 @@ struct xhci_pipe {
* XXX used to pass the xfer pointer back to the
* interrupt routine, better way?
*/
- struct usbd_xfer *pending_xfers[XHCI_MAX_TRANSFERS];
+ struct usbd_xfer *pending_xfers[XHCI_MAX_XFER];
int halted;
size_t free_trbs;
};
@@ -85,7 +85,8 @@ int xhci_scratchpad_alloc(struct xhci_softc *, int);
void xhci_scratchpad_free(struct xhci_softc *);
int xhci_softdev_alloc(struct xhci_softc *, uint8_t);
void xhci_softdev_free(struct xhci_softc *, uint8_t);
-int xhci_ring_alloc(struct xhci_softc *, struct xhci_ring *, size_t);
+int xhci_ring_alloc(struct xhci_softc *, struct xhci_ring *, size_t,
+ size_t);
void xhci_ring_free(struct xhci_softc *, struct xhci_ring *);
void xhci_ring_reset(struct xhci_softc *, struct xhci_ring *);
struct xhci_trb *xhci_ring_dequeue(struct xhci_softc *, struct xhci_ring *,
@@ -206,6 +207,68 @@ xhci_dump_trb(struct xhci_trb *trb)
}
#endif
+int usbd_dma_contig_alloc(struct usbd_bus *, struct usbd_dma_info *,
+ void **, bus_size_t, bus_size_t, bus_size_t);
+void usbd_dma_contig_free(struct usbd_bus *, struct usbd_dma_info *);
+
+int
+usbd_dma_contig_alloc(struct usbd_bus *bus, struct usbd_dma_info *dma,
+ void **kvap, bus_size_t size, bus_size_t alignment, bus_size_t boundary)
+{
+ int error;
+
+ dma->tag = bus->dmatag;
+ dma->size = size;
+
+ error = bus_dmamap_create(dma->tag, size, 1, size, boundary,
+ BUS_DMA_NOWAIT, &dma->map);
+ if (error != 0)
+ goto fail;
+
+ error = bus_dmamem_alloc(dma->tag, size, alignment, boundary, &dma->seg,
+ 1, &dma->nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
+ if (error != 0)
+ goto fail;
+
+ error = bus_dmamem_map(dma->tag, &dma->seg, 1, size, &dma->vaddr,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+ if (error != 0)
+ goto fail;
+
+ error = bus_dmamap_load_raw(dma->tag, dma->map, &dma->seg, 1, size,
+ BUS_DMA_NOWAIT);
+ if (error != 0)
+ goto fail;
+
+ bus_dmamap_sync(dma->tag, dma->map, 0, size, BUS_DMASYNC_PREWRITE);
+
+ dma->paddr = dma->map->dm_segs[0].ds_addr;
+ if (kvap != NULL)
+ *kvap = dma->vaddr;
+
+ return (0);
+
+fail: usbd_dma_contig_free(bus, dma);
+ return (error);
+}
+
+void
+usbd_dma_contig_free(struct usbd_bus *bus, struct usbd_dma_info *dma)
+{
+ if (dma->map != NULL) {
+ if (dma->vaddr != NULL) {
+ bus_dmamap_sync(bus->dmatag, dma->map, 0, dma->size,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(bus->dmatag, dma->map);
+ bus_dmamem_unmap(bus->dmatag, dma->vaddr, dma->size);
+ bus_dmamem_free(bus->dmatag, &dma->seg, 1);
+ dma->vaddr = NULL;
+ }
+ bus_dmamap_destroy(bus->dmatag, dma->map);
+ dma->map = NULL;
+ }
+}
+
int
xhci_init(struct xhci_softc *sc)
{
@@ -266,56 +329,50 @@ xhci_init(struct xhci_softc *sc)
DPRINTF(("%s: %d ports and %d slots\n", DEVNAME(sc), sc->sc_noport,
sc->sc_noslot));
- /*
- * Section 6.1 - Device Context Base Address Array
- * shall be aligned to a 64 byte boundary.
- */
- sc->sc_dcbaa.size = (sc->sc_noslot + 1) * sizeof(uint64_t);
- error = usb_allocmem(&sc->sc_bus, sc->sc_dcbaa.size, 64,
- &sc->sc_dcbaa.dma);
+ /* Setup Device Context Base Address Array. */
+ error = usbd_dma_contig_alloc(&sc->sc_bus, &sc->sc_dcbaa.dma,
+ (void **)&sc->sc_dcbaa.segs, (sc->sc_noslot + 1) * sizeof(uint64_t),
+ XHCI_DCBAA_ALIGN, sc->sc_pagesize);
if (error)
return (ENOMEM);
- sc->sc_dcbaa.segs = KERNADDR(&sc->sc_dcbaa.dma, 0);
- memset(sc->sc_dcbaa.segs, 0, sc->sc_dcbaa.size);
- usb_syncmem(&sc->sc_dcbaa.dma, 0, sc->sc_dcbaa.size,
- BUS_DMASYNC_PREWRITE);
/* Setup command ring. */
- error = xhci_ring_alloc(sc, &sc->sc_cmd_ring, XHCI_MAX_COMMANDS);
+ error = xhci_ring_alloc(sc, &sc->sc_cmd_ring, XHCI_MAX_CMDS,
+ XHCI_CMDS_RING_ALIGN);
if (error) {
printf("%s: could not allocate command ring.\n", DEVNAME(sc));
- usb_freemem(&sc->sc_bus, &sc->sc_dcbaa.dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_dcbaa.dma);
return (error);
}
/* Setup one event ring and its segment table (ERST). */
- error = xhci_ring_alloc(sc, &sc->sc_evt_ring, XHCI_MAX_EVENTS);
+ error = xhci_ring_alloc(sc, &sc->sc_evt_ring, XHCI_MAX_EVTS,
+ XHCI_EVTS_RING_ALIGN);
if (error) {
printf("%s: could not allocate event ring.\n", DEVNAME(sc));
xhci_ring_free(sc, &sc->sc_cmd_ring);
- usb_freemem(&sc->sc_bus, &sc->sc_dcbaa.dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_dcbaa.dma);
return (error);
}
/* Allocate the required entry for the segment table. */
- sc->sc_erst.size = 1 * sizeof(struct xhci_erseg);
- error = usb_allocmem(&sc->sc_bus, sc->sc_erst.size, 64,
- &sc->sc_erst.dma);
+ error = usbd_dma_contig_alloc(&sc->sc_bus, &sc->sc_erst.dma,
+ (void **)&sc->sc_erst.segs, sizeof(struct xhci_erseg),
+ XHCI_ERST_ALIGN, XHCI_ERST_BOUNDARY);
if (error) {
printf("%s: could not allocate segment table.\n", DEVNAME(sc));
xhci_ring_free(sc, &sc->sc_evt_ring);
xhci_ring_free(sc, &sc->sc_cmd_ring);
- usb_freemem(&sc->sc_bus, &sc->sc_dcbaa.dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_dcbaa.dma);
return (ENOMEM);
}
- sc->sc_erst.segs = KERNADDR(&sc->sc_erst.dma, 0);
/* Set our ring address and size in its corresponding segment. */
- sc->sc_erst.segs[0].er_addr = htole64(DMAADDR(&sc->sc_evt_ring.dma, 0));
- sc->sc_erst.segs[0].er_size = htole32(XHCI_MAX_EVENTS);
+ sc->sc_erst.segs[0].er_addr = htole64(sc->sc_evt_ring.dma.paddr);
+ sc->sc_erst.segs[0].er_size = htole32(XHCI_MAX_EVTS);
sc->sc_erst.segs[0].er_rsvd = 0;
- usb_syncmem(&sc->sc_erst.dma, 0, sc->sc_erst.size,
- BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->sc_erst.dma.tag, sc->sc_erst.dma.map, 0,
+ sc->sc_erst.dma.size, BUS_DMASYNC_PREWRITE);
/* Get the number of scratch pages and configure them if necessary. */
hcr = XREAD4(sc, XHCI_HCSPARAMS2);
@@ -324,10 +381,10 @@ xhci_init(struct xhci_softc *sc)
if (npage > 0 && xhci_scratchpad_alloc(sc, npage)) {
printf("%s: could not allocate scratchpad.\n", DEVNAME(sc));
- usb_freemem(&sc->sc_bus, &sc->sc_erst.dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_erst.dma);
xhci_ring_free(sc, &sc->sc_evt_ring);
xhci_ring_free(sc, &sc->sc_cmd_ring);
- usb_freemem(&sc->sc_bus, &sc->sc_dcbaa.dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_dcbaa.dma);
return (ENOMEM);
}
@@ -348,7 +405,7 @@ xhci_config(struct xhci_softc *sc)
XOWRITE4(sc, XHCI_CONFIG, hcr | sc->sc_noslot);
/* Set the device context base array address. */
- paddr = (uint64_t)DMAADDR(&sc->sc_dcbaa.dma, 0);
+ paddr = (uint64_t)sc->sc_dcbaa.dma.paddr;
XOWRITE4(sc, XHCI_DCBAAP_LO, (uint32_t)paddr);
XOWRITE4(sc, XHCI_DCBAAP_HI, (uint32_t)(paddr >> 32));
@@ -356,7 +413,7 @@ xhci_config(struct xhci_softc *sc)
XOREAD4(sc, XHCI_DCBAAP_HI), XOREAD4(sc, XHCI_DCBAAP_LO)));
/* Set the command ring address. */
- paddr = (uint64_t)DMAADDR(&sc->sc_cmd_ring.dma, 0);
+ paddr = (uint64_t)sc->sc_cmd_ring.dma.paddr;
XOWRITE4(sc, XHCI_CRCR_LO, ((uint32_t)paddr) | XHCI_CRCR_LO_RCS);
XOWRITE4(sc, XHCI_CRCR_HI, (uint32_t)(paddr >> 32));
@@ -367,7 +424,7 @@ xhci_config(struct xhci_softc *sc)
XRWRITE4(sc, XHCI_ERSTSZ(0), XHCI_ERSTS_SET(1));
/* Set the segment table address. */
- paddr = (uint64_t)DMAADDR(&sc->sc_erst.dma, 0);
+ paddr = (uint64_t)sc->sc_erst.dma.paddr;
XRWRITE4(sc, XHCI_ERSTBA_LO(0), (uint32_t)paddr);
XRWRITE4(sc, XHCI_ERSTBA_HI(0), (uint32_t)(paddr >> 32));
@@ -375,7 +432,7 @@ xhci_config(struct xhci_softc *sc)
XRREAD4(sc, XHCI_ERSTBA_HI(0)), XRREAD4(sc, XHCI_ERSTBA_LO(0))));
/* Set the ring dequeue address. */
- paddr = (uint64_t)DMAADDR(&sc->sc_evt_ring.dma, 0);
+ paddr = (uint64_t)sc->sc_evt_ring.dma.paddr;
XRWRITE4(sc, XHCI_ERDP_LO(0), (uint32_t)paddr);
XRWRITE4(sc, XHCI_ERDP_HI(0), (uint32_t)(paddr >> 32));
@@ -436,10 +493,10 @@ xhci_detach(struct device *self, int flags)
if (sc->sc_spad.npage > 0)
xhci_scratchpad_free(sc);
- usb_freemem(&sc->sc_bus, &sc->sc_erst.dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_erst.dma);
xhci_ring_free(sc, &sc->sc_evt_ring);
xhci_ring_free(sc, &sc->sc_cmd_ring);
- usb_freemem(&sc->sc_bus, &sc->sc_dcbaa.dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_dcbaa.dma);
return (0);
}
@@ -665,7 +722,7 @@ xhci_event_xfer(struct xhci_softc *sc, uint64_t paddr, uint32_t status,
code = XHCI_TRB_GET_CODE(status);
remain = XHCI_TRB_REMAIN(status);
- trb_idx = (paddr - DMAADDR(&xp->ring.dma, 0)) / sizeof(struct xhci_trb);
+ trb_idx = (paddr - xp->ring.dma.paddr) / sizeof(struct xhci_trb);
if (trb_idx < 0 || trb_idx >= xp->ring.ntrb) {
printf("%s: wrong trb index (%d) max is %zu\n", DEVNAME(sc),
trb_idx, xp->ring.ntrb - 1);
@@ -753,7 +810,7 @@ xhci_event_command(struct xhci_softc *sc, uint64_t paddr)
uint8_t dci, slot;
int i, trb_idx;
- trb_idx = (paddr - DMAADDR(&sc->sc_cmd_ring.dma, 0)) / sizeof(*trb);
+ trb_idx = (paddr - sc->sc_cmd_ring.dma.paddr) / sizeof(*trb);
if (trb_idx < 0 || trb_idx >= sc->sc_cmd_ring.ntrb) {
printf("%s: wrong trb index (%d) max is %zu\n", DEVNAME(sc),
trb_idx, sc->sc_cmd_ring.ntrb - 1);
@@ -785,7 +842,7 @@ xhci_event_command(struct xhci_softc *sc, uint64_t paddr)
xp->halted = 0;
/* Complete all pending transfers. */
- for (i = 0; i < XHCI_MAX_TRANSFERS; i++) {
+ for (i = 0; i < XHCI_MAX_XFER; i++) {
xfer = xp->pending_xfers[i];
if (xfer != NULL && xfer->done == 0) {
if (xfer->status != USBD_STALLED)
@@ -1135,7 +1192,8 @@ xhci_context_setup(struct xhci_softc *sc, struct usbd_pipe *pipe)
/* Unmask the slot context */
sdev->input_ctx->add_flags |= htole32(XHCI_INCTX_MASK_DCI(0));
- usb_syncmem(&sdev->ictx_dma, 0, sc->sc_pagesize, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sdev->ictx_dma.tag, sdev->ictx_dma.map, 0,
+ sc->sc_pagesize, BUS_DMASYNC_PREWRITE);
}
int
@@ -1153,7 +1211,7 @@ xhci_pipe_init(struct xhci_softc *sc, struct usbd_pipe *pipe)
pipe->endpoint->edesc->bEndpointAddress);
#endif
- if (xhci_ring_alloc(sc, &xp->ring, XHCI_MAX_TRANSFERS))
+ if (xhci_ring_alloc(sc, &xp->ring, XHCI_MAX_XFER, XHCI_XFER_RING_ALIGN))
return (ENOMEM);
xp->free_trbs = xp->ring.ntrb;
@@ -1174,10 +1232,10 @@ xhci_pipe_init(struct xhci_softc *sc, struct usbd_pipe *pipe)
* descriptor.
*/
error = xhci_cmd_set_address(sc, xp->slot,
- DMAADDR(&sdev->ictx_dma, 0), XHCI_TRB_BSR);
+ sdev->ictx_dma.paddr, XHCI_TRB_BSR);
} else {
error = xhci_cmd_configure_ep(sc, xp->slot,
- DMAADDR(&sdev->ictx_dma, 0));
+ sdev->ictx_dma.paddr);
}
if (error) {
@@ -1218,9 +1276,10 @@ xhci_pipe_close(struct usbd_pipe *pipe)
/* Clear the Endpoint Context */
memset(sdev->ep_ctx[xp->dci - 1], 0, sizeof(struct xhci_epctx));
- usb_syncmem(&sdev->ictx_dma, 0, sc->sc_pagesize, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sdev->ictx_dma.tag, sdev->ictx_dma.map, 0,
+ sc->sc_pagesize, BUS_DMASYNC_PREWRITE);
- if (xhci_cmd_configure_ep(sc, xp->slot, DMAADDR(&sdev->ictx_dma, 0)))
+ if (xhci_cmd_configure_ep(sc, xp->slot, sdev->ictx_dma.paddr))
DPRINTF(("%s: error clearing ep (%d)\n", DEVNAME(sc), xp->dci));
xhci_ring_free(sc, &xp->ring);
@@ -1258,19 +1317,18 @@ xhci_setaddr(struct usbd_device *dev, int addr)
xhci_context_setup(sc, dev->default_pipe);
- error = xhci_cmd_set_address(sc, xp->slot,
- DMAADDR(&sdev->ictx_dma, 0), 0);
+ error = xhci_cmd_set_address(sc, xp->slot, sdev->ictx_dma.paddr, 0);
#ifdef XHCI_DEBUG
if (error == 0) {
struct xhci_sctx *sctx;
uint8_t addr;
- usb_syncmem(&sdev->octx_dma, 0, sc->sc_pagesize,
- BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(sdev->octx_dma.tag, sdev->octx_dma.map, 0,
+ sc->sc_pagesize, BUS_DMASYNC_POSTREAD);
/* Get output slot context. */
- sctx = KERNADDR(&sdev->octx_dma, 0);
+ sctx = (struct xhci_sctx *)sdev->octx_dma.vaddr;
addr = XHCI_SCTX_DEV_ADDR(letoh32(sctx->state));
error = (addr == 0);
@@ -1300,35 +1358,33 @@ xhci_scratchpad_alloc(struct xhci_softc *sc, int npage)
int error, i;
/* Allocate the required entry for the table. */
- error = usb_allocmem(&sc->sc_bus, npage * sizeof(uint64_t), 64,
- &sc->sc_spad.table_dma);
+ error = usbd_dma_contig_alloc(&sc->sc_bus, &sc->sc_spad.table_dma,
+ (void **)&pte, npage * sizeof(uint64_t), XHCI_SPAD_TABLE_ALIGN,
+ sc->sc_pagesize);
if (error)
return (ENOMEM);
- pte = KERNADDR(&sc->sc_spad.table_dma, 0);
- /* Alloccate space for the pages. */
- error = usb_allocmem(&sc->sc_bus, npage * sc->sc_pagesize,
- sc->sc_pagesize, &sc->sc_spad.pages_dma);
+ /* Allocate pages. XXX does not need to be contiguous. */
+ error = usbd_dma_contig_alloc(&sc->sc_bus, &sc->sc_spad.pages_dma,
+ NULL, npage * sc->sc_pagesize, sc->sc_pagesize, 0);
if (error) {
- usb_freemem(&sc->sc_bus, &sc->sc_spad.table_dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_spad.table_dma);
return (ENOMEM);
}
- memset(KERNADDR(&sc->sc_spad.pages_dma, 0), 0, npage * sc->sc_pagesize);
- usb_syncmem(&sc->sc_spad.pages_dma, 0, npage * sc->sc_pagesize,
- BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
for (i = 0; i < npage; i++) {
pte[i] = htole64(
- DMAADDR(&sc->sc_spad.pages_dma, i * sc->sc_pagesize)
+ sc->sc_spad.pages_dma.paddr + (i * sc->sc_pagesize)
);
}
- usb_syncmem(&sc->sc_spad.table_dma, 0, npage * sizeof(uint64_t),
- BUS_DMASYNC_PREWRITE);
+
+ bus_dmamap_sync(sc->sc_spad.table_dma.tag, sc->sc_spad.table_dma.map, 0,
+ npage * sizeof(uint64_t), BUS_DMASYNC_PREWRITE);
/* Entry 0 points to the table of scratchpad pointers. */
- sc->sc_dcbaa.segs[0] = htole64(DMAADDR(&sc->sc_spad.table_dma, 0));
- usb_syncmem(&sc->sc_dcbaa.dma, 0, sizeof(uint64_t),
- BUS_DMASYNC_PREWRITE);
+ sc->sc_dcbaa.segs[0] = htole64(sc->sc_spad.table_dma.paddr);
+ bus_dmamap_sync(sc->sc_dcbaa.dma.tag, sc->sc_dcbaa.dma.map, 0,
+ sizeof(uint64_t), BUS_DMASYNC_PREWRITE);
sc->sc_spad.npage = npage;
@@ -1339,25 +1395,27 @@ void
xhci_scratchpad_free(struct xhci_softc *sc)
{
sc->sc_dcbaa.segs[0] = 0;
- usb_syncmem(&sc->sc_dcbaa.dma, 0, sizeof(uint64_t),
- BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->sc_dcbaa.dma.tag, sc->sc_dcbaa.dma.map, 0,
+ sizeof(uint64_t), BUS_DMASYNC_PREWRITE);
- usb_freemem(&sc->sc_bus, &sc->sc_spad.pages_dma);
- usb_freemem(&sc->sc_bus, &sc->sc_spad.table_dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_spad.pages_dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sc->sc_spad.table_dma);
}
-
int
-xhci_ring_alloc(struct xhci_softc *sc, struct xhci_ring *ring, size_t ntrb)
+xhci_ring_alloc(struct xhci_softc *sc, struct xhci_ring *ring, size_t ntrb,
+ size_t alignment)
{
size_t size;
+ int error;
size = ntrb * sizeof(struct xhci_trb);
- if (usb_allocmem(&sc->sc_bus, size, 16, &ring->dma) != 0)
- return (ENOMEM);
+ error = usbd_dma_contig_alloc(&sc->sc_bus, &ring->dma,
+ (void **)&ring->trbs, size, alignment, XHCI_RING_BOUNDARY);
+ if (error)
+ return (error);
- ring->trbs = KERNADDR(&ring->dma, 0);
ring->ntrb = ntrb;
xhci_ring_reset(sc, ring);
@@ -1368,7 +1426,7 @@ xhci_ring_alloc(struct xhci_softc *sc, struct xhci_ring *ring, size_t ntrb)
void
xhci_ring_free(struct xhci_softc *sc, struct xhci_ring *ring)
{
- usb_freemem(&sc->sc_bus, &ring->dma);
+ usbd_dma_contig_free(&sc->sc_bus, &ring->dma);
}
void
@@ -1390,10 +1448,11 @@ xhci_ring_reset(struct xhci_softc *sc, struct xhci_ring *ring)
if (ring != &sc->sc_evt_ring) {
struct xhci_trb *trb = &ring->trbs[ring->ntrb - 1];
- trb->trb_paddr = htole64(DMAADDR(&ring->dma, 0));
+ trb->trb_paddr = htole64(ring->dma.paddr);
trb->trb_flags = htole32(XHCI_TRB_TYPE_LINK | XHCI_TRB_LINKSEG);
}
- usb_syncmem(&ring->dma, 0, size, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(ring->dma.tag, ring->dma.map, 0, size,
+ BUS_DMASYNC_PREWRITE);
}
struct xhci_trb*
@@ -1404,8 +1463,8 @@ xhci_ring_dequeue(struct xhci_softc *sc, struct xhci_ring *ring, int cons)
KASSERT(idx < ring->ntrb);
- usb_syncmem(&ring->dma, idx * sizeof(struct xhci_trb),
- sizeof(struct xhci_trb), BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(ring->dma.tag, ring->dma.map, idx * sizeof(*trb),
+ sizeof(*trb), BUS_DMASYNC_POSTREAD);
trb = &ring->trbs[idx];
@@ -1422,8 +1481,9 @@ xhci_ring_dequeue(struct xhci_softc *sc, struct xhci_ring *ring, int cons)
else
ring->trbs[idx].trb_flags &= ~htole32(XHCI_TRB_CYCLE);
- usb_syncmem(&ring->dma, sizeof(struct xhci_trb) * idx,
- sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(ring->dma.tag, ring->dma.map,
+ sizeof(struct xhci_trb) * idx, sizeof(struct xhci_trb),
+ BUS_DMASYNC_PREWRITE);
ring->index = 0;
ring->toggle ^= 1;
@@ -1466,8 +1526,10 @@ xhci_command_submit(struct xhci_softc *sc, struct xhci_trb *trb0, int timeout)
if (trb == NULL)
return (EAGAIN);
memcpy(trb, trb0, sizeof(struct xhci_trb));
- usb_syncmem(&sc->sc_cmd_ring.dma, TRBOFF(sc->sc_cmd_ring, trb),
- sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->sc_cmd_ring.dma.tag, sc->sc_cmd_ring.dma.map,
+ TRBOFF(sc->sc_cmd_ring, trb), sizeof(struct xhci_trb),
+ BUS_DMASYNC_PREWRITE);
+
if (timeout == 0) {
XDWRITE4(sc, XHCI_DOORBELL(0), 0);
@@ -1683,43 +1745,42 @@ xhci_softdev_alloc(struct xhci_softc *sc, uint8_t slot)
{
struct xhci_soft_dev *sdev = &sc->sc_sdevs[slot];
int i, error;
+ uint8_t *kva;
/*
* Setup input context. Even with 64 byte context size, it
* fits into the smallest supported page size, so use that.
*/
- error = usb_allocmem(&sc->sc_bus, sc->sc_pagesize, sc->sc_pagesize,
- &sdev->ictx_dma);
+ error = usbd_dma_contig_alloc(&sc->sc_bus, &sdev->ictx_dma,
+ (void **)&kva, sc->sc_pagesize, XHCI_ICTX_ALIGN, sc->sc_pagesize);
if (error)
return (ENOMEM);
- memset(KERNADDR(&sdev->ictx_dma, 0), 0, sc->sc_pagesize);
- sdev->input_ctx = KERNADDR(&sdev->ictx_dma, 0);
- sdev->slot_ctx = KERNADDR(&sdev->ictx_dma, sc->sc_ctxsize);
+ sdev->input_ctx = (struct xhci_inctx *)kva;
+ sdev->slot_ctx = (struct xhci_sctx *)(kva + sc->sc_ctxsize);
for (i = 0; i < 31; i++)
sdev->ep_ctx[i] =
- KERNADDR(&sdev->ictx_dma, (i + 2) * sc->sc_ctxsize);
+ (struct xhci_epctx *)(kva + (i + 2) * sc->sc_ctxsize);
DPRINTF(("%s: dev %d, input=%p slot=%p ep0=%p\n", DEVNAME(sc),
slot, sdev->input_ctx, sdev->slot_ctx, sdev->ep_ctx[0]));
/* Setup output context */
- error = usb_allocmem(&sc->sc_bus, sc->sc_pagesize, sc->sc_pagesize,
- &sdev->octx_dma);
+ error = usbd_dma_contig_alloc(&sc->sc_bus, &sdev->octx_dma, NULL,
+ sc->sc_pagesize, XHCI_OCTX_ALIGN, sc->sc_pagesize);
if (error) {
- usb_freemem(&sc->sc_bus, &sdev->ictx_dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sdev->ictx_dma);
return (ENOMEM);
}
- memset(KERNADDR(&sdev->octx_dma, 0), 0, sc->sc_pagesize);
memset(&sdev->pipes, 0, sizeof(sdev->pipes));
DPRINTF(("%s: dev %d, setting DCBAA to 0x%016llx\n", DEVNAME(sc),
- slot, (long long)DMAADDR(&sdev->octx_dma, 0)));
+ slot, (long long)sdev->octx_dma.paddr));
- sc->sc_dcbaa.segs[slot] = htole64(DMAADDR(&sdev->octx_dma, 0));
- usb_syncmem(&sc->sc_dcbaa.dma, slot * sizeof(uint64_t),
- sizeof(uint64_t), BUS_DMASYNC_PREWRITE);
+ sc->sc_dcbaa.segs[slot] = htole64(sdev->octx_dma.paddr);
+ bus_dmamap_sync(sc->sc_dcbaa.dma.tag, sc->sc_dcbaa.dma.map,
+ slot * sizeof(uint64_t), sizeof(uint64_t), BUS_DMASYNC_PREWRITE);
return (0);
}
@@ -1730,11 +1791,11 @@ xhci_softdev_free(struct xhci_softc *sc, uint8_t slot)
struct xhci_soft_dev *sdev = &sc->sc_sdevs[slot];
sc->sc_dcbaa.segs[slot] = 0;
- usb_syncmem(&sc->sc_dcbaa.dma, slot * sizeof(uint64_t),
- sizeof(uint64_t), BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->sc_dcbaa.dma.tag, sc->sc_dcbaa.dma.map,
+ slot * sizeof(uint64_t), sizeof(uint64_t), BUS_DMASYNC_PREWRITE);
- usb_freemem(&sc->sc_bus, &sdev->octx_dma);
- usb_freemem(&sc->sc_bus, &sdev->ictx_dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sdev->octx_dma);
+ usbd_dma_contig_free(&sc->sc_bus, &sdev->ictx_dma);
memset(sdev, 0, sizeof(struct xhci_soft_dev));
}
@@ -2306,8 +2367,9 @@ xhci_device_ctrl_start(struct usbd_xfer *xfer)
trb0->trb_flags |= htole32(toggle0);
- usb_syncmem(&xp->ring.dma, TRBOFF(xp->ring, trb0),
- 3 * sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(xp->ring.dma.tag, xp->ring.dma.map,
+ TRBOFF(xp->ring, trb0), 3 * sizeof(struct xhci_trb),
+ BUS_DMASYNC_PREWRITE);
s = splusb();
XDWRITE4(sc, XHCI_DOORBELL(xp->slot), xp->dci);
@@ -2371,8 +2433,9 @@ xhci_device_generic_start(struct usbd_xfer *xfer)
if (usbd_xfer_isread(xfer))
trb->trb_flags |= htole32(XHCI_TRB_ISP);
- usb_syncmem(&xp->ring.dma, TRBOFF(xp->ring, trb),
- sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(xp->ring.dma.tag, xp->ring.dma.map,
+ TRBOFF(xp->ring, trb), sizeof(struct xhci_trb),
+ BUS_DMASYNC_PREWRITE);
s = splusb();
XDWRITE4(sc, XHCI_DOORBELL(xp->slot), xp->dci);